05/22 Enhance codes and fix bugs 3
This commit is contained in:
@@ -118,6 +118,8 @@ Both decorators must be applied **after** `@login_required`.
|
||||
| `PasswordResetToken` | `password_reset_tokens` | SHA-256 hashed, 1-hour expiry, single-use. |
|
||||
| `TicketTemplate` | `ticket_templates` | Pre-filled ticket scaffolds selectable on the new ticket form. |
|
||||
| `TicketSatisfaction` | `ticket_satisfaction` | One survey per resolved ticket; token-authenticated survey URL. |
|
||||
| `TicketWatcher` | `ticket_watchers` | Users subscribed to updates on a ticket. Unique `(ticket_id, user_id)`. Added migration 005. |
|
||||
| `TimeEntry` | `time_entries` | IT staff time log per ticket. Stores `minutes` + optional `note`. Added migration 005. |
|
||||
|
||||
### Cascade Rules
|
||||
|
||||
@@ -128,6 +130,8 @@ Both decorators must be applied **after** `@login_required`.
|
||||
- `history`
|
||||
- `links_as_source` / `links_as_target` (via `TicketLink`)
|
||||
- `satisfaction` (via `TicketSatisfaction`)
|
||||
- `watchers` (via `TicketWatcher`)
|
||||
- `time_entries` (via `TimeEntry`)
|
||||
|
||||
**When deleting a ticket, physical files in `UPLOAD_FOLDER` must be removed
|
||||
manually before the DB delete** — SQLAlchemy cascades handle DB rows only.
|
||||
@@ -169,6 +173,8 @@ manually before the DB delete** — SQLAlchemy cascades handle DB rows only.
|
||||
- `GET /kb` / `GET /kb/<id>` — knowledge base
|
||||
- `POST /tickets/<id>/link` / `POST /tickets/<id>/unlink/<link_id>`
|
||||
- `POST /tickets/<id>/reopen`
|
||||
- `POST /tickets/<id>/watch` / `POST /tickets/<id>/unwatch` — AJAX; toggle watcher subscription
|
||||
- `POST /tickets/<id>/log-time` — IT staff only; AJAX-aware; logs `TimeEntry`
|
||||
- `GET /canned-responses` — JSON endpoint for IT staff comment box
|
||||
- `POST /kb/<id>/feedback`
|
||||
- `GET/POST /survey/<token>` — public (no login required)
|
||||
@@ -178,7 +184,7 @@ manually before the DB delete** — SQLAlchemy cascades handle DB rows only.
|
||||
- `GET /admin/users` / `POST /admin/users/new` / `POST /admin/users/<id>/edit` / `POST /admin/users/<id>/delete`
|
||||
- `GET /admin/tickets` — all tickets with search, filter, pagination
|
||||
- `POST /admin/tickets/<id>/delete` — **admin only**; deletes ticket + physical files
|
||||
- `POST /admin/tickets/bulk-action` — actions: resolve, close, assign_me, unassign, **delete** (delete is admin-only)
|
||||
- `POST /admin/tickets/bulk-action` — actions: resolve, close, assign_me, assign_to, unassign, **delete** (delete is admin-only; `assign_to` requires `assign_to_id` form field)
|
||||
- `GET /admin/tickets/export` — CSV export with active filters
|
||||
- `GET /admin/kb` / `GET/POST /admin/kb/new` / `GET/POST /admin/kb/<id>/edit` / `POST /admin/kb/<id>/delete` / `POST /admin/kb/<id>/publish`
|
||||
- `POST /admin/kb/upload-image` — TinyMCE image upload
|
||||
@@ -236,18 +242,25 @@ log_ticket_history(ticket, field_name, old_value, new_value, changed_by_id)
|
||||
| `ticket_bulk_resolve` | Bulk resolve |
|
||||
| `ticket_bulk_close` | Bulk close |
|
||||
| `ticket_bulk_assign_me` | Bulk assign to self |
|
||||
| `ticket_bulk_assign_to` | Bulk assign to specific user |
|
||||
| `ticket_bulk_unassign` | Bulk unassign |
|
||||
| `kb_create` / `kb_edit` / `kb_delete` | KB article CRUD |
|
||||
| `kb_attachment_delete` | KB attachment removed |
|
||||
| `time_log` | IT staff logs time on a ticket |
|
||||
| `ticket_create_chatbot` | Ticket created via AI chatbot |
|
||||
|
||||
### `notification_service.py`
|
||||
|
||||
Functions: `notify_new_ticket`, `notify_status_change`, `notify_comment_added`,
|
||||
`notify_assignment`, `send_satisfaction_survey`
|
||||
`notify_assignment`, `send_satisfaction_survey`, `notify_watchers`,
|
||||
`send_weekly_digest`
|
||||
|
||||
**Critical rule:** Always call notification functions **after** `db.session.commit()`.
|
||||
Calling them before commit means they act on uncommitted state.
|
||||
|
||||
- **`notify_watchers(ticket, event_title, event_message, exclude_user_id=None)`** — sends in-app notifications to all `TicketWatcher` rows for a ticket. Call after commit from `update_ticket`. Pass `exclude_user_id=current_user.id` so the actor doesn't notify themselves.
|
||||
- **`send_weekly_digest(app)`** — APScheduler job; runs every Monday at 08:00 UTC via `CronTrigger`. Sends a rich HTML email to all active IT staff / admin users with `email_notif=True`. Summarises new, resolved, still-open, and overdue tickets for the past 7 days.
|
||||
|
||||
### `sla_service.py`
|
||||
|
||||
- `set_due_date(ticket, app)` — called at ticket creation; reads SLA hours from `SystemSetting`
|
||||
@@ -488,6 +501,9 @@ Migrations live in `migrations/versions/`. The chain is:
|
||||
└── 002_add_system_settings — creates system_settings table
|
||||
└── 003_render_comments — backfills comment bodies to HTML;
|
||||
widens alembic_version.version_num to VARCHAR(64)
|
||||
└── 004_widen_system_setting_value — system_settings.value VARCHAR(500) → TEXT
|
||||
└── 005_add_watchers_and_time_entries — creates ticket_watchers
|
||||
and time_entries tables
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
@@ -511,10 +527,13 @@ Migrations live in `migrations/versions/`. The chain is:
|
||||
| File upload validation | Magic-byte MIME inspection + extension allowlist |
|
||||
| HTML sanitization | bleach on all comment bodies and KB article bodies |
|
||||
| XSS in KB | bleach allowlist covers TinyMCE-produced tags; `_sanitize_kb_body()` in `admin.py` |
|
||||
| XSS in JS | `_esc()` helper in `base.html` escapes all server-supplied strings before DOM insertion (notifications, toasts) |
|
||||
| SQL injection | SQLAlchemy ORM parameterized queries throughout |
|
||||
| Real client IP | `ProxyFix` middleware trusts one nginx hop; `log_service._get_real_ip()` reads `X-Forwarded-For` |
|
||||
| Role enforcement | `@admin_required` / `@it_required` decorators; per-route checks where needed |
|
||||
| Avatar/file access | All file-serve routes require `@login_required` (except logo) |
|
||||
| HTTP security headers | `@app.after_request` hook in `create_app()` sets `X-Frame-Options`, `X-Content-Type-Options`, `Referrer-Policy`, `X-XSS-Protection`, `Permissions-Policy` via `setdefault` (never overrides app-set headers) |
|
||||
| Session cookie security | `ProductionConfig` sets `SESSION_COOKIE_SECURE=True`, `SESSION_COOKIE_HTTPONLY=True`, `SESSION_COOKIE_SAMESITE='Lax'` |
|
||||
|
||||
---
|
||||
|
||||
@@ -597,6 +616,24 @@ proxies; static files are served directly).
|
||||
| Admin ticket deletion (single + bulk) | ✅ |
|
||||
| Activity log viewer | ✅ |
|
||||
| Configurable display timezone | ✅ |
|
||||
| HTTP security headers (X-Frame-Options, CSP-adjacent, etc.) | ✅ |
|
||||
| Session cookie security flags (Secure, HttpOnly, SameSite) | ✅ |
|
||||
| XSS protection in JS notification/toast HTML via `_esc()` | ✅ |
|
||||
| Reusable `confirmModal()` system replacing all `confirm()` dialogs | ✅ |
|
||||
| Toast notifications repositioned to top-right (no FAB overlap) | ✅ |
|
||||
| Page navigation progress bar (thin top bar on link clicks) | ✅ |
|
||||
| Dark mode with localStorage persistence and anti-FOCT script | ✅ |
|
||||
| AJAX save on IT Update Panel (no page reload) | ✅ |
|
||||
| Mobile-responsive tables via `table-responsive` wrappers | ✅ |
|
||||
| Employee dashboard: status progress bar + urgency flags per ticket | ✅ |
|
||||
| Linked tickets shown read-only to employees on ticket detail | ✅ |
|
||||
| SLA status badge on ticket detail (On track / Overdue / Completed) | ✅ |
|
||||
| Template preview panel on new ticket form | ✅ |
|
||||
| Bulk assign to specific IT staff member | ✅ |
|
||||
| Weekly IT digest email (APScheduler, Monday 08:00 UTC) | ✅ |
|
||||
| Chatbot KB context injection (top matching articles in system prompt) | ✅ |
|
||||
| Ticket watchers (subscribe/unwatch, in-app notifications on update) | ✅ |
|
||||
| Time tracking (IT staff log minutes per ticket, AJAX form) | ✅ |
|
||||
|
||||
---
|
||||
|
||||
@@ -608,7 +645,7 @@ proxies; static files are served directly).
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 2026-04-17*
|
||||
*Last updated: 2026-05-22*
|
||||
|
||||
## 18. Notification Architecture
|
||||
|
||||
@@ -717,6 +754,7 @@ When an error is reported:
|
||||
| `002_add_system_settings` | Create `system_settings` table |
|
||||
| `003_render_comments` | Backfill comment bodies to HTML; widen `alembic_version.version_num` to `VARCHAR(64)` |
|
||||
| `004_widen_system_setting_value` | Widen `system_settings.value` from `VARCHAR(500)` to `TEXT` |
|
||||
| `005_add_watchers_and_time_entries` | Create `ticket_watchers` (UniqueConstraint + index) and `time_entries` (index) tables |
|
||||
|
||||
## 21. Browser Tab Notification Counter (added 2026-04-17)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user