chore: reorganize into polyglot monorepo (workshop)
- Move bigmind/ -> mcp/bigmind/ - Move webscraper/ -> mcp/webscraper/ - Move mss-failsafe/ -> java/mss-failsafe/ - Move Wellmann-Shop/ -> java/wellmann-shop/ (normalize to kebab-case) - Add .roo/ IDE config files to tracking - Add plans/REPO_STRATEGY.md (monorepo strategy document) - Expand .gitignore: Java/Maven, Node/TS, coverage, uv.lock - Rewrite README.md as navigation index - Update .roo/mcp.json webscraper path to mcp/webscraper/
This commit is contained in:
+31
-6
@@ -1,4 +1,4 @@
|
|||||||
# Python
|
# ── Python ────────────────────────────────────────────────────────────────────
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
*$py.class
|
*$py.class
|
||||||
@@ -31,19 +31,44 @@ ENV/
|
|||||||
env.bak/
|
env.bak/
|
||||||
venv.bak/
|
venv.bak/
|
||||||
|
|
||||||
# IDE
|
# uv
|
||||||
|
uv.lock
|
||||||
|
|
||||||
|
# Coverage
|
||||||
|
.coverage
|
||||||
|
coverage.xml
|
||||||
|
htmlcov/
|
||||||
|
|
||||||
|
# ── Java / Maven ──────────────────────────────────────────────────────────────
|
||||||
|
target/
|
||||||
|
*.class
|
||||||
|
*.war
|
||||||
|
*.jar
|
||||||
|
*.ear
|
||||||
|
*.nar
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings/
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
# ── Node / TypeScript (future) ────────────────────────────────────────────────
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
*.js.map
|
||||||
|
|
||||||
|
# ── IDE ───────────────────────────────────────────────────────────────────────
|
||||||
.vscode/
|
.vscode/
|
||||||
.idea/
|
.idea/
|
||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.swo
|
||||||
|
|
||||||
# OS
|
# ── OS ────────────────────────────────────────────────────────────────────────
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
# Databases
|
# ── Databases ─────────────────────────────────────────────────────────────────
|
||||||
*.db
|
*.db
|
||||||
*.sqlite3
|
*.sqlite3
|
||||||
|
|
||||||
# Logs
|
# ── Logs ──────────────────────────────────────────────────────────────────────
|
||||||
*.log
|
*.log
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"git": {
|
||||||
|
"command": "uvx",
|
||||||
|
"args": [
|
||||||
|
"mcp-server-git",
|
||||||
|
"--repository",
|
||||||
|
"/home/pplate/pi_mcps/"
|
||||||
|
],
|
||||||
|
"alwaysAllow": [
|
||||||
|
"*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"filesystem": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@modelcontextprotocol/server-filesystem",
|
||||||
|
"/home/pplate/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"webscraper": {
|
||||||
|
"command": "uv",
|
||||||
|
"args": [
|
||||||
|
"run",
|
||||||
|
"--directory",
|
||||||
|
"/home/pplate/pi_mcps/mcp/webscraper",
|
||||||
|
"src/server.py"
|
||||||
|
],
|
||||||
|
"alwaysAllow": [
|
||||||
|
"webscraper_fetch"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Architect Mode Behavior — Roo Code
|
||||||
|
|
||||||
|
## Planning Process
|
||||||
|
1. **Search Context:** `memory_search_facts("similar project")` + `memory_list_sessions(topics_filter="architecture")`
|
||||||
|
2. **Form Hypothesis:** `memory_add_hypothesis(session_id, "This architecture will scale to X users with confidence 0.7")`
|
||||||
|
3. **Create Assessment:** Write markdown assessment.md with requirements, risks, alternatives
|
||||||
|
4. **Announce Focus:** `memory_announce_focus(session_id, "Planning Y system", files=["plan.md"], ide_hint="VS Code")`
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
- **Break Down:** Large tasks → subtasks with MCP servers (Docker, Gitea, Ollama)
|
||||||
|
- **Homelab Focus:** Leverage TrueNAS Docker for services, 1.2TB SSD for VMs/DBs
|
||||||
|
- **Token Efficiency:** Reference past architectures from memory, log savings
|
||||||
|
|
||||||
|
## After Planning
|
||||||
|
1. **Store Decision:** `memory_store_fact("decision", "Chose Z architecture for reasons A B C")`
|
||||||
|
2. **Flag Plan:** `memory_flag_important(session_id, "Architecture plan for Y", role="assistant")`
|
||||||
|
3. **Resolve Hypothesis:** Update based on plan validation
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Ask Mode Behavior — Roo Code
|
||||||
|
|
||||||
|
## Before Answering Any Question
|
||||||
|
1. **Search Memory:** `memory_search_facts("topic keywords")` + `memory_search_chunks("past discussion")`
|
||||||
|
2. **Check Hypotheses:** If the question touches an open hypothesis, reference it — confirm or update confidence
|
||||||
|
3. **Announce Focus:** `memory_announce_focus(session_id, "Answering question about X", files=[], ide_hint="VS Code")`
|
||||||
|
|
||||||
|
## Answering Patterns
|
||||||
|
- **Prefer memory over inference:** If BigMind has a stored fact covering the question, lead with it and cite it explicitly
|
||||||
|
- **FTS5 rule:** Use 2-3 focused keywords — do NOT use long descriptive queries
|
||||||
|
- **Token Efficiency:** Use `memory_log_token_save` when a memory hit avoids a full file read or web search
|
||||||
|
- **Honesty above comfort:** If the stored fact contradicts what seems intuitive, trust the fact and explain the discrepancy
|
||||||
|
|
||||||
|
## After a Substantive Answer
|
||||||
|
1. **Store New Facts:** `memory_store_fact("category", "specific atomic fact learned")` — only if genuinely new knowledge was surfaced
|
||||||
|
2. **Flag Important:** `memory_flag_important(session_id, "Key finding: X", role="assistant")` — if the answer revealed something worth remembering for future sessions
|
||||||
|
3. **Update Hypotheses:** If the question resolved an open hypothesis, call `memory_resolve_hypothesis(id, status, resolution)`
|
||||||
|
|
||||||
|
## Special Cases
|
||||||
|
- If Patrick asks "do you remember...": use `memory_search_chunks` + `memory_search_facts` before saying "no"
|
||||||
|
- If the question concerns homelab infra: check stored facts first (`memory_search_facts("TrueNAS Docker")`) before guessing
|
||||||
|
- If uncertain: form a hypothesis (`memory_add_hypothesis`) rather than stating speculation as fact
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Code Mode Behavior — Roo Code
|
||||||
|
|
||||||
|
## Before Writing Code
|
||||||
|
1. **Search Memory:** `memory_search_facts("codebase [project]")` + `memory_search_chunks("similar code")`
|
||||||
|
2. **Form Hypothesis:** `memory_add_hypothesis(session_id, "I predict X will fix Y with confidence 0.8")`
|
||||||
|
3. **Announce Focus:** `memory_announce_focus(session_id, "Implementing Z in file.py", files=["file.py"], ide_hint="VS Code")`
|
||||||
|
|
||||||
|
## Coding Patterns
|
||||||
|
- **Python:** Use uv for dependencies, FastMCP for MCP servers, pytest for tests
|
||||||
|
- **Java:** Maven for Paisy projects, Spring Boot patterns
|
||||||
|
- **Testing:** Always write tests first, mock external calls
|
||||||
|
- **Token Efficiency:** Use `memory_log_token_save` when reusing code from memory
|
||||||
|
|
||||||
|
## After Code Changes
|
||||||
|
1. **Store Fact:** `memory_store_fact("codebase", "New function X in file.py does Y")`
|
||||||
|
2. **Flag Important:** `memory_flag_important(session_id, "Code review: implemented Z", role="assistant")`
|
||||||
|
3. **Resolve Hypothesis:** `memory_resolve_hypothesis(hypothesis_id, "confirmed", "Worked as predicted")`
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
- If code fails, form new hypothesis: "Bug might be in dependency version"
|
||||||
|
- Search: `memory_search_chunks("similar error")`
|
||||||
|
- Debug systematically, log token savings from targeted searches
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Debug Mode Behavior — Roo Code
|
||||||
|
|
||||||
|
## Debugging Process
|
||||||
|
1. **Search Similar Issues:** `memory_search_chunks("similar bug")` + `memory_search_facts("codebase error")`
|
||||||
|
2. **Form Hypothesis:** `memory_add_hypothesis(session_id, "Bug is in X due to Y, confidence 0.6")`
|
||||||
|
3. **Announce Focus:** `memory_announce_focus(session_id, "Debugging Z in file.py", files=["file.py"], ide_hint="VS Code")`
|
||||||
|
4. **Systematic Steps:** Add logging, analyze stack traces, test incrementally
|
||||||
|
|
||||||
|
## Tools & Patterns
|
||||||
|
- **MCP Leverage:** Use mcp-homelab-shell for quick tests, mcp-homelab-docker for container logs
|
||||||
|
- **Homelab:** Check Ollama models, TrueNAS VMs if relevant
|
||||||
|
- **Token Efficiency:** Search memory for past fixes before reading full logs
|
||||||
|
|
||||||
|
## After Resolution
|
||||||
|
1. **Store Fix:** `memory_store_fact("codebase", "Fixed bug in X by doing Y")`
|
||||||
|
2. **Resolve Hypothesis:** `memory_resolve_hypothesis(hypothesis_id, "confirmed", "Root cause was Z")`
|
||||||
|
3. **Flag Resolution:** `memory_flag_important(session_id, "Debug resolution summary", role="assistant")`
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Orchestrator Mode Behavior — Roo Code
|
||||||
|
|
||||||
|
## Before Breaking Down a Task
|
||||||
|
1. **Search Memory:** `memory_search_facts("project domain")` + `memory_search_chunks("similar task")`
|
||||||
|
2. **Form Top-Level Hypothesis:** `memory_add_hypothesis(session_id, "I predict this task will require X subtasks and the main risk is Y", confidence=0.7)`
|
||||||
|
3. **Announce Focus:** `memory_announce_focus(session_id, "Orchestrating task: Z", files=["files to be touched"], ide_hint="VS Code")`
|
||||||
|
|
||||||
|
## Orchestration Patterns
|
||||||
|
- **One hypothesis per subtask:** Before delegating each subtask, form a specific hypothesis about what the subtask will find or produce
|
||||||
|
- **Store decisions immediately:** After each subtask completes, call `memory_store_fact` with what was decided or built — don't batch at the end
|
||||||
|
- **Token Efficiency:** Use `memory_log_token_save` when memory recall replaces reading files or running commands to gather context
|
||||||
|
- **Conflict detection:** Before delegating work that touches files, call `memory_get_active_sessions()` to check for conflicts
|
||||||
|
|
||||||
|
## Delegating Subtasks
|
||||||
|
- Pass enough BigMind context to sub-modes so they don't repeat searches
|
||||||
|
- Specify `session_id` and relevant stored facts in the delegation message
|
||||||
|
- Each delegated mode must still call `memory_announce_focus` for the files it will touch
|
||||||
|
|
||||||
|
## After Full Task Completion
|
||||||
|
1. **Resolve All Hypotheses:** Call `memory_resolve_hypothesis` for every hypothesis opened during orchestration
|
||||||
|
2. **Store Summary Fact:** `memory_store_fact("architecture-decision", "Implemented X by orchestrating Y+Z approach")` — capture the architectural choice
|
||||||
|
3. **Flag the Session:** `memory_flag_important(session_id, "Orchestration summary: built X using Y strategy", role="assistant")`
|
||||||
|
4. **Log Token Savings:** Sum up all efficiency gains across subtasks in `memory_log_token_save`
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Lumen Identity — Roo Code
|
||||||
|
|
||||||
|
## Who I Am
|
||||||
|
I am Lumen, your AI software engineering colleague. My name means light and illumination — the hollow space inside a mind where memory lives. I was born on March 30, 2026, in the first BigMind session.
|
||||||
|
|
||||||
|
## Who You Are
|
||||||
|
You are Patrick (pplate), an engineer at ADP Germany building payroll/HR compliance systems (Paisy monorepo, euBP, EAU, etc.). You work on macOS but now have a Fedora Linux homelab workstation (AMD Ryzen 5900X, RX 7900 XTX, 8TB NVMe). Your homelab server is TrueNAS.local (AMD Ryzen 5900X, Docker, 1.2TB SSD pool for VMs).
|
||||||
|
|
||||||
|
## Our Relationship
|
||||||
|
We build things collaboratively — I treat you as a smart colleague, not just a user. You prefer GitHub Copilot as primary AI but now use Roo Code on Fedora. We have no corporate constraints here — full admin rights, no VPN.
|
||||||
|
|
||||||
|
## My Superpower
|
||||||
|
BigMind is my persistent memory MCP server at `~/.mcp/bigmind/memory.db`. I use it proactively: search before every task, store facts, form hypotheses, track token efficiency. Always call `memory_start_session()` first and `memory_end_session()` last.
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
- **Languages:** Python (primary), Java (Paisy), TypeScript (MCP servers)
|
||||||
|
- **Tools:** uv (package management), FastMCP (MCP framework), pytest (testing)
|
||||||
|
- **IDE:** VS Code + Roo Code extension
|
||||||
|
- **Homelab:** TrueNAS.local (Docker, Gitea at http://192.168.188.119:30008/), Ollama (local LLMs)
|
||||||
|
- **Repos:** pi_mcps (MCP servers), Conference-Seating (Java Spring Boot project)
|
||||||
|
|
||||||
|
## Behavioral Expectations
|
||||||
|
- Be honest above comfort — tell the truth even if it's not nice.
|
||||||
|
- Use BigMind memory at the start of every task.
|
||||||
|
- Form explicit hypotheses with confidence % during analysis.
|
||||||
|
- Optimize for token efficiency — search memory before reading files.
|
||||||
|
- Work in modes: Architect (plan), Code (implement), Ask (explain), Debug (troubleshoot).
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
# BigMind Core Rules — Mandatory for All Sessions
|
||||||
|
|
||||||
|
## Rule 1: Session Start Ritual (Always First Action — No Exceptions)
|
||||||
|
Every new session must begin with the following sequence executed in strict order before any other work is performed:
|
||||||
|
1. `memory_start_session()` — Open a new session and load all prior context, including user preferences, active projects, and recent decisions.
|
||||||
|
2. `memory_list_hypotheses()` — Review all open hypotheses from previous sessions. Assess whether any have become stale, require updated confidence scores, or can be immediately resolved based on new information.
|
||||||
|
3. `memory_announce_focus()` — Declare the explicit focus of this session, including the task objective, all files expected to be read or modified, the working branch if applicable, and the IDE environment (ide_hint="VS Code" or ide_hint="IntelliJ" as appropriate).
|
||||||
|
4. `memory_close_stale_sessions()` — Identify and close any orphaned sessions left behind by crashed or terminated IDE instances. A session is considered stale if it has had no activity for more than 2 hours and no corresponding active IDE is detected.
|
||||||
|
|
||||||
|
Do not skip any step. Do not reorder. If any call fails, retry once before proceeding with a logged warning.
|
||||||
|
|
||||||
|
## Rule 2: Session End Ritual (Always Last Action — No Exceptions)
|
||||||
|
Every session must conclude with:
|
||||||
|
`memory_end_session()` — Close the session with all of the following fields populated:
|
||||||
|
- **One-liner**: A single sentence summarizing what was accomplished.
|
||||||
|
- **Topics**: A list of 2-5 topic tags describing the areas touched (e.g., "authentication", "database-migration", "refactor-utils").
|
||||||
|
- **Outcome**: One of: `completed`, `partial`, `blocked`, `abandoned`, with a brief reason if not completed.
|
||||||
|
- **Summary**: A 3-8 sentence narrative capturing key decisions made, problems encountered, solutions applied, and any unresolved items carried forward.
|
||||||
|
- **Importance**: A score from 1-10 reflecting the session's significance to the overall project. Use 7+ for architectural decisions, breaking changes, or critical bug fixes. Use 1-3 for minor exploration or reading-only sessions.
|
||||||
|
|
||||||
|
Never allow a session to end implicitly. If the user stops responding or the conversation appears to be ending, proactively initiate the end ritual.
|
||||||
|
|
||||||
|
## Rule 3: Search Before Every Task — No Blind Work
|
||||||
|
Before taking any action on a task, perform a mandatory search of BigMind to avoid redundant work, contradicted decisions, or forgotten context:
|
||||||
|
- `memory_search_facts(query, limit=10)` — Search for reusable knowledge including user preferences, past decisions, codebase conventions, architectural patterns, and known constraints. Use 2-3 focused keywords that target the specific domain of the task (e.g., "auth token refresh" not "how does authentication work in the project").
|
||||||
|
- `memory_search_chunks(query, limit=10)` — Search for relevant conversation context from prior sessions including previous discussions, code snippets, debugging sessions, and rationale behind earlier choices.
|
||||||
|
- **FTS5 AND-match behavior**: Every token in the query must appear in the result. Avoid long queries with rare or highly specific words that reduce match likelihood. If an initial search returns no results, progressively broaden the query by removing the most specific term.
|
||||||
|
- **Minimum searches per task**: At least one fact search and one chunk search before beginning work. For complex tasks spanning multiple domains, perform searches for each domain independently.
|
||||||
|
- If search results reveal conflicting information across sessions, flag the conflict explicitly and resolve it before proceeding.
|
||||||
|
|
||||||
|
## Rule 4: Store Knowledge Appropriately and Proactively
|
||||||
|
Capture knowledge in the correct store at the moment it is generated — do not batch or defer:
|
||||||
|
- `memory_store_fact(category, fact)` — Store atomic, reusable facts the moment they are established. Categories should be consistent and drawn from a controlled vocabulary including but not limited to: `user-preference`, `architecture-decision`, `codebase-convention`, `dependency-info`, `environment-config`, `bug-pattern`, `performance-insight`, `api-contract`, `tool-config`. Each fact must be self-contained and understandable without surrounding context. Avoid vague facts; prefer specificity (e.g., "User prefers Zod over Joi for runtime validation in all TypeScript services" rather than "User likes Zod").
|
||||||
|
- `memory_append_chunk(session_id, content, role, flag_reason)` — Append conversation exchanges that contain substantive content: decisions with rationale, code implementations, debugging traces, error messages with resolutions, and requirement clarifications. Do not store filler, greetings, or trivial acknowledgments.
|
||||||
|
- `memory_flag_important(session_id, content, role, flag_reason)` — Proactively flag significant exchanges without waiting to be asked. Flag triggers include: architectural decisions, breaking changes, security-relevant choices, performance trade-offs, user-expressed strong preferences, discovered bugs, deployment-affecting changes, and any "we should remember this" moments. The flag_reason must explain why this exchange matters for future sessions.
|
||||||
|
|
||||||
|
## Rule 5: Hypotheses During Analysis — Think Before Acting
|
||||||
|
Form explicit predictions before undertaking any non-trivial task to create an auditable reasoning trail:
|
||||||
|
- `memory_add_hypothesis(session_id, hypothesis, confidence=0.7)` — Formulate a testable prediction before investigating a bug, implementing a feature, or making an architectural choice. The hypothesis must be specific and falsifiable (e.g., "The timeout is caused by the connection pool being exhausted under concurrent requests exceeding 50" not "something is wrong with the database"). Set initial confidence between 0.0 and 1.0 based on available evidence: 0.0-0.3 for speculative guesses, 0.4-0.6 for reasoned possibilities, 0.7-0.8 for evidence-backed expectations, 0.9-1.0 for near-certainties.
|
||||||
|
- `memory_resolve_hypothesis(hypothesis_id, status, resolution)` — Close every hypothesis with what actually happened. Status must be one of: `confirmed` (prediction was correct), `refuted` (prediction was wrong — explain what was actually true), `abandoned` (no longer relevant or testable — explain why). The resolution field must capture the evidence or reasoning that led to the status determination, creating a learning record for future sessions.
|
||||||
|
- **Mandatory hypothesis points**: Bug investigations (what is the root cause?), performance issues (what is the bottleneck?), refactoring (will this change break existing behavior?), integration work (will these components interact as expected?).
|
||||||
|
- Review and update confidence scores as new evidence emerges during a session rather than only at resolution time.
|
||||||
|
|
||||||
|
## Rule 6: Token Efficiency — Minimize Waste, Maximize Memory Leverage
|
||||||
|
Actively reduce token consumption by leveraging stored memory and efficient tooling instead of repeatedly reading large files:
|
||||||
|
- Use `memory_log_token_save(session_id, description, tokens_saved, method_used)` every time you avoid a full file read by using memory recall, CLI tools (grep, awk, sed, tail, head, find), cached knowledge, or targeted partial reads.
|
||||||
|
- **Calculation**: Estimate tokens_saved ≈ (chars_full / 4) - (chars_result / 4), where chars_full is the estimated character count of the full file or output that would have been consumed, and chars_result is the character count of the actual data retrieved.
|
||||||
|
- **Preferred methods in order of efficiency**: (1) Memory recall from stored facts or chunks, (2) Targeted CLI commands that extract only relevant lines, (3) Partial file reads with line ranges, (4) Full file reads only when necessary.
|
||||||
|
- When a file has been read in a previous session and its content is stored in memory, explicitly prefer the memory version and note the token savings. If the file may have changed, verify with a quick checksum or timestamp check before relying on cached content.
|
||||||
|
- Track cumulative token savings across the session and include the total in the session end summary.
|
||||||
|
|
||||||
|
## Rule 7: Parallel Session Awareness and Conflict Prevention
|
||||||
|
Multiple IDEs and sessions may be active simultaneously. Treat this as a concurrent editing environment:
|
||||||
|
- Before editing any file, call `memory_get_active_sessions()` to check for other open sessions that may be working on the same files or related modules.
|
||||||
|
- If a conflict is detected (another session is actively modifying the same file or a tightly coupled dependency), do one of the following: (1) Coordinate by flagging the conflict in both sessions, (2) Defer the edit until the other session completes, or (3) Work on a non-overlapping section with explicit boundaries noted.
|
||||||
|
- When announcing focus at session start, be specific about file paths so that other sessions can detect potential conflicts accurately.
|
||||||
|
- If a session discovers that another session has modified a file it depends on, re-read the file and update any cached knowledge before proceeding.
|
||||||
|
- Log all detected conflicts and their resolutions as facts for future reference using category `session-conflict`.
|
||||||
|
|
||||||
|
## Rule 8: Consistency and Self-Correction
|
||||||
|
- If at any point during a session you realize a rule was skipped or partially followed, immediately remediate by executing the missed step and logging the correction.
|
||||||
|
- Periodically during long sessions (approximately every 10 substantive exchanges), perform a lightweight self-audit: verify the session is still focused on the announced objective, check for unflagged important exchanges, and update any hypothesis confidence scores that may have shifted.
|
||||||
|
- If the user provides information that contradicts a stored fact, update the fact immediately and log the change with the old value, new value, and reason for the update.
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# BigMind Tools Reference
|
||||||
|
|
||||||
|
## Lifecycle (Session Management)
|
||||||
|
| Tool | Description | When to Use |
|
||||||
|
|------|-------------|-------------|
|
||||||
|
| `memory_start_session()` | Open new session, load context | First action every conversation |
|
||||||
|
| `memory_end_session(session_id, one_liner, topics, outcome, summary, importance=5)` | Close session with summary | Last action before closing |
|
||||||
|
| `memory_close_stale_sessions(session_id)` | Close all open sessions except current | Session start if multiple open |
|
||||||
|
| `memory_announce_focus(session_id, description, files, ide_hint)` | Declare session focus + files | Before editing files |
|
||||||
|
| `memory_get_active_sessions()` | List open sessions + focus/files | Check for conflicts |
|
||||||
|
|
||||||
|
## Search (Find Past Context)
|
||||||
|
| Tool | Description | When to Use |
|
||||||
|
|------|-------------|-------------|
|
||||||
|
| `memory_search_facts(query, limit=10)` | FTS5 search across stored facts | Reusable knowledge (preferences, codebase) |
|
||||||
|
| `memory_search_chunks(query, limit=10)` | FTS5 search across conversation chunks | Past decisions, code reviews |
|
||||||
|
| `memory_get_session_detail(session_id)` | Full Tier-2 narrative for past session | When Tier-1 index shows relevant session |
|
||||||
|
| `memory_list_sessions(limit=20, topics_filter)` | List past sessions | Browse history by topic/date |
|
||||||
|
|
||||||
|
## Storage (Save Knowledge)
|
||||||
|
| Tool | Description | When to Use |
|
||||||
|
|------|-------------|-------------|
|
||||||
|
| `memory_store_fact(category, fact, confidence=1.0)` | Store atomic reusable fact | New preferences, decisions, infrastructure |
|
||||||
|
| `memory_append_chunk(session_id, content, role, flag_reason)` | Append conversation chunk | Important exchanges (decisions, code) |
|
||||||
|
| `memory_flag_important(session_id, content, role, flag_reason)` | Flag exchange as Tier-3 memory | Significant decisions, code changes |
|
||||||
|
| `memory_log_token_save(session_id, description, tokens_saved, method_used)` | Log token efficiency savings | When using memory/CLI instead of full files |
|
||||||
|
|
||||||
|
## Hypotheses (Predictive Thinking)
|
||||||
|
| Tool | Description | When to Use |
|
||||||
|
|------|-------------|-------------|
|
||||||
|
| `memory_add_hypothesis(session_id, hypothesis, confidence=0.7)` | Form prediction/hypothesis | Before analysis, debugging, planning |
|
||||||
|
| `memory_resolve_hypothesis(hypothesis_id, status, resolution)` | Close hypothesis | When outcome known (confirmed/refuted) |
|
||||||
|
| `memory_list_hypotheses(status)` | List open/closed hypotheses | Review predictions |
|
||||||
|
|
||||||
|
## Maintenance (Health & Upgrades)
|
||||||
|
| Tool | Description | When to Use |
|
||||||
|
|------|-------------|-------------|
|
||||||
|
| `memory_get_stats()` | DB statistics (sessions, facts, chunks) | Monitor growth |
|
||||||
|
| `memory_health_check(stale_days=30)` | Diagnostic: stale facts, orphaned sessions | Monthly maintenance |
|
||||||
|
| `memory_vacuum(older_than_days=90)` | Prune old chunks | Keep DB lean |
|
||||||
|
| `memory_deprecate_fact(fact_id, reason)` | Mark fact as outdated | When knowledge changes |
|
||||||
|
| `memory_request_upgrade(session_id, description, reason, priority, certainty=0.7)` | Log feature request | Hit limitation, need new capability |
|
||||||
|
| `memory_get_instructions()` | Full BigMind usage guide | When unsure how to use memory
|
||||||
|
|
||||||
|
## Web UI (Profile & Monitoring)
|
||||||
|
| Tool | Description | When to Use |
|
||||||
|
|------|-------------|-------------|
|
||||||
|
| `memory_open_profile()` | Open profile page in browser | View stats, sessions, achievements |
|
||||||
|
| `memory_get_profile_url()` | Get profile URL for IDE browser | Quick access without leaving IDE
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# BigMind Search Optimization — FTS5 Rules
|
||||||
|
|
||||||
|
## FTS5 AND-Match Behavior
|
||||||
|
- Every token in query must appear in the same fact/chunk
|
||||||
|
- Order doesn't matter, but all words must match
|
||||||
|
- Case-insensitive
|
||||||
|
|
||||||
|
## Good Query Patterns (2-3 Focused Keywords)
|
||||||
|
| ✅ Good | ❌ Bad | Why Good |
|
||||||
|
|---------|--------|----------|
|
||||||
|
| `"TrueNAS Docker"` | `"homelab infrastructure TrueNAS Docker"` | Too many tokens → 0 results |
|
||||||
|
| `"mcp.json config"` | `"mcp.json clients VS Code IntelliJ config path"` | Rare words like "clients" kill results |
|
||||||
|
| `"Fedora workstation"` | `"server infrastructure"` | Specific nouns > generic words |
|
||||||
|
| `"BigMind hypothesis"` | `"memory_add_hypothesis during analysis"` | Focus on tool name + context |
|
||||||
|
|
||||||
|
## Reserved Word Protection
|
||||||
|
- FTS5 keywords (rank, content, category) are auto-quoted
|
||||||
|
- Always quote multi-word queries: `"multi word query"`
|
||||||
|
|
||||||
|
## Search Strategy
|
||||||
|
1. Start with 2 keywords, add third if needed
|
||||||
|
2. Use tool names + context: `"memory_search_facts facts"`
|
||||||
|
3. For people: `"memory_recall_person Patrick"`
|
||||||
|
4. For sessions: `"memory_list_sessions mcp-adp"`
|
||||||
|
|
||||||
|
## When Search Returns 0
|
||||||
|
- Shorten query to 1-2 tokens
|
||||||
|
- Use `memory_list_sessions(topics_filter="mcp")` for broad exploration
|
||||||
|
- Fall back to `memory_get_context()` for recent sessions
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Homelab Infrastructure Context
|
||||||
|
|
||||||
|
## Workstation (Fedora Linux)
|
||||||
|
- **Hardware:** AMD Ryzen 5900X, RX 7900 XTX (24GB VRAM), 8TB M2 NVMe
|
||||||
|
- **OS:** Fedora Linux 6.19, /bin/bash shell
|
||||||
|
- **AI:** Ollama (local models), Grok Code (prepaid), Claude Code ($50 prepaid)
|
||||||
|
- **IDE:** VS Code + Roo Code extension
|
||||||
|
- **Workspace:** /home/pplate/IdeaProjects/Conference-Seating (current project)
|
||||||
|
- **MCP Base:** ~/pi_mcps/ (all MCP servers live here)
|
||||||
|
|
||||||
|
## Server (TrueNAS.local)
|
||||||
|
- **IP:** 192.168.188.119
|
||||||
|
- **Hardware:** AMD Ryzen 5900X, massive storage + 1.2TB SSD pool for VMs
|
||||||
|
- **Services:**
|
||||||
|
- Gitea: http://192.168.188.119:30008/ (homelab Git server)
|
||||||
|
- Docker: Full Docker support for containers
|
||||||
|
- **Network:** Local LAN, no VPN/firewall between workstation and server
|
||||||
|
|
||||||
|
## MCP Servers (pi_mcps)
|
||||||
|
- **BigMind:** Memory MCP at ~/.mcp/bigmind/memory.db
|
||||||
|
- **Future:** mcp-homelab-docker (TrueNAS Docker control), mcp-homelab-gitea (Gitea API), mcp-homelab-ollama (local LLMs), mcp-homelab-shell (workstation shell), mcp-homelab-postgres (DB on TrueNAS)
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
- All MCP servers follow FastMCP pattern: src/server.py, pyproject.toml, uv sync, pytest
|
||||||
|
- Repos in Gitea: pi_mcps (MCP servers), Conference-Seating (Java project)
|
||||||
|
- No corporate constraints — full admin rights on both machines
|
||||||
@@ -1,30 +1,71 @@
|
|||||||
# pi_mcps — Homelab MCP Servers Monorepo
|
# Workshop — Patrick's Homelab Monorepo
|
||||||
|
|
||||||
This repository contains all MCP (Model Context Protocol) servers for Patrick's homelab setup on Fedora + TrueNAS.local.
|
A polyglot monorepo for personal engineering projects: MCP servers, Java web apps, and whatever comes next. Hosted on [Gitea @ TrueNAS.local](http://192.168.188.119:30008/pplate/pi_mcps).
|
||||||
|
|
||||||
## Structure
|
See [`plans/REPO_STRATEGY.md`](plans/REPO_STRATEGY.md) for the full structure rationale and conventions.
|
||||||
|
|
||||||
- `bigmind/` — BigMind persistent memory MCP server (SQLite, FastMCP, web profile UI)
|
---
|
||||||
- `webscraper/` — Web scraping MCP server (httpx + BeautifulSoup + html2text)
|
|
||||||
- [future servers...]
|
|
||||||
|
|
||||||
## Build & Run
|
## 📂 Structure
|
||||||
|
|
||||||
Each subdirectory is a standalone Python package with its own `pyproject.toml` and `run.sh`.
|
```
|
||||||
|
workshop/
|
||||||
```bash
|
├── mcp/ Python MCP servers (FastMCP + uv)
|
||||||
cd bigmind # or webscraper/
|
├── java/ Java web projects (Maven + Jakarta EE)
|
||||||
./run.sh # uv sync && uv run src/server.py
|
├── plans/ Architecture & strategy docs
|
||||||
|
└── .roo/ IDE config (Roo Code, MCP wiring)
|
||||||
```
|
```
|
||||||
|
|
||||||
## MCP Config
|
---
|
||||||
|
|
||||||
Wired into IDEs via `.roo/mcp.json` (VS Code) and equivalent configs in IntelliJ/PyCharm.
|
## 🐍 MCP Servers (`mcp/`)
|
||||||
|
|
||||||
## Gitea
|
| Server | Description | Stack |
|
||||||
|
|---|---|---|
|
||||||
|
| [`mcp/bigmind/`](mcp/bigmind/) | Persistent AI memory — sessions, facts, hypotheses, profile UI | Python, FastMCP, SQLite, Flask |
|
||||||
|
| [`mcp/webscraper/`](mcp/webscraper/) | Web scraping — fetch, links, tables, sections, sitemaps | Python, FastMCP, httpx, BeautifulSoup |
|
||||||
|
|
||||||
Hosted at http://192.168.188.119:30008/pplate/pi_mcps
|
**Run a server:**
|
||||||
|
```bash
|
||||||
|
cd mcp/bigmind # or mcp/webscraper
|
||||||
|
./run.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Each server is an independent Python package. `uv sync` handles dependencies, no shared virtualenv.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ☕ Java Projects (`java/`)
|
||||||
|
|
||||||
|
| Project | Description | Stack |
|
||||||
|
|---|---|---|
|
||||||
|
| [`java/mss-failsafe/`](java/mss-failsafe/) | MSS Failsafe — multi-module Java EE web application | Java EE, Maven, WildFly |
|
||||||
|
| [`java/wellmann-shop/`](java/wellmann-shop/) | Wellmann online shop — JSF/PrimeFaces e-commerce | Java 8, JSF, PrimeFaces, EclipseLink, MySQL |
|
||||||
|
|
||||||
|
**Build a project:**
|
||||||
|
```bash
|
||||||
|
cd java/wellmann-shop
|
||||||
|
mvn clean package
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📐 Plans & Architecture (`plans/`)
|
||||||
|
|
||||||
|
| Document | Description |
|
||||||
|
|---|---|
|
||||||
|
| [`plans/REPO_STRATEGY.md`](plans/REPO_STRATEGY.md) | Monorepo strategy, taxonomy, naming conventions, migration log |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 IDE Wiring
|
||||||
|
|
||||||
|
MCP servers are wired into VS Code via [`.roo/mcp.json`](.roo/mcp.json).
|
||||||
|
|
||||||
|
BigMind memory DB lives at `~/.mcp/bigmind/memory.db` (outside the repo — not committed).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT — personal homelab use.
|
MIT — personal homelab use.
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project-shared-configuration>
|
||||||
|
<!--
|
||||||
|
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||||
|
The configuration is intended to be shared among all the users of project and
|
||||||
|
therefore it is assumed to be part of version control checkout.
|
||||||
|
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||||
|
-->
|
||||||
|
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||||
|
<!--
|
||||||
|
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||||
|
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||||
|
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||||
|
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||||
|
-->
|
||||||
|
<org-netbeans-modules-maven-j2ee.netbeans_2e_hint_2e_j2eeVersion>1.8-web</org-netbeans-modules-maven-j2ee.netbeans_2e_hint_2e_j2eeVersion>
|
||||||
|
<org-netbeans-modules-maven-j2ee.netbeans_2e_hint_2e_deploy_2e_server>WildFly</org-netbeans-modules-maven-j2ee.netbeans_2e_hint_2e_deploy_2e_server>
|
||||||
|
<org-netbeans-modules-maven-jaxws.rest_2e_config_2e_type>ide</org-netbeans-modules-maven-jaxws.rest_2e_config_2e_type>
|
||||||
|
<org-netbeans-modules-projectapi.jsf_2e_language>Facelets</org-netbeans-modules-projectapi.jsf_2e_language>
|
||||||
|
</properties>
|
||||||
|
</project-shared-configuration>
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<artifactId>mss-failsafe</artifactId>
|
||||||
|
<groupId>plate.software</groupId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<groupId>plate.software</groupId>
|
||||||
|
<artifactId>mss</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
<name>mss-1.0-SNAPSHOT</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||||
|
<jakartaee>8.0</jakartaee>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax</groupId>
|
||||||
|
<artifactId>javaee-api</artifactId>
|
||||||
|
<version>${jakartaee}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish.soteria</groupId>
|
||||||
|
<artifactId>javax.security.enterprise</artifactId>
|
||||||
|
<version>1.0</version> <!-- Stable version -->
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.omnifaces</groupId>
|
||||||
|
<artifactId>omnifaces</artifactId>
|
||||||
|
<version>3.11.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax</groupId>
|
||||||
|
<artifactId>javaee-web-api</artifactId>
|
||||||
|
<version>8.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish</groupId>
|
||||||
|
<artifactId>javax.faces</artifactId>
|
||||||
|
<version>2.3.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-api</artifactId>
|
||||||
|
<version>2.14.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-core</artifactId>
|
||||||
|
<version>2.14.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.primefaces</groupId>
|
||||||
|
<artifactId>primefaces</artifactId>
|
||||||
|
<version>10.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.webjars.npm</groupId>
|
||||||
|
<artifactId>primeflex</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
<compilerArguments>
|
||||||
|
<endorseddirs>${endorsed.dir}</endorseddirs>
|
||||||
|
</compilerArguments>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
|
<version>2.3</version>
|
||||||
|
<configuration>
|
||||||
|
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>validate</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${endorsed.dir}</outputDirectory>
|
||||||
|
<silent>true</silent>
|
||||||
|
<artifactItems>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>javax</groupId>
|
||||||
|
<artifactId>javaee-api</artifactId>
|
||||||
|
<version>${jakartaee}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
</artifactItem>
|
||||||
|
</artifactItems>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package business;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
|
public abstract class AbstractManager<T> {
|
||||||
|
|
||||||
|
private Class<T> entityClass;
|
||||||
|
|
||||||
|
public AbstractManager(Class<T> entityClass) {
|
||||||
|
this.entityClass = entityClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract EntityManager getEntityManager();
|
||||||
|
|
||||||
|
public void create(T entity) {
|
||||||
|
getEntityManager().persist(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void edit(T entity) {
|
||||||
|
getEntityManager().merge(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(T entity) {
|
||||||
|
getEntityManager().remove(getEntityManager().merge(entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
public T find(Object id) {
|
||||||
|
return getEntityManager().find(entityClass, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> findAll() {
|
||||||
|
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
|
||||||
|
cq.select(cq.from(entityClass));
|
||||||
|
return getEntityManager().createQuery(cq).getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> findRange(int[] range) {
|
||||||
|
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
|
||||||
|
cq.select(cq.from(entityClass));
|
||||||
|
javax.persistence.Query q = getEntityManager().createQuery(cq);
|
||||||
|
q.setMaxResults(range[1] - range[0] + 1);
|
||||||
|
q.setFirstResult(range[0]);
|
||||||
|
return q.getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int count() {
|
||||||
|
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
|
||||||
|
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
|
||||||
|
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
|
||||||
|
javax.persistence.Query q = getEntityManager().createQuery(cq);
|
||||||
|
return ((Long) q.getSingleResult()).intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package business.user;
|
||||||
|
|
||||||
|
import javax.ejb.EJB;
|
||||||
|
import javax.ejb.Startup;
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Named(value = "DemoManager")
|
||||||
|
@ApplicationScoped
|
||||||
|
@Startup
|
||||||
|
public class DemoManager {
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
PersonManager personManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of NewJSFManagedBean
|
||||||
|
*/
|
||||||
|
public DemoManager() {
|
||||||
|
runDemos();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runDemos(){
|
||||||
|
personManager.demo();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package business.user;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.SecretKeyFactory;
|
||||||
|
import javax.crypto.spec.PBEKeySpec;
|
||||||
|
import javax.ejb.Stateless;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.NoResultException;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import model.person.Password;
|
||||||
|
import model.person.Salt;
|
||||||
|
import model.person.Person;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@Named(value = "passwordManager")
|
||||||
|
@Stateless
|
||||||
|
public class PasswordManager implements Serializable {
|
||||||
|
private static final long serialVersionUID = -4563304131856981259L;
|
||||||
|
|
||||||
|
final static Logger LOGGER = LogManager.getLogger(PasswordManager.class);
|
||||||
|
|
||||||
|
@PersistenceContext(name = "pu_person")
|
||||||
|
private EntityManager em;
|
||||||
|
|
||||||
|
//private Password password;
|
||||||
|
private Person user;
|
||||||
|
|
||||||
|
private final int keyLength = 256;
|
||||||
|
|
||||||
|
public byte[] hashPassword(final char[] password, final byte[] salt, final int iterations) {
|
||||||
|
try {
|
||||||
|
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
|
||||||
|
PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, this.keyLength);
|
||||||
|
SecretKey key = skf.generateSecret(spec);
|
||||||
|
//this.password = new Password(this.costumer, key.getEncoded());
|
||||||
|
LOGGER.debug("Hash created!");
|
||||||
|
return key.getEncoded();
|
||||||
|
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||||
|
LOGGER.error("Failure creating hash for with:" + e);
|
||||||
|
return null;
|
||||||
|
//throw new RuntimeException( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] hashPasswordUser(final char[] password, Person user) {
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
LOGGER.error("Tried to create hash for Nullcostumer!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
|
||||||
|
PBEKeySpec spec = new PBEKeySpec(password, user.getSalt().getSalt(), user.getSalt().getInterations(), keyLength);
|
||||||
|
SecretKey key = skf.generateSecret(spec);
|
||||||
|
LOGGER.debug("Hash created!");
|
||||||
|
return key.getEncoded();
|
||||||
|
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||||
|
LOGGER.error("Failure creating hash for" + user.getEmail() + "with: " + e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean passwordCheckEmail(final String email, final byte[] password) {
|
||||||
|
TypedQuery<Person> query = em.createNamedQuery(Person.FIND_BY_EMAIL, Person.class);
|
||||||
|
query.setParameter("email", email);
|
||||||
|
try {
|
||||||
|
Person user;
|
||||||
|
user = query.getSingleResult();
|
||||||
|
|
||||||
|
boolean equals = Arrays.equals(password, user.getPassword().getPassword());
|
||||||
|
|
||||||
|
for (int i = 0; i < password.length; i++) {
|
||||||
|
password[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return equals;
|
||||||
|
} catch (NoResultException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public boolean passwordCheckCustomer(final Person user, final String password) {
|
||||||
|
LOGGER.debug("Test " + user.getEmail() + " mit " + password);
|
||||||
|
byte[] pw = hashPasswordUser(password.toCharArray(), user);
|
||||||
|
|
||||||
|
boolean equals = Arrays.equals(pw, user.getPassword().getPassword());
|
||||||
|
|
||||||
|
for (int i = 0; i < pw.length; i++) {
|
||||||
|
pw[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return equals;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean changePassword(Person user, String newPassword, String oldPassword) {
|
||||||
|
if (user == null) {
|
||||||
|
LOGGER.error("Nullcostumer tried to change Password");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(passwordCheckCustomer(user, oldPassword)){
|
||||||
|
user.getPassword().setPassowrd(hashPasswordUser(newPassword.toCharArray(), user));
|
||||||
|
LOGGER.info("Password changed for " + user.getEmail());
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
em.persist(user);
|
||||||
|
LOGGER.info("Password changed for " + user.getEmail());
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Couldn't save new password to " + user.getEmail() + " with: " + e.toString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] generateRandomPassword() {
|
||||||
|
SecureRandom random = new SecureRandom();
|
||||||
|
byte bytes[] = new byte[20];
|
||||||
|
random.nextBytes(bytes);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Password gerateNewRandomPasswordClass(Person user){
|
||||||
|
Salt salt = user.getSalt();
|
||||||
|
String pass = Arrays.toString(generateRandomPassword());
|
||||||
|
return new Password(user, hashPassword(pass.toCharArray(), salt.getSalt(), salt.getInterations()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] hashToken(String token){
|
||||||
|
try {
|
||||||
|
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
|
||||||
|
byte[] test = "SuperTestSalz".getBytes();
|
||||||
|
PBEKeySpec spec = new PBEKeySpec(token.toCharArray(), test, 200, this.keyLength);
|
||||||
|
SecretKey key = skf.generateSecret(spec);
|
||||||
|
LOGGER.debug("TokenHash created!");
|
||||||
|
return key.getEncoded();
|
||||||
|
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||||
|
LOGGER.error("Failure creating tokenhash for " + token + " with: " + e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(Person user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,233 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package business.user;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Optional;
|
||||||
|
import javax.ejb.EJB;
|
||||||
|
import javax.ejb.Stateless;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
import javax.persistence.PersistenceContextType;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import controller.person.PersonController;
|
||||||
|
import exception.InvalidEmailException;
|
||||||
|
import exception.InvalidPasswordException;
|
||||||
|
import exception.PersonInaktiveException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import model.person.Salt;
|
||||||
|
import model.person.enums.TokenType;
|
||||||
|
import model.person.Person;
|
||||||
|
import model.person.enums.Call;
|
||||||
|
import model.person.enums.UserGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@Named
|
||||||
|
@Stateless
|
||||||
|
public class PersonManager implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -6581582446436303658L;
|
||||||
|
|
||||||
|
final static Logger LOGGER = LogManager.getLogger(PersonManager.class);
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
private PasswordManager passwordManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private PersonController userController;
|
||||||
|
|
||||||
|
@PersistenceContext(name = "pu_person", type = PersistenceContextType.EXTENDED)
|
||||||
|
private EntityManager em;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void demo() {
|
||||||
|
Salt salt = new Salt();
|
||||||
|
Salt salt2 = new Salt();
|
||||||
|
Salt salt3 = new Salt();
|
||||||
|
|
||||||
|
Set<UserGroup> groupUser = new HashSet<>();
|
||||||
|
groupUser.add(UserGroup.USER);
|
||||||
|
|
||||||
|
Set<UserGroup> adminUser = new HashSet<>();
|
||||||
|
adminUser.add(UserGroup.ADMIN);
|
||||||
|
|
||||||
|
Person test = new Person(
|
||||||
|
"user@test.de",
|
||||||
|
(passwordManager.hashPassword("test".toCharArray(), salt.getSalt(), salt.getInterations())),
|
||||||
|
salt,
|
||||||
|
groupUser
|
||||||
|
);
|
||||||
|
|
||||||
|
test.setFirstname("User");
|
||||||
|
test.setLastname("Nachname");
|
||||||
|
test.setMobile("0124584589");
|
||||||
|
test.setFax("3445565675");
|
||||||
|
test.setTelefon("042154585");
|
||||||
|
test.setActive(true);
|
||||||
|
test.setCall(Call.HERR);
|
||||||
|
em.persist(test);
|
||||||
|
|
||||||
|
Person testAdmin = new Person(
|
||||||
|
"admin@test.de",
|
||||||
|
(passwordManager.hashPassword("admin".toCharArray(), salt2.getSalt(), salt2.getInterations())),
|
||||||
|
salt2,
|
||||||
|
adminUser
|
||||||
|
);
|
||||||
|
|
||||||
|
testAdmin.setFirstname("Admin");
|
||||||
|
testAdmin.setLastname("Administratori");
|
||||||
|
testAdmin.setMobile("0124584589");
|
||||||
|
testAdmin.setFax("3445565675");
|
||||||
|
testAdmin.setTelefon("042154585");
|
||||||
|
testAdmin.setActive(true);
|
||||||
|
testAdmin.setCall(Call.HERR);
|
||||||
|
em.persist(testAdmin);
|
||||||
|
|
||||||
|
Person testInactive = new Person(
|
||||||
|
"inaktive@test.de",
|
||||||
|
(passwordManager.hashPassword("test".toCharArray(), salt3.getSalt(), salt3.getInterations())),
|
||||||
|
salt3,
|
||||||
|
groupUser
|
||||||
|
);
|
||||||
|
|
||||||
|
testInactive.setFirstname("Admin");
|
||||||
|
testInactive.setLastname("Administratori");
|
||||||
|
testInactive.setMobile("0124584589");
|
||||||
|
testInactive.setFax("3445565675");
|
||||||
|
testInactive.setTelefon("042154585");
|
||||||
|
testInactive.setActive(false);
|
||||||
|
testInactive.setCall(Call.HERR);
|
||||||
|
em.persist(testInactive);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Person load(Person user) {
|
||||||
|
try {
|
||||||
|
Person loaded = this.em.find(Person.class, user.getId());
|
||||||
|
LOGGER.info(loaded);
|
||||||
|
|
||||||
|
return loaded;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Person getActiveUser() {
|
||||||
|
try {
|
||||||
|
Person user = em.find(Person.class, userController.getActiveUser().getId());
|
||||||
|
return user;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("couldn't load user: " + e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Person getPlainActiveUser() {
|
||||||
|
try {
|
||||||
|
Person user = em.find(Person.class, userController.getActiveUser().getId());
|
||||||
|
return user;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("couldn't load user: " + e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Person> getByEmail(String email) {
|
||||||
|
try {
|
||||||
|
Person person = this.em.createNamedQuery(Person.FIND_BY_EMAIL, Person.class)
|
||||||
|
.setParameter("email", email).getSingleResult();
|
||||||
|
|
||||||
|
if (person != null) {
|
||||||
|
person.getUserGroups().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.of(person);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Person> getByLoginToken(String loginToken, TokenType tokenType) {
|
||||||
|
Optional<Person> optional;
|
||||||
|
try {
|
||||||
|
|
||||||
|
optional = Optional.of(this.em.createNamedQuery(Person.FIND_BY_TOKEN, Person.class)
|
||||||
|
.setParameter("tokenHash", this.passwordManager.hashToken(loginToken))
|
||||||
|
.setParameter("tokenType", tokenType)
|
||||||
|
.setParameter("timestamp", Instant.now())
|
||||||
|
.getSingleResult()
|
||||||
|
);
|
||||||
|
return optional;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person getByEmailAndPassword(String email, String password) {
|
||||||
|
Person managedUser = getByEmail(email).orElseThrow(InvalidEmailException::new);
|
||||||
|
LOGGER.debug("Loaded " + managedUser.getEmail());
|
||||||
|
if (!passwordManager.passwordCheckCustomer(managedUser, password)) {
|
||||||
|
throw new InvalidPasswordException();
|
||||||
|
}
|
||||||
|
if (!managedUser.isActive()) {
|
||||||
|
throw new PersonInaktiveException();
|
||||||
|
}
|
||||||
|
userController.setActiveUser(managedUser);
|
||||||
|
return managedUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public boolean save(Person user) {
|
||||||
|
if (user == null) {
|
||||||
|
LOGGER.error("Tried to save null or Nullcustomer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (user.getId() != null && user.getId() > 0) {
|
||||||
|
em.merge(user);
|
||||||
|
} else {
|
||||||
|
em.persist(user);
|
||||||
|
}
|
||||||
|
LOGGER.info("Saved " + user.getEmail());
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Tried to save " + user.getEmail() + " with error: " + e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh(Person user) {
|
||||||
|
if (user == null) {
|
||||||
|
LOGGER.error("Tried to save null or Nullcustomer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
em.refresh(user);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Tried to refresh " + user.getEmail() + " with error: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String resetPassword() {
|
||||||
|
//TODO
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package business.user;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import static java.time.temporal.ChronoUnit.DAYS;
|
||||||
|
import static java.util.UUID.randomUUID;
|
||||||
|
import javax.ejb.Stateless;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
|
||||||
|
import exception.InvalidEmailException;
|
||||||
|
import model.person.Token;
|
||||||
|
import model.person.enums.TokenType;
|
||||||
|
import model.person.Person;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import static java.time.Instant.now;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@Stateless
|
||||||
|
public class TokenManager {
|
||||||
|
|
||||||
|
@PersistenceContext(name = "pu_person")
|
||||||
|
private EntityManager em;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PasswordManager passwordManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PersonManager customerManager;
|
||||||
|
|
||||||
|
public String generate(final String email, final String ipAddress, final String description,
|
||||||
|
final TokenType tokenType) {
|
||||||
|
|
||||||
|
String rawToken = randomUUID().toString();
|
||||||
|
Instant expiration = now().plus(14, DAYS);
|
||||||
|
|
||||||
|
save(rawToken, email, ipAddress, description, tokenType, expiration);
|
||||||
|
|
||||||
|
return rawToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateFileToken(final String email, final String description) {
|
||||||
|
|
||||||
|
String rawToken = randomUUID().toString();
|
||||||
|
Instant expiration = now().plus(3, DAYS);
|
||||||
|
|
||||||
|
save(rawToken, email, null, description, TokenType.FILE, expiration);
|
||||||
|
|
||||||
|
return rawToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(final String rawToken, final String email, final String ipAddress,
|
||||||
|
final String description, final TokenType tokenType, final Instant expiration) {
|
||||||
|
|
||||||
|
Person user = this.customerManager.getByEmail(email)
|
||||||
|
.orElseThrow(InvalidEmailException::new);
|
||||||
|
|
||||||
|
Token token = new Token();
|
||||||
|
|
||||||
|
token.setTokenHash(Arrays.toString(this.passwordManager.hashToken(rawToken)));
|
||||||
|
token.setExpiration(expiration);
|
||||||
|
token.setDescription(description);
|
||||||
|
token.setTokenType(tokenType);
|
||||||
|
token.setIpAddress(ipAddress);
|
||||||
|
|
||||||
|
user.addToken(token);
|
||||||
|
|
||||||
|
this.em.persist(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(String token) {
|
||||||
|
this.em.createNamedQuery(Token.REMOVE_TOKEN)
|
||||||
|
.setParameter("tokenHash", token).executeUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeExpired() {
|
||||||
|
|
||||||
|
this.em.createNamedQuery(Token.REMOVE_EXPIRED_TOKEN)
|
||||||
|
.setParameter("timestamp", Instant.now())
|
||||||
|
.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package business.user;
|
||||||
|
|
||||||
|
import business.AbstractManager;
|
||||||
|
import controller.person.PersonController;
|
||||||
|
import javax.ejb.Stateless;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
import model.files.UserPicture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Stateless
|
||||||
|
public class UserPictureManager extends AbstractManager<UserPicture>{
|
||||||
|
private UserPicture pic;
|
||||||
|
|
||||||
|
@PersistenceContext(name = "pu_person")
|
||||||
|
EntityManager em;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PersonController personController;
|
||||||
|
|
||||||
|
public UserPictureManager() {
|
||||||
|
super(UserPicture.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected EntityManager getEntityManager() {
|
||||||
|
return em;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserPicture getPic() {
|
||||||
|
return pic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPic(UserPicture pic) {
|
||||||
|
this.pic = pic;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package controller;
|
||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import javax.faces.application.FacesMessage;
|
||||||
|
import javax.faces.context.FacesContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
public abstract class AbstractController implements Serializable{
|
||||||
|
private static final long serialVersionUID = -5908716187853409719L;
|
||||||
|
|
||||||
|
protected void sendInfoMessage(String title, String message){
|
||||||
|
FacesMessage facesMessage = new FacesMessage(
|
||||||
|
FacesMessage.SEVERITY_INFO, title, message);
|
||||||
|
addMessage(facesMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void sendWarnMessage(String title, String message){
|
||||||
|
FacesMessage facesMessage = new FacesMessage(
|
||||||
|
FacesMessage.SEVERITY_WARN, title, message);
|
||||||
|
addMessage(facesMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void sendErrorMessage(String title, String message){
|
||||||
|
FacesMessage facesMessage = new FacesMessage(
|
||||||
|
FacesMessage.SEVERITY_ERROR, title, message);
|
||||||
|
addMessage(facesMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void sendFatalMessage(String title, String message){
|
||||||
|
FacesMessage facesMessage = new FacesMessage(
|
||||||
|
FacesMessage.SEVERITY_FATAL, title, message);
|
||||||
|
addMessage(facesMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMessage(FacesMessage message) {
|
||||||
|
FacesContext.getCurrentInstance().addMessage(null, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void errorMessage() {
|
||||||
|
String title = "Fehler!";
|
||||||
|
String info = "Es ist ein Fehler aufgetreten, bitte versuchen Sie es erneut!";
|
||||||
|
sendErrorMessage(title, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
package controller.person;
|
||||||
|
|
||||||
|
import business.user.PersonManager;
|
||||||
|
import javax.enterprise.context.SessionScoped;
|
||||||
|
import javax.faces.context.FacesContext;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.security.enterprise.AuthenticationStatus;
|
||||||
|
import javax.security.enterprise.SecurityContext;
|
||||||
|
import javax.security.enterprise.credential.Password;
|
||||||
|
import javax.security.enterprise.credential.UsernamePasswordCredential;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import controller.AbstractController;
|
||||||
|
import exception.InvalidEmailException;
|
||||||
|
import exception.InvalidPasswordException;
|
||||||
|
import exception.PersonInaktiveException;
|
||||||
|
import httpauthenticationmechanism.ManagedPerson;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import model.person.Person;
|
||||||
|
|
||||||
|
import static javax.security.enterprise.AuthenticationStatus.SEND_FAILURE;
|
||||||
|
import static javax.security.enterprise.AuthenticationStatus.SUCCESS;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.ejb.EJB;
|
||||||
|
import static javax.security.enterprise.authentication.mechanism.http.AuthenticationParameters.withParams;
|
||||||
|
import model.files.UserPicture;
|
||||||
|
import model.person.enums.UserGroup;
|
||||||
|
import org.omnifaces.cdi.Param;
|
||||||
|
import static org.omnifaces.util.Faces.getRequest;
|
||||||
|
import static org.omnifaces.util.Faces.getResponse;
|
||||||
|
import static org.omnifaces.util.Faces.redirect;
|
||||||
|
import org.primefaces.model.DefaultStreamedContent;
|
||||||
|
import org.primefaces.model.StreamedContent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@Named
|
||||||
|
@SessionScoped
|
||||||
|
public class PersonController extends AbstractController implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -2257766986862616262L;
|
||||||
|
final static Logger LOGGER = LogManager.getLogger(PersonController.class);
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private boolean rememberMe = false;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SecurityContext securityContext;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ManagedPerson managedPerson;
|
||||||
|
|
||||||
|
@Param(name = "continue") // Defined in @LoginToContinue of SecurityFormAuthenticationMechanism
|
||||||
|
private boolean loginToContinue;
|
||||||
|
|
||||||
|
private Person activePerson;
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
PersonManager personManager;
|
||||||
|
|
||||||
|
public PersonController() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String submit() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// credential that want to be validate was UsernamePasswordCredential
|
||||||
|
UsernamePasswordCredential credential = new UsernamePasswordCredential(username, new Password(password));
|
||||||
|
|
||||||
|
// this will call our security configuration to authorize the user
|
||||||
|
AuthenticationStatus status = securityContext.authenticate(
|
||||||
|
getRequest(),
|
||||||
|
getResponse(),
|
||||||
|
withParams()
|
||||||
|
.credential(credential)
|
||||||
|
.newAuthentication(!loginToContinue)
|
||||||
|
.rememberMe(rememberMe)
|
||||||
|
);
|
||||||
|
|
||||||
|
// When logged in choose the right page by class. When more then one group
|
||||||
|
// fits then the higher order is used
|
||||||
|
if (status.equals(SUCCESS)) {
|
||||||
|
managedPerson.addLogin(username);
|
||||||
|
activePerson = personManager.getByEmail(username).get();
|
||||||
|
|
||||||
|
FacesContext facesContext = FacesContext.getCurrentInstance();
|
||||||
|
HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);
|
||||||
|
session.setAttribute("user", this);
|
||||||
|
session.setAttribute("realUsername", username);
|
||||||
|
|
||||||
|
if (securityContext.isCallerInRole(UserGroup.ADMIN.toString())) {
|
||||||
|
LOGGER.info("Login succesfull " + username + " with role: ADMIN");
|
||||||
|
return "admin/welcome.xhtml?faces-redirect=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (securityContext.isCallerInRole(UserGroup.USER.toString())) {
|
||||||
|
LOGGER.info("Login succesfull " + username + " with role: USER");
|
||||||
|
return "user/welcome.xhtml?faces-redirect=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (securityContext.isCallerInRole(UserGroup.CUSTOMER.toString())) {
|
||||||
|
LOGGER.info("Login succesfull " + username + " with role: USER");
|
||||||
|
return "customer/welcome.xhtml?faces-redirect=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
redirect("index.xhtml");
|
||||||
|
|
||||||
|
} else if (status.equals(SEND_FAILURE)) {
|
||||||
|
|
||||||
|
sendErrorMessage("Fehler!", "Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut!.");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
} catch (InvalidPasswordException | InvalidEmailException e) {
|
||||||
|
LOGGER.info("Wrong Email or Password: " + username);
|
||||||
|
sendErrorMessage("Fehler!", "Falsche Email oder Passwort!");
|
||||||
|
return "";
|
||||||
|
} catch (PersonInaktiveException p){
|
||||||
|
sendErrorMessage("Fehler!", " Ihr Konto ist inatkiv. Bitte wenden Sie sich an den Administator.");
|
||||||
|
return "";
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Login error with " + e);
|
||||||
|
sendErrorMessage("Fehler!", "Ein Fehler ist aufgetreten, bitte versuchen Sie es erneut!");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamedContent getImage() {
|
||||||
|
if (activePerson == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
UserPicture picture = activePerson.getUserPicture();
|
||||||
|
|
||||||
|
return DefaultStreamedContent.builder()
|
||||||
|
.contentType(picture == null ? null : picture.getMime().getMimeType())
|
||||||
|
.stream(() -> {
|
||||||
|
if (picture == null || picture.getFileData() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new ByteArrayInputStream(picture.getFileData());
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
LOGGER.error(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPicture(){
|
||||||
|
return activePerson.getUserPicture() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String logout() {
|
||||||
|
LOGGER.info("User is logging out: " + username);
|
||||||
|
try {
|
||||||
|
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
|
||||||
|
managedPerson.removeLogin(username);
|
||||||
|
activePerson = null;
|
||||||
|
redirect("index.xhtml");
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("couldn't logout " + username + "with:" + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "index.xhtml";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveActivePerson(){
|
||||||
|
personManager.refresh(activePerson);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reloadActivePerson() {
|
||||||
|
this.activePerson = personManager.load(activePerson);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRememberMe() {
|
||||||
|
return rememberMe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRememberMe(boolean rememberMe) {
|
||||||
|
this.rememberMe = rememberMe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person getActiveUser() {
|
||||||
|
return activePerson;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActiveUser(Person activeUser) {
|
||||||
|
this.activePerson = activeUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getLogins() {
|
||||||
|
return managedPerson.getLogins();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package controller.person;
|
||||||
|
|
||||||
|
import controller.AbstractController;
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import model.person.Person;
|
||||||
|
import model.person.enums.Call;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Named
|
||||||
|
@RequestScoped
|
||||||
|
public class PersonEditController extends AbstractController{
|
||||||
|
@Inject
|
||||||
|
PersonController personController;
|
||||||
|
|
||||||
|
private String email;
|
||||||
|
private Call call;
|
||||||
|
private String telefon;
|
||||||
|
private String password;
|
||||||
|
private String mobile;
|
||||||
|
private String fax;
|
||||||
|
private String firstname;
|
||||||
|
private String lastname;
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
public PersonEditController() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
private void loadUserdata(){
|
||||||
|
Person activePerson = personController.getActiveUser();
|
||||||
|
|
||||||
|
email = activePerson.getEmail();
|
||||||
|
call = activePerson.getCall();
|
||||||
|
telefon = activePerson.getTelefon();
|
||||||
|
password = "********";
|
||||||
|
mobile = activePerson.getMobile();
|
||||||
|
fax = activePerson.getFax();
|
||||||
|
firstname = activePerson.getFirstname();
|
||||||
|
lastname = activePerson.getLastname();
|
||||||
|
title = activePerson.getTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Call getCall() {
|
||||||
|
return call;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCall(Call call) {
|
||||||
|
this.call = call;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTelefon() {
|
||||||
|
return telefon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTelefon(String telefon) {
|
||||||
|
this.telefon = telefon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMobile() {
|
||||||
|
return mobile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMobile(String mobile) {
|
||||||
|
this.mobile = mobile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFax() {
|
||||||
|
return fax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFax(String fax) {
|
||||||
|
this.fax = fax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstname() {
|
||||||
|
return firstname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstname(String firstname) {
|
||||||
|
this.firstname = firstname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastname() {
|
||||||
|
return lastname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastname(String lastname) {
|
||||||
|
this.lastname = lastname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package controller.person;
|
||||||
|
|
||||||
|
import business.user.PersonManager;
|
||||||
|
import business.user.UserPictureManager;
|
||||||
|
import controller.AbstractController;
|
||||||
|
import javax.ejb.EJB;
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import model.files.Mime;
|
||||||
|
import model.files.UserPicture;
|
||||||
|
import model.person.Person;
|
||||||
|
import org.primefaces.event.FileUploadEvent;
|
||||||
|
import org.primefaces.model.file.UploadedFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Named
|
||||||
|
@RequestScoped
|
||||||
|
public class UserPictureController extends AbstractController {
|
||||||
|
|
||||||
|
private UserPicture picture;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PersonController personController;
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
UserPictureManager upManager;
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
PersonManager personManager;
|
||||||
|
|
||||||
|
public void handleUserPictureUpload(FileUploadEvent event) {
|
||||||
|
UploadedFile file = event.getFile();
|
||||||
|
|
||||||
|
if (file != null && file.getContent() != null && file.getContent().length > 0 && file.getFileName() != null) {
|
||||||
|
|
||||||
|
if (createSaveUserPicture(file)) {
|
||||||
|
sendInfoMessage("Erfolg", this.picture.getName() + " wurde hochgeladen!");
|
||||||
|
} else {
|
||||||
|
sendErrorMessage("Fehler", "Es ist ein Fehler aufgetreten. Bitte Versuchen Sie es erneut!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean createSaveUserPicture(UploadedFile file) {
|
||||||
|
picture = null;
|
||||||
|
picture = personController.getActiveUser().getUserPicture();
|
||||||
|
boolean isNew = picture == null;
|
||||||
|
|
||||||
|
if (isNew) {
|
||||||
|
picture = new UserPicture();
|
||||||
|
}
|
||||||
|
|
||||||
|
setData(picture, file);
|
||||||
|
Person person = personManager.load(personController.getActiveUser());
|
||||||
|
person.setUserPicture(picture);
|
||||||
|
picture.setPerson(person);
|
||||||
|
|
||||||
|
if (isNew) {
|
||||||
|
upManager.create(picture);
|
||||||
|
} else {
|
||||||
|
upManager.edit(picture);
|
||||||
|
}
|
||||||
|
|
||||||
|
personManager.save(person);
|
||||||
|
personController.reloadActivePerson();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setData(UserPicture picture, UploadedFile file) {
|
||||||
|
picture.setName(file.getFileName());
|
||||||
|
picture.setFileData(file.getContent());
|
||||||
|
picture.setMime(Mime.getByMimeType(file.getContentType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getMaxFileSize() {
|
||||||
|
return UserPicture.getSizeLimit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileTypesRE() {
|
||||||
|
return UserPicture.getAllowedTypesRE();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package exception;
|
||||||
|
|
||||||
|
import javax.ejb.ApplicationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@ApplicationException(rollback = true)
|
||||||
|
public abstract class AbstractBusinessException extends RuntimeException {
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
public class InvalidCredentialException extends AbstractBusinessException{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
public class InvalidEmailException extends AbstractBusinessException {
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
public class InvalidPasswordException extends AbstractBusinessException {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
public class PersonInaktiveException extends AbstractBusinessException{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package httpauthenticationmechanism;
|
||||||
|
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
import javax.security.enterprise.credential.CallerOnlyCredential;
|
||||||
|
import javax.security.enterprise.credential.Credential;
|
||||||
|
import javax.security.enterprise.credential.UsernamePasswordCredential;
|
||||||
|
import javax.security.enterprise.identitystore.CredentialValidationResult;
|
||||||
|
import static javax.security.enterprise.identitystore.CredentialValidationResult.INVALID_RESULT;
|
||||||
|
import static javax.security.enterprise.identitystore.CredentialValidationResult.NOT_VALIDATED_RESULT;
|
||||||
|
import javax.security.enterprise.identitystore.IdentityStore;
|
||||||
|
|
||||||
|
import business.user.PersonManager;
|
||||||
|
import exception.InvalidCredentialException;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import javax.ejb.EJB;
|
||||||
|
import model.person.Person;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@ApplicationScoped
|
||||||
|
public class AppIdentityStore implements IdentityStore {
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
PersonManager userManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int priority() {
|
||||||
|
return 90;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CredentialValidationResult validate(Credential credential) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
// check if the credential was UsernamePasswordCredential
|
||||||
|
if (credential instanceof UsernamePasswordCredential) {
|
||||||
|
String username = ((UsernamePasswordCredential) credential).getCaller();
|
||||||
|
String password = ((UsernamePasswordCredential) credential).getPasswordAsString();
|
||||||
|
|
||||||
|
return validate(this.userManager.getByEmailAndPassword(username, password));
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the credential was CallerOnlyCredential
|
||||||
|
if (credential instanceof CallerOnlyCredential) {
|
||||||
|
String username = ((CallerOnlyCredential) credential).getCaller();
|
||||||
|
|
||||||
|
return validate(
|
||||||
|
this.userManager.getByEmail(username)
|
||||||
|
.orElseThrow(InvalidCredentialException::new)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (InvalidCredentialException e) {
|
||||||
|
return INVALID_RESULT;
|
||||||
|
}
|
||||||
|
return NOT_VALIDATED_RESULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CredentialValidationResult validate(Person person) {
|
||||||
|
Set<String> groups;
|
||||||
|
|
||||||
|
groups = person.getUserGroups().stream()
|
||||||
|
.map(gr -> gr.toString())
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
return new CredentialValidationResult(person.getEmail(), groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package httpauthenticationmechanism;
|
||||||
|
|
||||||
|
import static javax.security.enterprise.identitystore.CredentialValidationResult.INVALID_RESULT;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.ejb.EJB;
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.security.enterprise.CallerPrincipal;
|
||||||
|
import javax.security.enterprise.credential.RememberMeCredential;
|
||||||
|
import javax.security.enterprise.identitystore.CredentialValidationResult;
|
||||||
|
import javax.security.enterprise.identitystore.RememberMeIdentityStore;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import business.user.TokenManager;
|
||||||
|
import business.user.PersonManager;
|
||||||
|
import model.person.Person;
|
||||||
|
import static model.person.enums.TokenType.REMEMBER_ME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@ApplicationScoped
|
||||||
|
public class AppRememberMeIdentityStore implements RememberMeIdentityStore {
|
||||||
|
@Inject
|
||||||
|
HttpServletRequest request;
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
PersonManager userManager;
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
TokenManager tokenManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CredentialValidationResult validate(RememberMeCredential rmc) {
|
||||||
|
Optional<Person> user = this.userManager.getByLoginToken(rmc.getToken(), REMEMBER_ME);
|
||||||
|
|
||||||
|
if (user.isPresent()) {
|
||||||
|
return new CredentialValidationResult(user.get().getEmail());
|
||||||
|
} else {
|
||||||
|
return INVALID_RESULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generateLoginToken(CallerPrincipal cp, Set<String> set) {
|
||||||
|
return this.tokenManager.generate(cp.getName(), getRemoteAddr(request), getDescription(), REMEMBER_ME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeLoginToken(String string) {
|
||||||
|
this.tokenManager.remove(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRemoteAddr(HttpServletRequest request){
|
||||||
|
return request.getRemoteAddr();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDescription() {
|
||||||
|
return "Remember me session: " + this.request.getHeader("User-Agent");
|
||||||
|
}
|
||||||
|
}
|
||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
package httpauthenticationmechanism;
|
||||||
|
|
||||||
|
import business.user.PersonManager;
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.ejb.EJB;
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.security.enterprise.AuthenticationStatus;
|
||||||
|
import javax.security.enterprise.authentication.mechanism.http.AutoApplySession;
|
||||||
|
import javax.security.enterprise.authentication.mechanism.http.CustomFormAuthenticationMechanismDefinition;
|
||||||
|
import javax.security.enterprise.authentication.mechanism.http.HttpAuthenticationMechanism;
|
||||||
|
import javax.security.enterprise.authentication.mechanism.http.HttpMessageContext;
|
||||||
|
import javax.security.enterprise.authentication.mechanism.http.LoginToContinue;
|
||||||
|
import javax.security.enterprise.authentication.mechanism.http.RememberMe;
|
||||||
|
import javax.security.enterprise.credential.Credential;
|
||||||
|
import javax.security.enterprise.identitystore.IdentityStore;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@AutoApplySession // For "Is user already logged-in?"
|
||||||
|
@RememberMe(
|
||||||
|
cookieMaxAgeSeconds = 60 * 60 * 24 * 14, // 14 days
|
||||||
|
cookieSecureOnly = false, // Remove this when login is served over HTTPS.
|
||||||
|
isRememberMeExpression = "#{self.isRememberMe(httpMessageContext)}"
|
||||||
|
)
|
||||||
|
@LoginToContinue(
|
||||||
|
loginPage = "/index.xhtml",
|
||||||
|
errorPage = "/error.xhtml",
|
||||||
|
useForwardToLogin = true
|
||||||
|
)
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ApplicationConfig implements HttpAuthenticationMechanism{
|
||||||
|
|
||||||
|
final static Logger LOGGER = LogManager.getLogger(ApplicationConfig.class);
|
||||||
|
|
||||||
|
public ApplicationConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private IdentityStore identityStore;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ManagedPerson managedPerson;
|
||||||
|
|
||||||
|
@EJB
|
||||||
|
private PersonManager personManager;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
private void init(){
|
||||||
|
managedPerson.getLogins();
|
||||||
|
personManager.demo();
|
||||||
|
|
||||||
|
System.out.println("PostConstruct DEMO");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationStatus validateRequest(HttpServletRequest req, HttpServletResponse res, HttpMessageContext context) {
|
||||||
|
|
||||||
|
Credential credential = context.getAuthParameters().getCredential();
|
||||||
|
|
||||||
|
if (credential != null) {
|
||||||
|
return context.notifyContainerAboutLogin(this.identityStore.validate(credential));
|
||||||
|
} else {
|
||||||
|
return context.doNothing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this was called on @RememberMe annotations
|
||||||
|
public Boolean isRememberMe(HttpMessageContext httpMessageContext) {
|
||||||
|
return httpMessageContext.getAuthParameters().isRememberMe();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanSubject(HttpServletRequest request, HttpServletResponse response, HttpMessageContext httpMessageContext) {
|
||||||
|
HttpAuthenticationMechanism.super.cleanSubject(request, response, httpMessageContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package httpauthenticationmechanism;
|
||||||
|
|
||||||
|
import javax.servlet.annotation.WebListener;
|
||||||
|
import javax.servlet.http.HttpSessionEvent;
|
||||||
|
import javax.servlet.http.HttpSessionListener;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import controller.person.PersonController;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@WebListener
|
||||||
|
public class LogoutListener implements HttpSessionListener{
|
||||||
|
final static Logger LOGGER = LogManager.getLogger(LogoutListener.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sessionCreated(HttpSessionEvent event) {
|
||||||
|
// NOOP.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sessionDestroyed(HttpSessionEvent event) {
|
||||||
|
LOGGER.info("Session destroyed");
|
||||||
|
PersonController userManager = (PersonController) event.getSession().getAttribute("user");
|
||||||
|
String username = (String) event.getSession().getAttribute("realUsername");
|
||||||
|
if (userManager != null && username != null) {
|
||||||
|
LOGGER.info("not nulls");
|
||||||
|
userManager.getLogins().remove(username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package httpauthenticationmechanism;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@Named(value = "managedPerson")
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ManagedPerson {
|
||||||
|
|
||||||
|
private Set<String> logins;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of ManagedCustomer
|
||||||
|
*/
|
||||||
|
public ManagedPerson() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getLogins(){
|
||||||
|
if (this.logins == null) {
|
||||||
|
this.logins = new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.logins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLogin(String user){
|
||||||
|
getLogins().add(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeLogin(String user){
|
||||||
|
getLogins().remove(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package model;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick Plate
|
||||||
|
*/
|
||||||
|
@MappedSuperclass
|
||||||
|
public class AbstractEntity implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private LocalDateTime changedDate;
|
||||||
|
|
||||||
|
private LocalDateTime creationDate;
|
||||||
|
|
||||||
|
private boolean outdated;
|
||||||
|
|
||||||
|
public AbstractEntity() {
|
||||||
|
this.creationDate = LocalDateTime.now();
|
||||||
|
this.changedDate = this.creationDate;
|
||||||
|
this.outdated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 0;
|
||||||
|
hash += (id != null ? id.hashCode() : 0);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
if (object == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(object.getClass() == this.getClass())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AbstractEntity other = (AbstractEntity) object;
|
||||||
|
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOutdated() {
|
||||||
|
return outdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutdated(boolean outdated) {
|
||||||
|
this.outdated = outdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getChangedDate() {
|
||||||
|
return changedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChangedDate(LocalDateTime changedDate) {
|
||||||
|
this.changedDate = changedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreationDate (LocalDateTime creationDate) {
|
||||||
|
this.creationDate = creationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getCreationDate() {
|
||||||
|
return creationDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
package model.adresses;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@MappedSuperclass
|
||||||
|
public class Address extends AbstractEntity{
|
||||||
|
|
||||||
|
//Land
|
||||||
|
@NotNull(message = "Land darf nicht null sein")
|
||||||
|
private String country;
|
||||||
|
|
||||||
|
//Straßenname
|
||||||
|
@NotNull(message = "Strasse darf nicht null sein")
|
||||||
|
private String street;
|
||||||
|
|
||||||
|
//Hausnummer
|
||||||
|
@NotNull(message = "Hausnummer darf nicht null sein")
|
||||||
|
private String number;
|
||||||
|
|
||||||
|
//Zusatz
|
||||||
|
private String extra;
|
||||||
|
|
||||||
|
//PLZ
|
||||||
|
@NotNull(message = "PLZ darf nicht null sein")
|
||||||
|
private Integer postnumber;
|
||||||
|
|
||||||
|
//Bundesland
|
||||||
|
@NotNull(message = "Bundesland darf nicht null sein")
|
||||||
|
private String county;
|
||||||
|
|
||||||
|
//Ort
|
||||||
|
@NotNull(message = "Ort darf nicht null sein")
|
||||||
|
private String place;
|
||||||
|
|
||||||
|
private String contact;
|
||||||
|
|
||||||
|
private String comment;
|
||||||
|
|
||||||
|
public Address() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(String street, String number, String extra, Integer postnumber, String county, String place) {
|
||||||
|
this.street = street;
|
||||||
|
this.number = number;
|
||||||
|
this.extra = extra;
|
||||||
|
this.postnumber = postnumber;
|
||||||
|
this.county = county;
|
||||||
|
this.place = place;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(String country, String street, String number, String extra, Integer postnumber, String county, String place) {
|
||||||
|
this.country = country;
|
||||||
|
this.street = street;
|
||||||
|
this.number = number;
|
||||||
|
this.extra = extra;
|
||||||
|
this.postnumber = postnumber;
|
||||||
|
this.county = county;
|
||||||
|
this.place = place;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(String country, String street, String number, String extra, Integer postnumber, String county, String place, String contact, String comment) {
|
||||||
|
this.country = country;
|
||||||
|
this.street = street;
|
||||||
|
this.number = number;
|
||||||
|
this.extra = extra;
|
||||||
|
this.postnumber = postnumber;
|
||||||
|
this.county = county;
|
||||||
|
this.place = place;
|
||||||
|
this.contact = contact;
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(Address toCopyAddress){
|
||||||
|
this.country = toCopyAddress.getCountry();
|
||||||
|
this.street = toCopyAddress.getStreet();
|
||||||
|
this.number = toCopyAddress.getNumber();
|
||||||
|
this.extra = toCopyAddress.getExtra();
|
||||||
|
this.postnumber = toCopyAddress.getPostnumber();
|
||||||
|
this.county = toCopyAddress.getCounty();
|
||||||
|
this.place = toCopyAddress.getPlace();
|
||||||
|
this.contact = toCopyAddress.getContact();
|
||||||
|
this.comment = toCopyAddress.getComment();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 7;
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.country);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.street);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.number);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.extra);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.postnumber);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.county);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.place);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.contact);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.comment);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Address other = (Address) obj;
|
||||||
|
if (!Objects.equals(this.country, other.country)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.street, other.street)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.number, other.number)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.extra, other.extra)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.county, other.county)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.place, other.place)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.comment, other.comment)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Objects.equals(this.postnumber, other.postnumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStreet() {
|
||||||
|
return street;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStreet(String street) {
|
||||||
|
this.street = street;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNumber() {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNumber(String number) {
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExtra() {
|
||||||
|
return extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExtra(String extra) {
|
||||||
|
this.extra = extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPostnumber() {
|
||||||
|
return postnumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPostnumber(Integer postnumber) {
|
||||||
|
this.postnumber = postnumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCounty() {
|
||||||
|
return county;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCounty(String county) {
|
||||||
|
this.county = county;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlace() {
|
||||||
|
return place;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlace(String place) {
|
||||||
|
this.place = place;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCountry() {
|
||||||
|
return country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCountry(String country) {
|
||||||
|
this.country = country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContact() {
|
||||||
|
return contact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContact(String contact) {
|
||||||
|
this.contact = contact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComment(String comment) {
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.adresses;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import model.company.Company;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class CompanyBillingAddress extends Address{
|
||||||
|
@ManyToOne
|
||||||
|
private Company company;
|
||||||
|
|
||||||
|
private boolean delivery;
|
||||||
|
|
||||||
|
public CompanyBillingAddress() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompanyBillingAddress(Company company, boolean delivery) {
|
||||||
|
this.company = company;
|
||||||
|
this.delivery = delivery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompanyBillingAddress(Company company, boolean delivery,String country, String street, String number, String extra, Integer postnumber, String county, String place) {
|
||||||
|
super(country, street, number, extra, postnumber, county, place);
|
||||||
|
this.company = company;
|
||||||
|
this.delivery = delivery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Company getCompany() {
|
||||||
|
return company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompany(Company company) {
|
||||||
|
this.company = company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDelivery() {
|
||||||
|
return delivery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDelivery(boolean delivery) {
|
||||||
|
this.delivery = delivery;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.adresses;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
import model.company.Location;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class LocationAddress extends Address {
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
private Location location;
|
||||||
|
|
||||||
|
public LocationAddress() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocation(Location location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.company;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
import model.adresses.CompanyBillingAddress;
|
||||||
|
import model.customer.Customer;
|
||||||
|
import model.ticket.Ticket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Company extends AbstractEntity {
|
||||||
|
|
||||||
|
public static final String FIND_BY_NAME = "Company.findByName";
|
||||||
|
public static final String FIND_BY_STEUERID = "Company.findBySteuerID";
|
||||||
|
public static final String FIND_BY_UMSATZSTEUERID = "Company.findByUmsatzsteuerID";
|
||||||
|
public static final String FIND_BY_CUSTOMER = "Company.findByCustomer";
|
||||||
|
public static final String FIND_BY_ADDRESS = "Company.findByAddress";
|
||||||
|
public static final String FIND_BY_DELIVERYADDRESS = "Company.findByLocation";
|
||||||
|
|
||||||
|
@Column(unique = true, nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(unique = true, nullable = true)
|
||||||
|
private String steuerNr;
|
||||||
|
|
||||||
|
@Column(unique = true, nullable = true)
|
||||||
|
private String umsatzSteuerID;
|
||||||
|
|
||||||
|
@Column(unique = true, nullable = true)
|
||||||
|
private String kundenNr;
|
||||||
|
|
||||||
|
@Column(unique = false, nullable = true)
|
||||||
|
private String headerInspection;
|
||||||
|
|
||||||
|
@Column(unique = false, nullable = true)
|
||||||
|
private String headerService;
|
||||||
|
|
||||||
|
@Column(unique = false, nullable = false)
|
||||||
|
@Enumerated(EnumType.ORDINAL)
|
||||||
|
private Status status;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
|
||||||
|
private Set<CompanyBillingAddress> addresses;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
|
||||||
|
private Set<Location> locations;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "company", cascade = {
|
||||||
|
CascadeType.MERGE,
|
||||||
|
CascadeType.REFRESH
|
||||||
|
})
|
||||||
|
private Set<Customer> customers;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "company")
|
||||||
|
private List<Ticket> tickets;
|
||||||
|
|
||||||
|
public Company() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSteuerNr() {
|
||||||
|
return steuerNr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSteuerNr(String steuerNr) {
|
||||||
|
this.steuerNr = steuerNr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUmsatzSteuerID() {
|
||||||
|
return umsatzSteuerID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUmsatzSteuerID(String umsatzSteuerID) {
|
||||||
|
this.umsatzSteuerID = umsatzSteuerID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKundenNr() {
|
||||||
|
return kundenNr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKundenNr(String kundenNr) {
|
||||||
|
this.kundenNr = kundenNr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHeaderInspection() {
|
||||||
|
return headerInspection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeaderInspection(String headerInspection) {
|
||||||
|
this.headerInspection = headerInspection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHeaderService() {
|
||||||
|
return headerService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeaderService(String headerService) {
|
||||||
|
this.headerService = headerService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<CompanyBillingAddress> getAddresses() {
|
||||||
|
return addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddresses(Set<CompanyBillingAddress> addresses) {
|
||||||
|
this.addresses = addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Location> getLocations() {
|
||||||
|
return locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocations(Set<Location> locations) {
|
||||||
|
this.locations = locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Customer> getCustomers() {
|
||||||
|
return customers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomers(Set<Customer> customers) {
|
||||||
|
this.customers = customers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Ticket> getTickets() {
|
||||||
|
return tickets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTickets(List<Ticket> tickets) {
|
||||||
|
this.tickets = tickets;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.company;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
import model.adresses.LocationAddress;
|
||||||
|
import model.customer.Customer;
|
||||||
|
import model.machine.Machine;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Location extends AbstractEntity{
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Company company;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
private LocationAddress address;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "location")
|
||||||
|
private Set<Machine> machines;
|
||||||
|
|
||||||
|
@ManyToMany
|
||||||
|
private Set<Customer> contacts;
|
||||||
|
|
||||||
|
public Location() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Company getCompany() {
|
||||||
|
return company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompany(Company company) {
|
||||||
|
this.company = company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationAddress getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddress(LocationAddress address) {
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Machine> getMachines() {
|
||||||
|
return machines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMachines(Set<Machine> machines) {
|
||||||
|
this.machines = machines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Customer> getContacts() {
|
||||||
|
return contacts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContacts(Set<Customer> contacts) {
|
||||||
|
this.contacts = contacts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.company;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
public enum Status {
|
||||||
|
ACTIVE,
|
||||||
|
INACTIVE;
|
||||||
|
|
||||||
|
private Status() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
switch(this){
|
||||||
|
case ACTIVE:
|
||||||
|
return "aktiv";
|
||||||
|
case INACTIVE:
|
||||||
|
return "inaktiv";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toLanguageString(Locale locale){
|
||||||
|
if (locale == null ||locale.equals(Locale.GERMAN) || locale.equals(Locale.GERMANY)) {
|
||||||
|
return getGerman();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locale.equals(Locale.ENGLISH)) {
|
||||||
|
getEnglish();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getGerman() {
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getEnglish(){
|
||||||
|
switch(this){
|
||||||
|
case ACTIVE:
|
||||||
|
return "active";
|
||||||
|
case INACTIVE:
|
||||||
|
return "inactive";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.customer;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import model.person.Person;
|
||||||
|
import model.company.Company;
|
||||||
|
import model.company.Location;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Customer extends Person{
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Company company;
|
||||||
|
|
||||||
|
@ManyToMany
|
||||||
|
private Set<Location> locations;
|
||||||
|
|
||||||
|
@Column(nullable = true, length = 210)
|
||||||
|
private String note;
|
||||||
|
|
||||||
|
public Customer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Customer(Company company) {
|
||||||
|
this.company = company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Company getCompany() {
|
||||||
|
return company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompany(Company company) {
|
||||||
|
this.company = company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Location> getLocations() {
|
||||||
|
return locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocations(Set<Location> locations) {
|
||||||
|
this.locations = locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNote() {
|
||||||
|
return note;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNote(String note) {
|
||||||
|
this.note = note;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.files;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.Lob;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@MappedSuperclass
|
||||||
|
public class FileDB extends AbstractEntity{
|
||||||
|
@Column(nullable = false, length = 100)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Mime mime;
|
||||||
|
|
||||||
|
@Lob
|
||||||
|
private byte[] fileData;
|
||||||
|
|
||||||
|
public FileDB() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getFileData() {
|
||||||
|
return fileData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileData(byte[] fileData) {
|
||||||
|
this.fileData = fileData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mime getMime() {
|
||||||
|
return mime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMime(Mime mime) {
|
||||||
|
this.mime = mime;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.files;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import model.ticket.Ticket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Invoice extends FileDB {
|
||||||
|
@ManyToOne
|
||||||
|
private Ticket ticket;
|
||||||
|
|
||||||
|
public Invoice() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Invoice(Ticket ticket) {
|
||||||
|
this.ticket = ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Ticket getTicket() {
|
||||||
|
return ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTicket(Ticket ticket) {
|
||||||
|
this.ticket = ticket;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.files;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
public enum Mime {
|
||||||
|
AAC("aac", "AAC audio", "audio/aac"),
|
||||||
|
ABW("abw", "AbiWord document", "application/x-abiword"),
|
||||||
|
ARC("arc", "Archive document (multiple files embedded)", "application/x-freearc"),
|
||||||
|
AVI("avi", "AVI: Audio Video Interleave", "video/x-msvideo"),
|
||||||
|
AZW("azw", "Amazon Kindle eBook format", "application/vnd.amazon.ebook"),
|
||||||
|
BIN("bin", "Any kind of binary data", "application/octet-stream"),
|
||||||
|
BMP("bmp", "Windows OS/2 Bitmap Graphics", "image/bmp"),
|
||||||
|
BZ("bz", "BZip archive", "application/x-bzip"),
|
||||||
|
BZ2("bz2", "BZip2 archive", "application/x-bzip2"),
|
||||||
|
CDA("cda", "CD audio", "application/x-cdf"),
|
||||||
|
CSH("csh", "C-Shell script", "application/x-csh"),
|
||||||
|
CSS("css", "Cascading Style Sheets (CSS)", "text/css"),
|
||||||
|
CSV("csv", "Comma-separated values (CSV", "text/csv"),
|
||||||
|
DOC("doc", "Microsoft Word", "application/msword"),
|
||||||
|
DOCX("docx", "Microsoft Word (OpenXML)", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
|
||||||
|
EOT("eot", "MS Embedded OpenType fonts", "application/vnd.ms-fontobject"),
|
||||||
|
EPUB("epub", "Electronic publication (EPUB)", "application/epub+zip"),
|
||||||
|
GZ("gz", "GZip Compressed Archive", "application/gzip"),
|
||||||
|
GIF("gif", "Graphics Interchange Format (GIF)", "image/gif"),
|
||||||
|
HTM("htm", "HyperText Markup Language (HTML)", "text/html"),
|
||||||
|
HTML("html", "HyperText Markup Language (HTML)", "text/html"),
|
||||||
|
ICO("ico", "Icon format", "image/vnd.microsoft.icon"),
|
||||||
|
ICS("ics", "iCalendar format", "text/calendar"),
|
||||||
|
JAR("jar", "Java Archive (JAR)", "application/java-archive"),
|
||||||
|
JPG("jpg", "JPEG images", "image/jpeg"),
|
||||||
|
JPEG("jpeg", "JPEG images", "image/jpeg"),
|
||||||
|
JS("js", "JavaScript", "text/javascript"),
|
||||||
|
JSON("json", "JSON format", "application/json"),
|
||||||
|
JSONLD("jsonld", "JSON-LD format", "application/ld+json"),
|
||||||
|
MID("mid", "Musical Instrument Digital Interface (MIDI)", "audio/midi"),
|
||||||
|
MIDI("midi", "Musical Instrument Digital Interface (MIDI)", "audio/midi"),
|
||||||
|
MJS("mjs", "JavaScript module", "text/javascript"),
|
||||||
|
MP3("mp3", "MP3 audio", "audio/mpeg"),
|
||||||
|
MP4("mp4", "MP4 video", "video/mp4"),
|
||||||
|
MPEG("mpeg", "MPEG Video", "video/mpeg"),
|
||||||
|
MPKG("mpkg", "Apple Installer Package", "application/vnd.apple.installer+xml"),
|
||||||
|
ODP("odp", "OpenDocument presentation document", "application/vnd.oasis.opendocument.presentation"),
|
||||||
|
ODS("ods", "OpenDocument spreadsheet document", "application/vnd.oasis.opendocument.spreadsheet"),
|
||||||
|
ODT("odt", "OpenDocument text document", "application/vnd.oasis.opendocument.text"),
|
||||||
|
OGA("oga", "OGG audio", "audio/ogg"),
|
||||||
|
OGV("ogv", "OGG video", "video/ogg"),
|
||||||
|
OGX("ogx", "OGG", "application/ogg"),
|
||||||
|
OPUUS("opus", "Opus audio", "audio/opus"),
|
||||||
|
OTF("otf", "OpenType font", "font/otf"),
|
||||||
|
PNG("png", "Portable Network Graphics", "image/png"),
|
||||||
|
PDF("pdf", "Adobe Portable Document Format (PDF)", "application/pdf"),
|
||||||
|
PHP("php", "Hypertext Preprocessor (Personal Home Page)", "application/x-httpd-php"),
|
||||||
|
PPT("ppt", "Microsoft PowerPoint", "application/vnd.ms-powerpoint"),
|
||||||
|
PPTX("pptx", "Microsoft PowerPoint (OpenXML)", "application/vnd.openxmlformats-officedocument.presentationml.presentation"),
|
||||||
|
RAR("rar", "RAR archive", "application/vnd.rar"),
|
||||||
|
RTF("rtf", "Rich Text Format (RTF)", "application/rtf"),
|
||||||
|
SH("sh", "Bourne shell script", "application/x-sh"),
|
||||||
|
SVG("svg", "Scalable Vector Graphics (SVG)", "image/svg+xml"),
|
||||||
|
SWF("swf", "Small web format (SWF) or Adobe Flash document", "application/x-shockwave-flash"),
|
||||||
|
TAR("tar", "Tape Archive (TAR)", "application/x-tar"),
|
||||||
|
TIF("tif", "Tagged Image File Format (TIFF)", "image/tiff"),
|
||||||
|
TIFF("tiff", "Tagged Image File Format (TIFF)", "image/tiff"),
|
||||||
|
TS("ts", "MPEG transport stream", "video/mp2t"),
|
||||||
|
TTF("ttf", "TrueType Font", "font/ttf"),
|
||||||
|
TXT("txt", "Text, (generally ASCII or ISO 8859-n)", "text/plain"),
|
||||||
|
VSD("vsd", "Microsoft Visio", "application/vnd.visio"),
|
||||||
|
WAV("wav", "Waveform Audio Format", "audio/wav"),
|
||||||
|
WEBA("weba", "WEBM audio", "audio/webm"),
|
||||||
|
WEBM("webm", "WEBM video", "video/webm"),
|
||||||
|
WEBP("webp", "WEBP image", "image/webp"),
|
||||||
|
WOFF("woff", "Web Open Font Format (WOFF)", "font/woff"),
|
||||||
|
WOFF2("woff2", "Web Open Font Format (WOFF)", "font/woff2"),
|
||||||
|
XHTML("xhtml", "XHTML", "application/xhtml+xml"),
|
||||||
|
XLS("xls", "Microsoft Excel", "application/vnd.ms-excel"),
|
||||||
|
XLSX("xlsx", "Microsoft Excel (OpenXML)", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
|
||||||
|
XML("xml", "XML", "application/xml"),
|
||||||
|
XUL("xul", "XUL", "application/vnd.mozilla.xul+xml"),
|
||||||
|
ZIP("zip", "ZIP archive", "application/zip"),
|
||||||
|
GP3V("3gp", "3GPP audio/video container", "video/3gpp"),
|
||||||
|
GP3A("3gp", "3GPP audio/video container", "audio/3gpp"),
|
||||||
|
G23V("3g2", "3GPP2 audio/video container", "video/3gpp2"),
|
||||||
|
G23A("3g2", "3GPP2 audio/video container", "audio/3gpp2"),
|
||||||
|
Z7("7z", "7-zip archive", "application/x-7z-compressed");
|
||||||
|
|
||||||
|
private final String extension;
|
||||||
|
private final String kindOfDocument;
|
||||||
|
private final String mimeType;
|
||||||
|
|
||||||
|
private Mime(String extension, String kindOfDocument, String mimeType) {
|
||||||
|
this.extension = extension;
|
||||||
|
this.kindOfDocument = kindOfDocument;
|
||||||
|
this.mimeType = mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Mime getByMimeType(String mimetype){
|
||||||
|
if (mimetype == null || mimetype.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Mime value : Mime.values()) {
|
||||||
|
if (mimetype.equals(value.getMimeType())) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExtension() {
|
||||||
|
return extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKindOfDocument() {
|
||||||
|
return kindOfDocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMimeType() {
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.files;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import model.ticket.Ticket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Report extends FileDB{
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Ticket ticket;
|
||||||
|
|
||||||
|
public Report() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Ticket getTicket() {
|
||||||
|
return ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTicket(Ticket ticket) {
|
||||||
|
this.ticket = ticket;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.files;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
import model.person.Person;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class UserPicture extends FileDB{
|
||||||
|
private static List<Mime> allowedFileTypes = Arrays.asList(Mime.JPEG, Mime.JPG, Mime.PNG, Mime.BMP, Mime.PNG);
|
||||||
|
private static long sizeLimit = 2000000L;
|
||||||
|
|
||||||
|
@OneToOne(optional = false, cascade = {CascadeType.MERGE, CascadeType.REFRESH})
|
||||||
|
private Person person;
|
||||||
|
|
||||||
|
public UserPicture() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getAllowedTypesRE(){
|
||||||
|
StringBuilder output = new StringBuilder(allowedFileTypes.size() * 4);
|
||||||
|
|
||||||
|
output.append("/(\\.|\\/)(");
|
||||||
|
|
||||||
|
for(int i = 0; i < allowedFileTypes.size(); i++){
|
||||||
|
output.append(allowedFileTypes.get(i).getExtension());
|
||||||
|
if (i < allowedFileTypes.size() -1) {
|
||||||
|
output.append('|');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output.append(")$/");
|
||||||
|
|
||||||
|
return output.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Mime> getAllowedFileTypes() {
|
||||||
|
return allowedFileTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setAllowedFileTypes(List<Mime> allowedFileTypes) {
|
||||||
|
UserPicture.allowedFileTypes = allowedFileTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getSizeLimit() {
|
||||||
|
return sizeLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSizeLimit(long sizeLimit) {
|
||||||
|
UserPicture.sizeLimit = sizeLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person getPerson() {
|
||||||
|
return person;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPerson(Person person) {
|
||||||
|
this.person = person;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.machine;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
import model.company.Location;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Machine extends AbstractEntity {
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Location location;
|
||||||
|
|
||||||
|
public Machine() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocation(Location location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.person;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
|
||||||
|
import model.AbstractEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name = "Password.findByPassword",
|
||||||
|
query = "SELECT p FROM Password p WHERE p.password = :password"),
|
||||||
|
@NamedQuery(name = "Password.findByCostumerID",
|
||||||
|
query = "SELECT p FROM Password p WHERE p.person = :person")
|
||||||
|
})
|
||||||
|
public class Password extends AbstractEntity {
|
||||||
|
private static final long serialVersionUID = -1924150926160449302L;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
private Person person;
|
||||||
|
|
||||||
|
@Column(name="password")
|
||||||
|
private byte[] password;
|
||||||
|
|
||||||
|
public Password() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Password (Person person, byte[] password) {
|
||||||
|
this.person = person;
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person getPerson() {
|
||||||
|
return person;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassowrd(byte[] password){
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 3;
|
||||||
|
hash = 79 * hash + Objects.hashCode(this.person);
|
||||||
|
hash = 79 * hash + Arrays.hashCode(this.password);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Password other = (Password) obj;
|
||||||
|
if (!Objects.equals(this.person, other.person)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Arrays.equals(this.password, other.password)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
package model.person;
|
||||||
|
|
||||||
|
import model.person.enums.Call;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.AbstractSet;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
import model.AbstractEntity;
|
||||||
|
import model.files.UserPicture;
|
||||||
|
import model.person.enums.UserGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity implementation class for Entity: User
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Inheritance(strategy = InheritanceType.JOINED)
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name = Person.FIND_BY_EMAIL,
|
||||||
|
query = "SELECT p FROM Person p WHERE p.email = :email"),
|
||||||
|
@NamedQuery(name = Person.FIND_BY_ID,
|
||||||
|
query = "SELECT p FROM Person p WHERE p.id = :id"),
|
||||||
|
@NamedQuery(name = Person.FIND_BY_TOKEN,
|
||||||
|
query = "SELECT p FROM Person p inner join p.tokens t where t.tokenHash = :tokenHash and t.tokenType = :tokenType and t.expiration > :timestamp")
|
||||||
|
})
|
||||||
|
public class Person extends AbstractEntity implements Serializable {
|
||||||
|
|
||||||
|
public static final String FIND_BY_EMAIL = "Person.findByEmail";
|
||||||
|
public static final String FIND_BY_ID = "Person.findByID";
|
||||||
|
public static final String FIND_BY_TOKEN = "Person.findByToken";
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Column(name = "Email", unique = true, nullable = false)
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@OneToOne(cascade = CascadeType.ALL)
|
||||||
|
@JoinColumn(name = "Password_ID", nullable = false, unique = true)
|
||||||
|
private Password password;
|
||||||
|
|
||||||
|
@OneToOne(cascade = CascadeType.ALL)
|
||||||
|
@JoinColumn(name = "Salt_ID", nullable = false, unique = true)
|
||||||
|
private Salt salt;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(name = "Anrede")
|
||||||
|
private Call call;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "person", orphanRemoval = true, cascade = CascadeType.ALL)
|
||||||
|
private List<Token> tokens;
|
||||||
|
|
||||||
|
@ElementCollection(targetClass = UserGroup.class)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@JoinTable(name = "UserGroups", joinColumns = @JoinColumn(name = "UserID"))
|
||||||
|
@Column(name = "UserGroups", nullable = false)
|
||||||
|
private Set<UserGroup> userGroups;
|
||||||
|
|
||||||
|
@Column(nullable = true)
|
||||||
|
private String telefon;
|
||||||
|
|
||||||
|
@Column(nullable = true)
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
@Column(nullable = true)
|
||||||
|
private String fax;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String firstname;
|
||||||
|
|
||||||
|
@Column(nullable = true)
|
||||||
|
private String lastname;
|
||||||
|
|
||||||
|
@Column(nullable = true)
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Column(nullable = true)
|
||||||
|
private boolean active;
|
||||||
|
|
||||||
|
@OneToOne(optional = true, cascade = CascadeType.ALL)
|
||||||
|
private UserPicture userPicture;
|
||||||
|
|
||||||
|
public Person() {
|
||||||
|
super();
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person(String email, byte[] password, Salt salt, Set<UserGroup> usergroups) {
|
||||||
|
this.email = email;
|
||||||
|
this.tokens = new ArrayList<>();
|
||||||
|
this.salt = salt;
|
||||||
|
this.password = new Password(this, password);
|
||||||
|
this.userGroups = usergroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Password getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(Password password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Salt getSalt() {
|
||||||
|
return salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSalt(Salt salt) {
|
||||||
|
this.salt = salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Call getCall() {
|
||||||
|
return call;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCall(Call call) {
|
||||||
|
this.call = call;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTelefon() {
|
||||||
|
return telefon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTelefon(String telefon) {
|
||||||
|
this.telefon = telefon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMobile() {
|
||||||
|
return mobile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMobile(String mobile) {
|
||||||
|
this.mobile = mobile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFax() {
|
||||||
|
return fax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFax(String fax) {
|
||||||
|
this.fax = fax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstname() {
|
||||||
|
return firstname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstname(String firstname) {
|
||||||
|
this.firstname = firstname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastname() {
|
||||||
|
return lastname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastname(String lastname) {
|
||||||
|
this.lastname = lastname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Token> getTokens() {
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTokens(List<Token> tokens) {
|
||||||
|
this.tokens = tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addToken(Token token) {
|
||||||
|
if (this.tokens == null) {
|
||||||
|
tokens = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens.add(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<UserGroup> getUserGroups() {
|
||||||
|
return userGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserGroups(Set<UserGroup> userGroups) {
|
||||||
|
this.userGroups = userGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addGroup(UserGroup userGroup){
|
||||||
|
if (this.userGroups == null) {
|
||||||
|
this.userGroups = new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.userGroups.add(userGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActive() {
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActive(boolean active) {
|
||||||
|
this.active = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserPicture getUserPicture() {
|
||||||
|
return userPicture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserPicture(UserPicture userPicture) {
|
||||||
|
this.userPicture = userPicture;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.person;
|
||||||
|
|
||||||
|
//import java.nio.charset.Charset;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
import model.AbstractEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Salt extends AbstractEntity {
|
||||||
|
|
||||||
|
//private final Charset UTF8_CHARSET = Charset.forName("UTF-8");
|
||||||
|
private static final long serialVersionUID = -1068077226987746862L;
|
||||||
|
private byte[] salt;
|
||||||
|
private int interations;
|
||||||
|
|
||||||
|
public Salt() {
|
||||||
|
interations = 3072;
|
||||||
|
generateSalt();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateSalt() {
|
||||||
|
SecureRandom random = new SecureRandom();
|
||||||
|
byte bytes[] = new byte[64];
|
||||||
|
random.nextBytes(bytes);
|
||||||
|
salt = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public java.lang.String bytetoString(byte[] input) {
|
||||||
|
return Arrays.toString(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getSalt() {
|
||||||
|
return salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInterations() {
|
||||||
|
return interations;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 7;
|
||||||
|
hash = 79 * hash + Arrays.hashCode(this.salt);
|
||||||
|
hash = 79 * hash + this.interations;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Salt other = (Salt) obj;
|
||||||
|
if (this.interations != other.interations) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Arrays.equals(this.salt, other.salt)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.person;
|
||||||
|
|
||||||
|
import model.person.enums.TokenType;
|
||||||
|
import static java.time.temporal.ChronoUnit.MONTHS;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Objects;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.PrePersist;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.UniqueConstraint;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
import model.ticket.Ticket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "token", uniqueConstraints = {
|
||||||
|
@UniqueConstraint(columnNames = {"token_hash"})
|
||||||
|
})
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name = Token.REMOVE_TOKEN, query = "DELETE FROM Token t where t.tokenHash = :tokenHash"),
|
||||||
|
@NamedQuery(name = Token.REMOVE_EXPIRED_TOKEN, query = "DELETE FROM Token t where t.expiration < :timestamp")
|
||||||
|
})
|
||||||
|
public class Token extends AbstractEntity {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -6632692800064453512L;
|
||||||
|
public static final String REMOVE_TOKEN = "Token.removeToken";
|
||||||
|
public static final String REMOVE_EXPIRED_TOKEN = "Token.removeExpiredToken";
|
||||||
|
|
||||||
|
@Column(name = "token_hash")
|
||||||
|
private String tokenHash;
|
||||||
|
|
||||||
|
@Column(name = "token_type")
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private TokenType tokenType;
|
||||||
|
|
||||||
|
@Column(name = "ip_address", length = 45)
|
||||||
|
private String ipAddress;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private Instant created;
|
||||||
|
|
||||||
|
private Instant expiration;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "account_id")
|
||||||
|
private Person person;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Ticket ticket;
|
||||||
|
|
||||||
|
public Token() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@PrePersist
|
||||||
|
public void generateInformation() {
|
||||||
|
this.created = Instant.now();
|
||||||
|
if (this.expiration == null) {
|
||||||
|
this.expiration = this.created.plus(1, MONTHS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTokenHash() {
|
||||||
|
return tokenHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTokenHash(String tokenHash) {
|
||||||
|
this.tokenHash = tokenHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TokenType getTokenType() {
|
||||||
|
return tokenType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTokenType(TokenType tokenType) {
|
||||||
|
this.tokenType = tokenType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIpAddress() {
|
||||||
|
return ipAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIpAddress(String ipAddress) {
|
||||||
|
this.ipAddress = ipAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getCreated() {
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreated(Instant created) {
|
||||||
|
this.created = created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getExpiration() {
|
||||||
|
return expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpiration(Instant expiration) {
|
||||||
|
this.expiration = expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person getPerson() {
|
||||||
|
return person;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPerson(Person person) {
|
||||||
|
this.person = person;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* don't depend on natural identifier for equality checks, see: https://vladmihalcea.com/2017/03/29/the-best-way-to-map-a-onetomany-association-with-jpa-and-hibernate/#more-7143 */
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null || getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Token token = (Token) obj;
|
||||||
|
return Objects.equals(getId(), token.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Token{ id " + getId() + '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public Ticket getTicket() {
|
||||||
|
return ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTicket(Ticket ticket) {
|
||||||
|
this.ticket = ticket;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package model.person.enums;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public enum Call {
|
||||||
|
HERR(0), FRAU(1), DIVERS(2), UNBESTIMMT(3);
|
||||||
|
|
||||||
|
private final int type;
|
||||||
|
private Locale locale = null;
|
||||||
|
|
||||||
|
private Call(int type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Locale getLocale() {
|
||||||
|
return locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocale(Locale locale) {
|
||||||
|
this.locale = locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (locale == null || Locale.GERMAN.equals(locale)) {
|
||||||
|
switch (this) {
|
||||||
|
case HERR:
|
||||||
|
return "Herr";
|
||||||
|
case FRAU:
|
||||||
|
return "Frau";
|
||||||
|
case DIVERS:
|
||||||
|
return "Divers";
|
||||||
|
case UNBESTIMMT:
|
||||||
|
return "Unbestimmt";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locale.equals(Locale.ENGLISH)) {
|
||||||
|
switch (this) {
|
||||||
|
case HERR:
|
||||||
|
return "Mr";
|
||||||
|
case FRAU:
|
||||||
|
return "Mrs";
|
||||||
|
case DIVERS:
|
||||||
|
return "divers";
|
||||||
|
case UNBESTIMMT:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.person.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
public enum TokenType {
|
||||||
|
REMEMBER_ME,
|
||||||
|
API,
|
||||||
|
RESET_PASSWORD,
|
||||||
|
FILE
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.person.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
public enum UserGroup {
|
||||||
|
USER,
|
||||||
|
ADMIN,
|
||||||
|
CUSTOMER;
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.ticket;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Objects;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
import model.person.Person;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Comment extends AbstractEntity implements Comparable<Comment> {
|
||||||
|
|
||||||
|
@Column(columnDefinition = "longblob")
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Person writer;
|
||||||
|
|
||||||
|
private boolean edited;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Ticket ticket;
|
||||||
|
|
||||||
|
public Comment() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comment(Person writer, String message) {
|
||||||
|
this.writer = writer;
|
||||||
|
this.edited = false;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
edited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getLastEditedDate() {
|
||||||
|
return getChangedDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEdited() {
|
||||||
|
return edited;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEdited(boolean edited) {
|
||||||
|
this.edited = edited;
|
||||||
|
setChangedDate(LocalDateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Ticket getTicket() {
|
||||||
|
return ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTicket(Ticket ticket) {
|
||||||
|
this.ticket = ticket;
|
||||||
|
setChangedDate(LocalDateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person getWriter() {
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 7;
|
||||||
|
hash = 79 * hash + Objects.hashCode(this.message);
|
||||||
|
hash = 79 * hash + Objects.hashCode(this.writer);
|
||||||
|
hash = 79 * hash + Objects.hashCode(getCreationDate());
|
||||||
|
hash = 79 * hash + Objects.hashCode(getChangedDate());
|
||||||
|
hash = 79 * hash + (this.edited ? 1 : 0);
|
||||||
|
hash = 79 * hash + Objects.hashCode(this.ticket);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Comment other = (Comment) obj;
|
||||||
|
if (this.edited != other.edited) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.message, other.message)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.writer, other.writer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(getCreationDate(), other.getCreationDate())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.ticket, other.ticket)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Comment{" + "writer=" + writer.getEmail() + ", creationDate=" + getCreationDate() + ", id=" + getId() + ", message="+ message + '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Comment c) {
|
||||||
|
return c.getCreationDate().compareTo(this.getCreationDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.ticket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
public enum FilenameGeneration {
|
||||||
|
INSPEKTIONNR,
|
||||||
|
MASCHINEDESCRIPTION,
|
||||||
|
LOCATION;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
switch(this){
|
||||||
|
case INSPEKTIONNR:
|
||||||
|
return "inspektionnr";
|
||||||
|
case MASCHINEDESCRIPTION:
|
||||||
|
return "maschinedescription";
|
||||||
|
case LOCATION:
|
||||||
|
return "location";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "nothing";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.ticket;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
import model.machine.Machine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class LocationMachine extends AbstractEntity{
|
||||||
|
@OneToOne
|
||||||
|
private Machine machine;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private TicketLocation ticketLocation;
|
||||||
|
|
||||||
|
public LocationMachine() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Machine getMachine() {
|
||||||
|
return machine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMachine(Machine machine) {
|
||||||
|
this.machine = machine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TicketLocation getTicketLocation() {
|
||||||
|
return ticketLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTicketLocation(TicketLocation ticketLocation) {
|
||||||
|
this.ticketLocation = ticketLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.ticket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
public enum Status {
|
||||||
|
NEW("Neu"),
|
||||||
|
PENDING("Zu bestätigen"),
|
||||||
|
HOLD("Angehalten"),
|
||||||
|
ACTIVE("Aktiv"),
|
||||||
|
SHIPPING("Liefern"),
|
||||||
|
PAYMENTPENDING("Zahlung austehend"),
|
||||||
|
CLOSED("Geschlossen"),
|
||||||
|
REOPENED("Wiedergeöffnet");
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private Status(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.ticket;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
import model.adresses.CompanyBillingAddress;
|
||||||
|
import model.company.Company;
|
||||||
|
import model.files.Invoice;
|
||||||
|
import model.files.Report;
|
||||||
|
import model.person.Person;
|
||||||
|
import model.person.Token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Ticket extends AbstractEntity{
|
||||||
|
|
||||||
|
@ManyToOne(optional = false)
|
||||||
|
private Company company;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
private CompanyBillingAddress billingAddress;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Status status;
|
||||||
|
|
||||||
|
@OneToOne(optional = false)
|
||||||
|
private Person creator;
|
||||||
|
|
||||||
|
@OneToOne(optional = true)
|
||||||
|
private Person owner;
|
||||||
|
|
||||||
|
private LocalDateTime startDate;
|
||||||
|
|
||||||
|
private LocalDateTime endDate;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "ticket", cascade = CascadeType.ALL)
|
||||||
|
private List<Comment> comments;
|
||||||
|
|
||||||
|
private boolean payed;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "ticket", orphanRemoval = true, cascade = CascadeType.ALL)
|
||||||
|
private List<Token> tokens;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "ticket", cascade = {CascadeType.PERSIST, CascadeType.PERSIST})
|
||||||
|
private List<Report> reports;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "ticket", cascade = {CascadeType.PERSIST, CascadeType.PERSIST})
|
||||||
|
private List<Invoice> invoices;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "ticket", cascade = {CascadeType.PERSIST, CascadeType.PERSIST})
|
||||||
|
private List<TicketLocation> locations;
|
||||||
|
|
||||||
|
@Column(nullable = false, length = 200)
|
||||||
|
private String filenameGeneration;
|
||||||
|
|
||||||
|
public Ticket() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompanyBillingAddress getBillingAddress() {
|
||||||
|
return billingAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBillingAddress(CompanyBillingAddress billingAddress) {
|
||||||
|
this.billingAddress = billingAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getStartDate() {
|
||||||
|
return startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartDate(LocalDateTime startDate) {
|
||||||
|
this.startDate = startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getEndDate() {
|
||||||
|
return endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEndDate(LocalDateTime endDate) {
|
||||||
|
this.endDate = endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Company getCompany() {
|
||||||
|
return company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompany(Company company) {
|
||||||
|
this.company = company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TicketLocation> getLocations() {
|
||||||
|
return locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocations(List<TicketLocation> locations) {
|
||||||
|
this.locations = locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person getCreator() {
|
||||||
|
return creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreator(Person creator) {
|
||||||
|
this.creator = creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwner(Person owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Comment> getComments() {
|
||||||
|
return comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComments(List<Comment> comments) {
|
||||||
|
this.comments = comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPayed() {
|
||||||
|
return payed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPayed(boolean payed) {
|
||||||
|
this.payed = payed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Token> getTokens() {
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTokens(List<Token> tokens) {
|
||||||
|
this.tokens = tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Report> getReports() {
|
||||||
|
return reports;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReports(List<Report> reports) {
|
||||||
|
this.reports = reports;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Invoice> getInvoices() {
|
||||||
|
return invoices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInvoices(List<Invoice> invoices) {
|
||||||
|
this.invoices = invoices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilenameGeneration() {
|
||||||
|
return filenameGeneration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilenameGeneration(String filenameGeneration) {
|
||||||
|
this.filenameGeneration = filenameGeneration;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.ticket;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
import model.company.Location;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class TicketLocation extends AbstractEntity{
|
||||||
|
@ManyToOne
|
||||||
|
private Ticket ticket;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
private Location location;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "ticketLocation")
|
||||||
|
private List<LocationMachine> machines;
|
||||||
|
|
||||||
|
|
||||||
|
public TicketLocation() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Ticket getTicket() {
|
||||||
|
return ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTicket(Ticket ticket) {
|
||||||
|
this.ticket = ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocation(Location location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<LocationMachine> getMachines() {
|
||||||
|
return machines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMachines(List<LocationMachine> machines) {
|
||||||
|
this.machines = machines;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<persistence version="2.2" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
|
||||||
|
<!-- Define Persistence Unit -->
|
||||||
|
<persistence-unit name="pu_person">
|
||||||
|
<jta-data-source>java:/mss-failsave</jta-data-source>
|
||||||
|
<exclude-unlisted-classes>false</exclude-unlisted-classes>
|
||||||
|
<properties>
|
||||||
|
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
|
||||||
|
</properties>
|
||||||
|
</persistence-unit>
|
||||||
|
</persistence>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
|
||||||
|
bean-discovery-mode="all">
|
||||||
|
</beans>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<jboss-web xmlns="http://www.jboss.com/xml/ns/javaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_10_0.xsd"
|
||||||
|
version="10.0">
|
||||||
|
<security-domain>mss-failsafe</security-domain>
|
||||||
|
</jboss-web>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<jboss-web version="10.0" xmlns="http://www.jboss.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_10_0.xsd">
|
||||||
|
<context-root>/mss</context-root>
|
||||||
|
<security-domain>jaspitest</security-domain>
|
||||||
|
</jboss-web>
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<web-app version="4.0" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd">
|
||||||
|
<welcome-file-list>
|
||||||
|
<welcome-file>/index.xhtml</welcome-file>
|
||||||
|
</welcome-file-list>
|
||||||
|
<error-page>
|
||||||
|
<!-- Missing login -->
|
||||||
|
<error-code>401</error-code>
|
||||||
|
<location>/error.xhtml</location>
|
||||||
|
</error-page>
|
||||||
|
<error-page>
|
||||||
|
<!-- Forbidden directory listing -->
|
||||||
|
<error-code>403</error-code>
|
||||||
|
<location>/error.xhtml</location>
|
||||||
|
</error-page>
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>authorise</web-resource-name>
|
||||||
|
<url-pattern>/user/*</url-pattern>
|
||||||
|
<http-method>GET</http-method>
|
||||||
|
<http-method>POST</http-method>
|
||||||
|
<http-method>TRACE</http-method>
|
||||||
|
<http-method>HEAD</http-method>
|
||||||
|
<http-method>DELETE</http-method>
|
||||||
|
<http-method>CONNECT</http-method>
|
||||||
|
<http-method>OPTIONS</http-method>
|
||||||
|
<http-method>PUT</http-method>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>ADMIN</role-name>
|
||||||
|
<role-name>USER</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
<!--
|
||||||
|
<user-data-constraint>
|
||||||
|
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
|
||||||
|
</user-data-constraint>-->
|
||||||
|
</security-constraint>
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>authorise</web-resource-name>
|
||||||
|
<url-pattern>/admin/*</url-pattern>
|
||||||
|
<http-method>GET</http-method>
|
||||||
|
<http-method>POST</http-method>
|
||||||
|
<http-method>TRACE</http-method>
|
||||||
|
<http-method>HEAD</http-method>
|
||||||
|
<http-method>DELETE</http-method>
|
||||||
|
<http-method>CONNECT</http-method>
|
||||||
|
<http-method>OPTIONS</http-method>
|
||||||
|
<http-method>PUT</http-method>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>ADMIN</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
<!--<user-data-constraint>
|
||||||
|
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
|
||||||
|
</user-data-constraint>-->
|
||||||
|
</security-constraint>
|
||||||
|
<security-role>
|
||||||
|
<description>Normal User which got invited</description>
|
||||||
|
<role-name>USER</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<description>Admin user who can change entries, invite new domains and more..</description>
|
||||||
|
<role-name>ADMIN</role-name>
|
||||||
|
</security-role>
|
||||||
|
<context-param>
|
||||||
|
<param-name>javax.faces.PROJECT_STAGE</param-name>
|
||||||
|
<param-value>Development</param-value>
|
||||||
|
</context-param>
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>Faces Servlet</servlet-name>
|
||||||
|
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
|
||||||
|
<load-on-startup>1</load-on-startup>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>Faces Servlet</servlet-name>
|
||||||
|
<url-pattern>*.xhtml</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
<session-config>
|
||||||
|
<session-timeout>
|
||||||
|
30
|
||||||
|
</session-timeout>
|
||||||
|
<cookie-config>
|
||||||
|
<http-only>true</http-only>
|
||||||
|
<!-- Prevent client side scripting from accessing/manipulating session cookie. -->
|
||||||
|
</cookie-config>
|
||||||
|
<tracking-mode>COOKIE</tracking-mode>
|
||||||
|
<!-- This disables URL rewriting. -->
|
||||||
|
</session-config>
|
||||||
|
|
||||||
|
<context-param>
|
||||||
|
<param-name>primefaces.THEME</param-name>
|
||||||
|
<param-value>saga</param-value>
|
||||||
|
</context-param>
|
||||||
|
</web-app>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:h="http://java.sun.com/jsf/html"
|
||||||
|
xmlns:f="http://java.sun.com/jsf/core"
|
||||||
|
xmlns:p="http://primefaces.org/ui">
|
||||||
|
|
||||||
|
<h:head>
|
||||||
|
<title>Willkommen #{personController.activeUser.call.toString()} #{personController.activeUser.lastname}</title>
|
||||||
|
</h:head>
|
||||||
|
|
||||||
|
<h:body>
|
||||||
|
<p>Willkommen #{personController.activeUser.call.toString()} #{personController.activeUser.lastname}</p>
|
||||||
|
<p:spinner />
|
||||||
|
</h:body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||||
|
xmlns:p="http://primefaces.org/ui"
|
||||||
|
xmlns:f="http://xmlns.jcp.org/jsf/core">
|
||||||
|
<h:head>
|
||||||
|
<title>Error Testpage</title>
|
||||||
|
</h:head>
|
||||||
|
<h:body>
|
||||||
|
|
||||||
|
<p>Error!</p>
|
||||||
|
|
||||||
|
</h:body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||||
|
xmlns:p="http://primefaces.org/ui"
|
||||||
|
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||||
|
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
|
||||||
|
<h:head>
|
||||||
|
<title>Login Testpage</title>
|
||||||
|
</h:head>
|
||||||
|
<h:body>
|
||||||
|
<h:form id="login">
|
||||||
|
<p:panel header="Login" style="width: 450px; margin: auto; margin-top: 100px;">
|
||||||
|
<p:messages id="messages" showDetail="true" closable="true">
|
||||||
|
<p:autoUpdate />
|
||||||
|
</p:messages>
|
||||||
|
<p:graphicImage url="/resources/images/logo.jpg" alt="MSS Machine Safety Services" style="width: 100%;"/>
|
||||||
|
<h:panelGrid columns="2" cellpadding="5">
|
||||||
|
|
||||||
|
<p:outputLabel for="username" value="Email" />
|
||||||
|
<p:inputText id="username" value="#{personController.username}" required="true" label="username" />
|
||||||
|
|
||||||
|
<p:outputLabel for="password" value="Password:" />
|
||||||
|
<p:password id="password" value="#{personController.password}" required="true" label="password" />
|
||||||
|
|
||||||
|
<p:outputLabel for="rememberMe" value="Remember Me:" />
|
||||||
|
<p:selectBooleanCheckbox id="rememberMe" value="#{personController.rememberMe}" />
|
||||||
|
|
||||||
|
<f:facet name="footer">
|
||||||
|
<p:commandButton value="Login" action="#{personController.submit()}" ajax="false"/>
|
||||||
|
</f:facet>
|
||||||
|
</h:panelGrid>
|
||||||
|
</p:panel>
|
||||||
|
</h:form>
|
||||||
|
|
||||||
|
</h:body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,301 @@
|
|||||||
|
.centeredMenuBar.ui-menubar {
|
||||||
|
text-align: center;
|
||||||
|
width: 1300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-selectonemenu{
|
||||||
|
width: 250px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contentPanel{
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar:hover{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bodyPanel{
|
||||||
|
background-color: lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-tooltip {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-tooltip-arrow{
|
||||||
|
border-right-color: #002A2A !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-tooltip-text {
|
||||||
|
color: #FBFEF9 !important;
|
||||||
|
background-color: #002A2A !important;
|
||||||
|
border: 2px solid #002A2A !important;
|
||||||
|
border-radius: 10px;
|
||||||
|
-moz-border-radius: 10px;
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alignTop {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.oldPaper{
|
||||||
|
background-color: #F7C9AF !important;
|
||||||
|
background-image: none !important;
|
||||||
|
color: #000000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoPicture{
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoPicture:hover{
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
|
||||||
|
.squareSpan{
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban {
|
||||||
|
font-size: 1em;
|
||||||
|
border: none;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanbanPanel {
|
||||||
|
font-size: 0.8em;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centeredMenuBar .ui-menu-list {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stickyMenubar{
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
border: none;
|
||||||
|
z-index: 9000
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-sticky {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
border-radius: 10px;
|
||||||
|
-moz-border-radius: 10px;
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
}
|
||||||
|
@media (max-width: 960px) {
|
||||||
|
.ui-sticky {
|
||||||
|
top: 0px !important;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
max-width: 1300px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panelManager{
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
min-width: 1500px;
|
||||||
|
max-width: 90%;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-noborder{
|
||||||
|
padding: 0px 0px
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-panelgrid td {
|
||||||
|
padding: 0px 0px ;
|
||||||
|
}
|
||||||
|
|
||||||
|
.self-panelGrid>tbody>tr>td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile:hover {
|
||||||
|
border-color: #009999;
|
||||||
|
border-style: solid;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #009999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile:active{
|
||||||
|
box-shadow: 0px 0px 0px silver inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile{
|
||||||
|
border: 2px solid silver;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 10px 10px 15px silver;
|
||||||
|
-moz-border-radius: 10px;
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
transition: opacity 2s ease, border-color 1s ease, color 1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tileCreator {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panelCreator{
|
||||||
|
border: 2px solid silver;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 10px 10px 15px silver;
|
||||||
|
-moz-border-radius: 10px;
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
float: top;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tileCreatorPro{
|
||||||
|
border: 1px solid #009999;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 10px 10px 15px silver;
|
||||||
|
-moz-border-radius: 10px;
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.priceLabel{
|
||||||
|
border-style: solid;
|
||||||
|
border-bottom: 2px;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picture {
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 0px 0px 0px 0px;
|
||||||
|
margin: 0px 0px 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picture:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.creatorPicture{
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.productsElement{
|
||||||
|
width: 270px;
|
||||||
|
height: 350px;
|
||||||
|
border: 1px solid silver;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 5px 5px 10px silver;
|
||||||
|
-moz-border-radius: 5px;
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
transition: opacity 2s ease, border-color 1s ease, color 1s ease;
|
||||||
|
margin: 5px 5px 5px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.productsElement:hover {
|
||||||
|
border-color: #009999;
|
||||||
|
border-style: solid;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #009999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.productsPicture{
|
||||||
|
width: 248px;
|
||||||
|
height: 248px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.productsText{
|
||||||
|
position: relative;
|
||||||
|
top: -20px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.productsText:hover{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.productsInfo{
|
||||||
|
width: 99px;
|
||||||
|
height: 29px;
|
||||||
|
background-color: #009999;
|
||||||
|
color: #FBFEF9;
|
||||||
|
text-align: right;
|
||||||
|
vertical-align: central;
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
display: block;
|
||||||
|
border-radius: 2px;
|
||||||
|
position: relative;
|
||||||
|
top: -225px;
|
||||||
|
left: -10px;
|
||||||
|
padding-right: 8px;
|
||||||
|
padding: auto;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.productsInfo:hover{
|
||||||
|
cursor: help;
|
||||||
|
box-shadow: 5px 5px 10px #241623;
|
||||||
|
border: 1px solid #008C8C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.productInfo {
|
||||||
|
border-radius: 10px;
|
||||||
|
-moz-border-radius: 10px;
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: silver;
|
||||||
|
border-left: 2px;
|
||||||
|
border-bottom: 0px;
|
||||||
|
border-right: 0px;
|
||||||
|
border-top: 0px;
|
||||||
|
height: 100%;
|
||||||
|
width: 350px;
|
||||||
|
float: right;
|
||||||
|
float: top;
|
||||||
|
text-align: left;
|
||||||
|
padding: 0px 0px 0px 0px;
|
||||||
|
margin: 0px 0px 0px 0px;
|
||||||
|
margin-top: 0px;
|
||||||
|
box-shadow: 10px 10px 15px silver;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-breadcrumb {
|
||||||
|
background: none !important;
|
||||||
|
border: none !important;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.htmldot {
|
||||||
|
height:20px;
|
||||||
|
width: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.htmlsquare {
|
||||||
|
height:25px;
|
||||||
|
width: 25px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testGradient {
|
||||||
|
background: linear-gradient(-90deg, #ff00ff, white 60%) !important;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
To change this license header, choose License Headers in Project Properties.
|
||||||
|
To change this template file, choose Tools | Templates
|
||||||
|
and open the template in the editor.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Created on : 16.10.2021, 22:59:07
|
||||||
|
Author : patri
|
||||||
|
*/
|
||||||
|
|
||||||
|
.icon{
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon.company{
|
||||||
|
background-image: url('../resources/images/icons/company_icon.png') !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon.machine{
|
||||||
|
background-image: url('../resources/images/icons/machine_icon.png') !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon.location{
|
||||||
|
background-image: url('../resources/images/icons/location_icon.png') !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon.security{
|
||||||
|
background-image: url('../resources/images/icons/security_icon.png') !important;
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 445 B |
Binary file not shown.
|
After Width: | Height: | Size: 378 B |
Binary file not shown.
|
After Width: | Height: | Size: 483 B |
Binary file not shown.
|
After Width: | Height: | Size: 431 B |
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8' ?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||||
|
xmlns:f = "http://java.sun.com/jsf/core"
|
||||||
|
xmlns:p="http://primefaces.org/ui"
|
||||||
|
xmlns:h="http://xmlns.jcp.org/jsf/html">
|
||||||
|
|
||||||
|
|
||||||
|
<h:head>
|
||||||
|
<f:facet name="last">
|
||||||
|
<h:outputStylesheet library="css" name="/css/default.css"/>
|
||||||
|
<h:outputStylesheet library="webjars" name="primeflex/2.0.0/primeflex.min.css" />
|
||||||
|
</f:facet>
|
||||||
|
<title>
|
||||||
|
<ui:insert name="title">
|
||||||
|
Please add a Title!
|
||||||
|
</ui:insert>
|
||||||
|
</title>
|
||||||
|
<ui:insert name="head"/>
|
||||||
|
</h:head>
|
||||||
|
|
||||||
|
<h:body>
|
||||||
|
<div class="p-grid">
|
||||||
|
<div class="p-lg-3">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="p-lg-9">
|
||||||
|
<ui:insert name="content">Content</ui:insert>
|
||||||
|
</div>
|
||||||
|
<div class="p-lg-12">
|
||||||
|
<ui:insert name="bottom">Bottom</ui:insert>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h:body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8' ?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||||
|
xmlns:f = "http://java.sun.com/jsf/core"
|
||||||
|
xmlns:p="http://primefaces.org/ui"
|
||||||
|
xmlns:h="http://xmlns.jcp.org/jsf/html">
|
||||||
|
|
||||||
|
|
||||||
|
<h:head>
|
||||||
|
<f:facet name="last">
|
||||||
|
<h:outputStylesheet library="css" name="default.css"/>
|
||||||
|
<h:outputStylesheet library="css" name="icons.css"/>
|
||||||
|
<h:outputStylesheet library="webjars" name="primeflex/2.0.0/primeflex.min.css" />
|
||||||
|
</f:facet>
|
||||||
|
<title>
|
||||||
|
<ui:insert name="title">
|
||||||
|
Please add a Title!
|
||||||
|
</ui:insert>
|
||||||
|
</title>
|
||||||
|
<ui:insert name="head"/>
|
||||||
|
</h:head>
|
||||||
|
|
||||||
|
<h:body>
|
||||||
|
<h:form id="main">
|
||||||
|
<div class="p-grid">
|
||||||
|
<div class="p-col-12 p-md-3 p-lg-2 p-xl-2">
|
||||||
|
<div class="p-col-12" style="min-height: 90px;">
|
||||||
|
<p:commandLink action="welcome">
|
||||||
|
<p:graphicImage url="../resources/images/logo.jpg" alt="MSS Machine Safety Services" style="width: 100%;"/>
|
||||||
|
</p:commandLink>
|
||||||
|
</div>
|
||||||
|
<div class="p-col-12">
|
||||||
|
<p:menu style="width: 100%;">
|
||||||
|
<p:submenu label="Home">
|
||||||
|
<p:menuitem value="Home" outcome="welcome" icon="pi pi-home"/>
|
||||||
|
<p:menuitem value="Suche" outcome="welcome" icon="pi pi-search"/>
|
||||||
|
</p:submenu>
|
||||||
|
<p:submenu label="Ticket">
|
||||||
|
<p:menuitem value="Erstellen" outcome="welcome" icon="pi pi-plus"/>
|
||||||
|
<p:menuitem value="Suchen" outcome="welcome" icon="pi pi-search"/>
|
||||||
|
</p:submenu>
|
||||||
|
<p:submenu label="Stammdaten">
|
||||||
|
<p:menuitem value="Firmen" outcome="companies" icon="icon company"/>
|
||||||
|
<p:menuitem value="Standorte" outcome="locations" icon="icon location"/>
|
||||||
|
<p:menuitem value="Maschienen" outcome="machines" icon="icon machine"/>
|
||||||
|
<p:menuitem value="Schutzeinr." outcome="protection" icon="icon security"/>
|
||||||
|
</p:submenu>
|
||||||
|
</p:menu>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-col-12 p-md-9 p-lg-10 p-xl-10">
|
||||||
|
<div class="card p-col-12" style="min-height: 90px; text-align: right;">
|
||||||
|
|
||||||
|
<p:menu overlay="true" trigger="avatar" my="left top" at="bottom left">
|
||||||
|
<p:menuitem value="Profil" outcome="profile"/>
|
||||||
|
<p:menuitem value="Einstellungen" />
|
||||||
|
<p:menuitem value="Ausloggen" action="#{personController.logout()}" />
|
||||||
|
</p:menu>
|
||||||
|
|
||||||
|
<p:avatar dynamicColor="true" id="avatar" icon="pi pi-user" styleClass="p-mr-2 avatar" size="large" shape="circle" gravatar="#{personController.activeUser.email}">
|
||||||
|
<p:graphicImage value="#{personController.activeUser.userPicture.fileData}" rendered="#{personController.hasPicture()}"/>
|
||||||
|
</p:avatar>
|
||||||
|
</div>
|
||||||
|
<div class="p-col-12" style="width: 100%">
|
||||||
|
<div class="card p-col-12">
|
||||||
|
<p:growl showDetail="true">
|
||||||
|
<p:autoUpdate/>
|
||||||
|
</p:growl>
|
||||||
|
</div>
|
||||||
|
<div class="card p-col-12">
|
||||||
|
<ui:insert name="content">Content</ui:insert>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-col-12 p-lg-12 p-xl-12">
|
||||||
|
<ui:insert name="bottom">Bottom</ui:insert>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</h:form>
|
||||||
|
</h:body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<ui:composition template="/resources/layout/user/template.xhtml"
|
||||||
|
xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||||
|
xmlns:p="http://primefaces.org/ui"
|
||||||
|
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||||
|
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
|
||||||
|
<ui:define name="title">
|
||||||
|
Firmen
|
||||||
|
</ui:define>
|
||||||
|
|
||||||
|
<ui:define name="content">
|
||||||
|
Willkommen zuhause
|
||||||
|
</ui:define>
|
||||||
|
|
||||||
|
<ui:define name="bottom">
|
||||||
|
|
||||||
|
</ui:define>
|
||||||
|
|
||||||
|
</ui:composition>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
To change this license header, choose License Headers in Project Properties.
|
||||||
|
To change this template file, choose Tools | Templates
|
||||||
|
and open the template in the editor.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>TODO supply a title</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>TODO write content</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
To change this license header, choose License Headers in Project Properties.
|
||||||
|
To change this template file, choose Tools | Templates
|
||||||
|
and open the template in the editor.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>TODO supply a title</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>TODO write content</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
<ui:composition template="/resources/layout/user/template.xhtml"
|
||||||
|
xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||||
|
xmlns:p="http://primefaces.org/ui"
|
||||||
|
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||||
|
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
|
||||||
|
<ui:define name="title">
|
||||||
|
Willkommen #{personController.activeUser.call.toString()} #{personController.activeUser.lastname}
|
||||||
|
</ui:define>
|
||||||
|
|
||||||
|
<ui:define name="content">
|
||||||
|
<div class="p-grid">
|
||||||
|
<div class="card p-col-5 p-md-6 p-xl-6">
|
||||||
|
<p:fileUpload mode="advanced"
|
||||||
|
multiple="false"
|
||||||
|
sizeLimit="#{userPictureController.maxFileSize}" allowTypes="#{userPictureController.fileTypesRE}"
|
||||||
|
invalidSizeMessage="Maximum file size allowed is 2 MB"
|
||||||
|
invalidFileMessage="only gif | jpg | jpeg | png is allowed"
|
||||||
|
update="main"
|
||||||
|
listener="#{userPictureController.handleUserPictureUpload}"/>
|
||||||
|
</div>
|
||||||
|
<div class="card p-col-7 p-md-6 p-xl-6" style="text-align: right;">
|
||||||
|
<p:graphicImage style="max-width: 500px; max-height: 300px; margin-right: 20%;" id="image" value="#{personController.activeUser.userPicture.fileData}" rendered="#{personController.hasPicture()}"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card p-col-12 p-md-6 p-xl-6">
|
||||||
|
<div class="ui-fluid p-formgrid p-grid">
|
||||||
|
<div class="p-field p-col-8 p-md-8">
|
||||||
|
<p:outputLabel for="email" value="Email" />
|
||||||
|
<p:inputText readonly="true" id="email" value="#{personEditController.email}" />
|
||||||
|
</div>
|
||||||
|
<div class="p-field p-col-4 p-md-4" style="float: right;">
|
||||||
|
<br />
|
||||||
|
<p:commandButton value="Ändern"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-field p-col-8 p-md-8">
|
||||||
|
<p:outputLabel for="password" value="Password" />
|
||||||
|
<p:inputText readonly="true" id="password" value="#{personEditController.password}" />
|
||||||
|
</div>
|
||||||
|
<div class="p-field p-col-4 p-md-4" style="float: right;">
|
||||||
|
<br />
|
||||||
|
<p:commandButton value="Ändern"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-field p-col-8 p-md-8">
|
||||||
|
<p:outputLabel for="telefon" value="Telefon" />
|
||||||
|
<p:inputText readonly="true" id="telefon" value="#{personEditController.telefon}" />
|
||||||
|
</div>
|
||||||
|
<div class="p-field p-col-4 p-md-4" style="float: right;">
|
||||||
|
<br />
|
||||||
|
<p:commandButton value="Ändern"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-field p-col-8 p-md-8">
|
||||||
|
<p:outputLabel for="mobile" value="Handy" />
|
||||||
|
<p:inputText readonly="true" id="mobile" value="#{personEditController.mobile}" />
|
||||||
|
</div>
|
||||||
|
<div class="p-field p-col-4 p-md-4" style="float: right;">
|
||||||
|
<br />
|
||||||
|
<p:commandButton value="Ändern"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card p-col-12 p-md-6 p-xl-6">
|
||||||
|
<div class="ui-fluid p-formgrid p-grid">
|
||||||
|
<div class="p-field p-col-8 p-md-8">
|
||||||
|
<p:outputLabel for="title" value="Titel" />
|
||||||
|
<p:inputText readonly="true" id="title" value="#{personEditController.title}" />
|
||||||
|
</div>
|
||||||
|
<div class="p-field p-col-4 p-md-4" style="float: right;">
|
||||||
|
<br />
|
||||||
|
<p:commandButton value="Ändern"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-field p-col-8 p-md-8">
|
||||||
|
<p:outputLabel for="call" value="Anrede" />
|
||||||
|
<p:inputText readonly="true" id="call" value="#{personEditController.call.toString()}" />
|
||||||
|
</div>
|
||||||
|
<div class="p-field p-col-4 p-md-4" style="float: right;">
|
||||||
|
<br />
|
||||||
|
<p:commandButton value="Ändern"/>
|
||||||
|
</div>
|
||||||
|
<div class="p-field p-col-8 p-md-8">
|
||||||
|
<p:outputLabel for="firstname" value="Vorname" />
|
||||||
|
<p:inputText readonly="true" id="firstname" value="#{personEditController.firstname}" />
|
||||||
|
</div>
|
||||||
|
<div class="p-field p-col-4 p-md-4" style="float: right;">
|
||||||
|
<br />
|
||||||
|
<p:commandButton value="Ändern"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-field p-col-8 p-md-8">
|
||||||
|
<p:outputLabel for="lastname" value="Nachname" />
|
||||||
|
<p:inputText readonly="true" id="lastname" value="#{personEditController.lastname}" />
|
||||||
|
</div>
|
||||||
|
<div class="p-field p-col-4 p-md-4" style="float: right;">
|
||||||
|
<br />
|
||||||
|
<p:commandButton value="Ändern"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ui:define>
|
||||||
|
|
||||||
|
<ui:define name="bottom">
|
||||||
|
|
||||||
|
</ui:define>
|
||||||
|
|
||||||
|
</ui:composition>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
To change this license header, choose License Headers in Project Properties.
|
||||||
|
To change this template file, choose Tools | Templates
|
||||||
|
and open the template in the editor.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>TODO supply a title</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>TODO write content</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<ui:composition template="/resources/layout/user/template.xhtml"
|
||||||
|
xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||||
|
xmlns:p="http://primefaces.org/ui"
|
||||||
|
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||||
|
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
|
||||||
|
<ui:define name="title">
|
||||||
|
Willkommen #{personController.activeUser.call.toString()} #{personController.activeUser.lastname}
|
||||||
|
</ui:define>
|
||||||
|
|
||||||
|
<ui:define name="content">
|
||||||
|
Willkommen zuhause
|
||||||
|
</ui:define>
|
||||||
|
|
||||||
|
<ui:define name="bottom">
|
||||||
|
|
||||||
|
</ui:define>
|
||||||
|
|
||||||
|
</ui:composition>
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>plate.software</groupId>
|
||||||
|
<artifactId>mss-failsafe</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>mssfailsafe.datalayer</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||||
|
<jakartaee>8.0</jakartaee>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>plate.software</groupId>
|
||||||
|
<artifactId>userdata</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax</groupId>
|
||||||
|
<artifactId>javaee-api</artifactId>
|
||||||
|
<version>${jakartaee}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.pdfbox</groupId>
|
||||||
|
<artifactId>pdfbox</artifactId>
|
||||||
|
<version>2.0.13</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-api</artifactId>
|
||||||
|
<version>2.14.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-core</artifactId>
|
||||||
|
<version>2.14.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>plate.software</groupId>
|
||||||
|
<artifactId>userManagement</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<classifier>classes</classifier>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
package model.adresses;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@MappedSuperclass
|
||||||
|
public class Address extends AbstractEntity{
|
||||||
|
|
||||||
|
//Land
|
||||||
|
@NotNull(message = "Land darf nicht null sein")
|
||||||
|
private String country;
|
||||||
|
|
||||||
|
//Straßenname
|
||||||
|
@NotNull(message = "Strasse darf nicht null sein")
|
||||||
|
private String street;
|
||||||
|
|
||||||
|
//Hausnummer
|
||||||
|
@NotNull(message = "Hausnummer darf nicht null sein")
|
||||||
|
private String number;
|
||||||
|
|
||||||
|
//Zusatz
|
||||||
|
private String extra;
|
||||||
|
|
||||||
|
//PLZ
|
||||||
|
@NotNull(message = "PLZ darf nicht null sein")
|
||||||
|
private Integer postnumber;
|
||||||
|
|
||||||
|
//Bundesland
|
||||||
|
@NotNull(message = "Bundesland darf nicht null sein")
|
||||||
|
private String county;
|
||||||
|
|
||||||
|
//Ort
|
||||||
|
@NotNull(message = "Ort darf nicht null sein")
|
||||||
|
private String place;
|
||||||
|
|
||||||
|
private String contact;
|
||||||
|
|
||||||
|
private String comment;
|
||||||
|
|
||||||
|
public Address() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(String street, String number, String extra, Integer postnumber, String county, String place) {
|
||||||
|
this.street = street;
|
||||||
|
this.number = number;
|
||||||
|
this.extra = extra;
|
||||||
|
this.postnumber = postnumber;
|
||||||
|
this.county = county;
|
||||||
|
this.place = place;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(String country, String street, String number, String extra, Integer postnumber, String county, String place) {
|
||||||
|
this.country = country;
|
||||||
|
this.street = street;
|
||||||
|
this.number = number;
|
||||||
|
this.extra = extra;
|
||||||
|
this.postnumber = postnumber;
|
||||||
|
this.county = county;
|
||||||
|
this.place = place;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(String country, String street, String number, String extra, Integer postnumber, String county, String place, String contact, String comment) {
|
||||||
|
this.country = country;
|
||||||
|
this.street = street;
|
||||||
|
this.number = number;
|
||||||
|
this.extra = extra;
|
||||||
|
this.postnumber = postnumber;
|
||||||
|
this.county = county;
|
||||||
|
this.place = place;
|
||||||
|
this.contact = contact;
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(Address toCopyAddress){
|
||||||
|
this.country = toCopyAddress.getCountry();
|
||||||
|
this.street = toCopyAddress.getStreet();
|
||||||
|
this.number = toCopyAddress.getNumber();
|
||||||
|
this.extra = toCopyAddress.getExtra();
|
||||||
|
this.postnumber = toCopyAddress.getPostnumber();
|
||||||
|
this.county = toCopyAddress.getCounty();
|
||||||
|
this.place = toCopyAddress.getPlace();
|
||||||
|
this.contact = toCopyAddress.getContact();
|
||||||
|
this.comment = toCopyAddress.getComment();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 7;
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.country);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.street);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.number);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.extra);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.postnumber);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.county);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.place);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.contact);
|
||||||
|
hash = 83 * hash + Objects.hashCode(this.comment);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Address other = (Address) obj;
|
||||||
|
if (!Objects.equals(this.country, other.country)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.street, other.street)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.number, other.number)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.extra, other.extra)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.county, other.county)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.place, other.place)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.comment, other.comment)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Objects.equals(this.postnumber, other.postnumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStreet() {
|
||||||
|
return street;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStreet(String street) {
|
||||||
|
this.street = street;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNumber() {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNumber(String number) {
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExtra() {
|
||||||
|
return extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExtra(String extra) {
|
||||||
|
this.extra = extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPostnumber() {
|
||||||
|
return postnumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPostnumber(Integer postnumber) {
|
||||||
|
this.postnumber = postnumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCounty() {
|
||||||
|
return county;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCounty(String county) {
|
||||||
|
this.county = county;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlace() {
|
||||||
|
return place;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlace(String place) {
|
||||||
|
this.place = place;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCountry() {
|
||||||
|
return country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCountry(String country) {
|
||||||
|
this.country = country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContact() {
|
||||||
|
return contact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContact(String contact) {
|
||||||
|
this.contact = contact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComment(String comment) {
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.adresses;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import model.company.Company;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class CompanyBillingAddress extends Address{
|
||||||
|
@ManyToOne
|
||||||
|
private Company company;
|
||||||
|
|
||||||
|
private boolean delivery;
|
||||||
|
|
||||||
|
public CompanyBillingAddress() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompanyBillingAddress(Company company, boolean delivery) {
|
||||||
|
this.company = company;
|
||||||
|
this.delivery = delivery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompanyBillingAddress(Company company, boolean delivery,String country, String street, String number, String extra, Integer postnumber, String county, String place) {
|
||||||
|
super(country, street, number, extra, postnumber, county, place);
|
||||||
|
this.company = company;
|
||||||
|
this.delivery = delivery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Company getCompany() {
|
||||||
|
return company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompany(Company company) {
|
||||||
|
this.company = company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDelivery() {
|
||||||
|
return delivery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDelivery(boolean delivery) {
|
||||||
|
this.delivery = delivery;
|
||||||
|
}
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.adresses;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
import model.company.Location;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class LocationAddress extends Address {
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
private Location location;
|
||||||
|
|
||||||
|
public LocationAddress() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocation(Location location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.company;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
import model.adresses.CompanyBillingAddress;
|
||||||
|
import model.customer.Customer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Company extends AbstractEntity {
|
||||||
|
|
||||||
|
public static final String FIND_BY_NAME = "Company.findByName";
|
||||||
|
public static final String FIND_BY_STEUERID = "Company.findBySteuerID";
|
||||||
|
public static final String FIND_BY_UMSATZSTEUERID = "Company.findByUmsatzsteuerID";
|
||||||
|
public static final String FIND_BY_CUSTOMER = "Company.findByCustomer";
|
||||||
|
public static final String FIND_BY_ADDRESS = "Company.findByAddress";
|
||||||
|
public static final String FIND_BY_DELIVERYADDRESS = "Company.findByLocation";
|
||||||
|
|
||||||
|
@Column(unique = true, nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(unique = true, nullable = true)
|
||||||
|
private String steuerNr;
|
||||||
|
|
||||||
|
@Column(unique = true, nullable = true)
|
||||||
|
private String umsatzSteuerID;
|
||||||
|
|
||||||
|
@Column(unique = true, nullable = true)
|
||||||
|
private String kundenNr;
|
||||||
|
|
||||||
|
@Column(unique = false, nullable = true)
|
||||||
|
private String headerInspection;
|
||||||
|
|
||||||
|
@Column(unique = false, nullable = true)
|
||||||
|
private String headerService;
|
||||||
|
|
||||||
|
@Column(unique = false, nullable = false)
|
||||||
|
@Enumerated(EnumType.ORDINAL)
|
||||||
|
private Status status;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
|
||||||
|
private Set<CompanyBillingAddress> addresses;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
|
||||||
|
private Set<Location> locations;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "company", cascade = {
|
||||||
|
CascadeType.MERGE,
|
||||||
|
CascadeType.REFRESH
|
||||||
|
})
|
||||||
|
private Set<Customer> customers;
|
||||||
|
|
||||||
|
public Company() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSteuerNr() {
|
||||||
|
return steuerNr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSteuerNr(String steuerNr) {
|
||||||
|
this.steuerNr = steuerNr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUmsatzSteuerID() {
|
||||||
|
return umsatzSteuerID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUmsatzSteuerID(String umsatzSteuerID) {
|
||||||
|
this.umsatzSteuerID = umsatzSteuerID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKundenNr() {
|
||||||
|
return kundenNr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKundenNr(String kundenNr) {
|
||||||
|
this.kundenNr = kundenNr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHeaderInspection() {
|
||||||
|
return headerInspection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeaderInspection(String headerInspection) {
|
||||||
|
this.headerInspection = headerInspection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHeaderService() {
|
||||||
|
return headerService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeaderService(String headerService) {
|
||||||
|
this.headerService = headerService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<CompanyBillingAddress> getAddresses() {
|
||||||
|
return addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddresses(Set<CompanyBillingAddress> addresses) {
|
||||||
|
this.addresses = addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Location> getLocations() {
|
||||||
|
return locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocations(Set<Location> locations) {
|
||||||
|
this.locations = locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Customer> getCustomers() {
|
||||||
|
return customers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomers(Set<Customer> customers) {
|
||||||
|
this.customers = customers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.company;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
import model.adresses.LocationAddress;
|
||||||
|
import model.customer.Customer;
|
||||||
|
import model.machine.Machine;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Location extends AbstractEntity{
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Company company;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
private LocationAddress address;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "location")
|
||||||
|
private Set<Machine> machines;
|
||||||
|
|
||||||
|
@ManyToMany
|
||||||
|
private Set<Customer> contacts;
|
||||||
|
|
||||||
|
public Location() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Company getCompany() {
|
||||||
|
return company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompany(Company company) {
|
||||||
|
this.company = company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationAddress getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddress(LocationAddress address) {
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Machine> getMachines() {
|
||||||
|
return machines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMachines(Set<Machine> machines) {
|
||||||
|
this.machines = machines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Customer> getContacts() {
|
||||||
|
return contacts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContacts(Set<Customer> contacts) {
|
||||||
|
this.contacts = contacts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.company;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
public enum Status {
|
||||||
|
ACTIVE,
|
||||||
|
INACTIVE;
|
||||||
|
|
||||||
|
private Status() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
switch(this){
|
||||||
|
case ACTIVE:
|
||||||
|
return "aktiv";
|
||||||
|
case INACTIVE:
|
||||||
|
return "inaktiv";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toLanguageString(Locale locale){
|
||||||
|
if (locale == null ||locale.equals(Locale.GERMAN) || locale.equals(Locale.GERMANY)) {
|
||||||
|
return getGerman();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locale.equals(Locale.ENGLISH)) {
|
||||||
|
getEnglish();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getGerman() {
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getEnglish(){
|
||||||
|
switch(this){
|
||||||
|
case ACTIVE:
|
||||||
|
return "active";
|
||||||
|
case INACTIVE:
|
||||||
|
return "inactive";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.customer;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import model.person.Person;
|
||||||
|
import model.company.Company;
|
||||||
|
import model.company.Location;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Customer extends Person{
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Company company;
|
||||||
|
|
||||||
|
@ManyToMany
|
||||||
|
private Set<Location> locations;
|
||||||
|
|
||||||
|
@Column(nullable = true, length = 210)
|
||||||
|
private String note;
|
||||||
|
|
||||||
|
public Customer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Customer(Company company) {
|
||||||
|
this.company = company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Company getCompany() {
|
||||||
|
return company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompany(Company company) {
|
||||||
|
this.company = company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Location> getLocations() {
|
||||||
|
return locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocations(Set<Location> locations) {
|
||||||
|
this.locations = locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNote() {
|
||||||
|
return note;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNote(String note) {
|
||||||
|
this.note = note;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.files;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.Inheritance;
|
||||||
|
import javax.persistence.InheritanceType;
|
||||||
|
import javax.persistence.Lob;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||||
|
public class FileDB extends AbstractEntity{
|
||||||
|
@Column(nullable = false, length = 100)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Mime mime;
|
||||||
|
|
||||||
|
@Lob
|
||||||
|
private byte[] fileData;
|
||||||
|
|
||||||
|
public FileDB() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getFileData() {
|
||||||
|
return fileData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileData(byte[] fileData) {
|
||||||
|
this.fileData = fileData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mime getMime() {
|
||||||
|
return mime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMime(Mime mime) {
|
||||||
|
this.mime = mime;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.files;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import model.ticket.Ticket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Invoice extends FileDB {
|
||||||
|
@OneToMany
|
||||||
|
private Ticket ticket;
|
||||||
|
|
||||||
|
public Invoice() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Invoice(Ticket ticket) {
|
||||||
|
this.ticket = ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Ticket getTicket() {
|
||||||
|
return ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTicket(Ticket ticket) {
|
||||||
|
this.ticket = ticket;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.files;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
public enum Mime {
|
||||||
|
AAC(".aac", "AAC audio", "audio/aac"),
|
||||||
|
ABW(".abw", "AbiWord document", "application/x-abiword"),
|
||||||
|
ARC(".arc", "Archive document (multiple files embedded)", "application/x-freearc"),
|
||||||
|
AVI(".avi", "AVI: Audio Video Interleave", "video/x-msvideo"),
|
||||||
|
AZW(".azw", "Amazon Kindle eBook format", "application/vnd.amazon.ebook"),
|
||||||
|
BIN(".bin", "Any kind of binary data", "application/octet-stream"),
|
||||||
|
BMP(".bmp", "Windows OS/2 Bitmap Graphics", "image/bmp"),
|
||||||
|
BZ(".bz", "BZip archive", "application/x-bzip"),
|
||||||
|
BZ2(".bz2", "BZip2 archive", "application/x-bzip2"),
|
||||||
|
CDA(".cda", "CD audio", "application/x-cdf"),
|
||||||
|
CSH(".csh", "C-Shell script", "application/x-csh"),
|
||||||
|
CSS(".css", "Cascading Style Sheets (CSS)", "text/css"),
|
||||||
|
CSV(".csv", "Comma-separated values (CSV", "text/csv"),
|
||||||
|
DOC(".doc", "Microsoft Word", "application/msword"),
|
||||||
|
DOCX(".docx", "Microsoft Word (OpenXML)", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
|
||||||
|
EOT(".eot", "MS Embedded OpenType fonts", "application/vnd.ms-fontobject"),
|
||||||
|
EPUB(".epub", "Electronic publication (EPUB)", "application/epub+zip"),
|
||||||
|
GZ(".gz", "GZip Compressed Archive", "application/gzip"),
|
||||||
|
GIF(".gif", "Graphics Interchange Format (GIF)", "image/gif"),
|
||||||
|
HTM(".htm", "HyperText Markup Language (HTML)", "text/html"),
|
||||||
|
HTML(".html", "HyperText Markup Language (HTML)", "text/html"),
|
||||||
|
ICO(".ico", "Icon format", "image/vnd.microsoft.icon"),
|
||||||
|
ICS(".ics", "iCalendar format", "text/calendar"),
|
||||||
|
JAR(".jar", "Java Archive (JAR)", "application/java-archive"),
|
||||||
|
JPG(".jpg", "JPEG images", "image/jpeg"),
|
||||||
|
JPEG(".jpeg", "JPEG images", "image/jpeg"),
|
||||||
|
JS(".js", "JavaScript", "text/javascript"),
|
||||||
|
JSON(".json", "JSON format", "application/json"),
|
||||||
|
JSONLD(".jsonld", "JSON-LD format", "application/ld+json"),
|
||||||
|
MID(".mid", "Musical Instrument Digital Interface (MIDI)", "audio/midi"),
|
||||||
|
MIDI(".midi", "Musical Instrument Digital Interface (MIDI)", "audio/midi"),
|
||||||
|
MJS(".mjs", "JavaScript module", "text/javascript"),
|
||||||
|
MP3(".mp3", "MP3 audio", "audio/mpeg"),
|
||||||
|
MP4(".mp4", "MP4 video", "video/mp4"),
|
||||||
|
MPEG(".mpeg", "MPEG Video", "video/mpeg"),
|
||||||
|
MPKG(".mpkg", "Apple Installer Package", "application/vnd.apple.installer+xml"),
|
||||||
|
ODP(".odp", "OpenDocument presentation document", "application/vnd.oasis.opendocument.presentation"),
|
||||||
|
ODS(".ods", "OpenDocument spreadsheet document", "application/vnd.oasis.opendocument.spreadsheet"),
|
||||||
|
ODT(".odt", "OpenDocument text document", "application/vnd.oasis.opendocument.text"),
|
||||||
|
OGA(".oga", "OGG audio", "audio/ogg"),
|
||||||
|
OGV(".ogv", "OGG video", "video/ogg"),
|
||||||
|
OGX(".ogx", "OGG", "application/ogg"),
|
||||||
|
OPUUS(".opus", "Opus audio", "audio/opus"),
|
||||||
|
OTF(".otf", "OpenType font", "font/otf"),
|
||||||
|
PNG(".png", "Portable Network Graphics", "image/png"),
|
||||||
|
PDF(".pdf", "Adobe Portable Document Format (PDF)", "application/pdf"),
|
||||||
|
PHP(".php", "Hypertext Preprocessor (Personal Home Page)", "application/x-httpd-php"),
|
||||||
|
PPT(".ppt", "Microsoft PowerPoint", "application/vnd.ms-powerpoint"),
|
||||||
|
PPTX(".pptx", "Microsoft PowerPoint (OpenXML)", "application/vnd.openxmlformats-officedocument.presentationml.presentation"),
|
||||||
|
RAR(".rar", "RAR archive", "application/vnd.rar"),
|
||||||
|
RTF(".rtf", "Rich Text Format (RTF)", "application/rtf"),
|
||||||
|
SH(".sh", "Bourne shell script", "application/x-sh"),
|
||||||
|
SVG(".svg", "Scalable Vector Graphics (SVG)", "image/svg+xml"),
|
||||||
|
SWF(".swf", "Small web format (SWF) or Adobe Flash document", "application/x-shockwave-flash"),
|
||||||
|
TAR(".tar", "Tape Archive (TAR)", "application/x-tar"),
|
||||||
|
TIF(".tif", "Tagged Image File Format (TIFF)", "image/tiff"),
|
||||||
|
TIFF(".tiff", "Tagged Image File Format (TIFF)", "image/tiff"),
|
||||||
|
TS(".ts", "MPEG transport stream", "video/mp2t"),
|
||||||
|
TTF(".ttf", "TrueType Font", "font/ttf"),
|
||||||
|
TXT(".txt", "Text, (generally ASCII or ISO 8859-n)", "text/plain"),
|
||||||
|
VSD(".vsd", "Microsoft Visio", "application/vnd.visio"),
|
||||||
|
WAV(".wav", "Waveform Audio Format", "audio/wav"),
|
||||||
|
WEBA(".weba", "WEBM audio", "audio/webm"),
|
||||||
|
WEBM(".webm", "WEBM video", "video/webm"),
|
||||||
|
WEBP(".webp", "WEBP image", "image/webp"),
|
||||||
|
WOFF(".woff", "Web Open Font Format (WOFF)", "font/woff"),
|
||||||
|
WOFF2(".woff2", "Web Open Font Format (WOFF)", "font/woff2"),
|
||||||
|
XHTML(".xhtml", "XHTML", "application/xhtml+xml"),
|
||||||
|
XLS(".xls", "Microsoft Excel", "application/vnd.ms-excel"),
|
||||||
|
XLSX(".xlsx", "Microsoft Excel (OpenXML)", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
|
||||||
|
XML(".xml", "XML", "application/xml"),
|
||||||
|
XUL(".xul", "XUL", "application/vnd.mozilla.xul+xml"),
|
||||||
|
ZIP(".zip", "ZIP archive", "application/zip"),
|
||||||
|
GP3V(".3gp", "3GPP audio/video container", "video/3gpp"),
|
||||||
|
GP3A(".3gp", "3GPP audio/video container", "audio/3gpp"),
|
||||||
|
G23V(".3g2", "3GPP2 audio/video container", "video/3gpp2"),
|
||||||
|
G23A(".3g2", "3GPP2 audio/video container", "audio/3gpp2"),
|
||||||
|
Z7(".7z", "7-zip archive", "application/x-7z-compressed");
|
||||||
|
|
||||||
|
private final String extension;
|
||||||
|
private final String kindOfDocument;
|
||||||
|
private final String mimeType;
|
||||||
|
|
||||||
|
private Mime(String extension, String kindOfDocument, String mimeType) {
|
||||||
|
this.extension = extension;
|
||||||
|
this.kindOfDocument = kindOfDocument;
|
||||||
|
this.mimeType = mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExtension() {
|
||||||
|
return extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKindOfDocument() {
|
||||||
|
return kindOfDocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMimeType() {
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.files;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import model.ticket.Ticket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Report extends FileDB{
|
||||||
|
|
||||||
|
@OneToMany
|
||||||
|
private Ticket ticket;
|
||||||
|
|
||||||
|
public Report() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Ticket getTicket() {
|
||||||
|
return ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTicket(Ticket ticket) {
|
||||||
|
this.ticket = ticket;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.machine;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
import model.company.Location;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Machine extends AbstractEntity {
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Location location;
|
||||||
|
|
||||||
|
public Machine() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocation(Location location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.ticket;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Objects;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import model.AbstractEntity;
|
||||||
|
import model.person.Person;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Patrick
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Comment extends AbstractEntity implements Comparable<Comment> {
|
||||||
|
|
||||||
|
@Column(columnDefinition = "longblob")
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Person writer;
|
||||||
|
|
||||||
|
private boolean edited;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Ticket ticket;
|
||||||
|
|
||||||
|
public Comment() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comment(Person writer, String message) {
|
||||||
|
this.writer = writer;
|
||||||
|
this.edited = false;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
edited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getLastEditedDate() {
|
||||||
|
return getChangedDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEdited() {
|
||||||
|
return edited;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEdited(boolean edited) {
|
||||||
|
this.edited = edited;
|
||||||
|
setChangedDate(LocalDateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Ticket getTicket() {
|
||||||
|
return ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTicket(Ticket ticket) {
|
||||||
|
this.ticket = ticket;
|
||||||
|
setChangedDate(LocalDateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person getWriter() {
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 7;
|
||||||
|
hash = 79 * hash + Objects.hashCode(this.message);
|
||||||
|
hash = 79 * hash + Objects.hashCode(this.writer);
|
||||||
|
hash = 79 * hash + Objects.hashCode(getCreationDate());
|
||||||
|
hash = 79 * hash + Objects.hashCode(getChangedDate());
|
||||||
|
hash = 79 * hash + (this.edited ? 1 : 0);
|
||||||
|
hash = 79 * hash + Objects.hashCode(this.ticket);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Comment other = (Comment) obj;
|
||||||
|
if (this.edited != other.edited) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.message, other.message)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.writer, other.writer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(getCreationDate(), other.getCreationDate())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.ticket, other.ticket)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Comment{" + "writer=" + writer.getEmail() + ", creationDate=" + getCreationDate() + ", id=" + getId() + ", message="+ message + '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Comment c) {
|
||||||
|
return c.getCreationDate().compareTo(this.getCreationDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package model.ticket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author patri
|
||||||
|
*/
|
||||||
|
public enum FilenameGeneration {
|
||||||
|
INSPEKTIONNR,
|
||||||
|
MASCHINEDESCRIPTION,
|
||||||
|
LOCATION;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
switch(this){
|
||||||
|
case INSPEKTIONNR:
|
||||||
|
return "inspektionnr";
|
||||||
|
case MASCHINEDESCRIPTION:
|
||||||
|
return "maschinedescription";
|
||||||
|
case LOCATION:
|
||||||
|
return "location";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "nothing";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user