feat: production launch — email audit, team invites, security headers, router fixes
- Fix loyalty & monitoring router bugs (_get_router → named routers) - Implement team invitation email with send_template + seed templates (en/fr/de) - Add SecurityHeadersMiddleware (nosniff, HSTS, referrer-policy, permissions-policy) - Build email audit admin page: service, schemas, API, page route, menu, i18n, HTML, JS - Clean stale TODO in platform-menu-config.js - Add 67 tests (unit + integration) covering all new functionality Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -245,3 +245,74 @@ class EmailTestResponse(BaseModel):
|
||||
success: bool
|
||||
message: str
|
||||
email_log_id: int | None = None
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Email Log (Audit) Schemas
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class EmailLogListItem(BaseModel):
|
||||
"""Compact email log item (no body content)."""
|
||||
|
||||
id: int
|
||||
recipient_email: str
|
||||
recipient_name: str | None = None
|
||||
subject: str
|
||||
status: str
|
||||
template_code: str | None = None
|
||||
provider: str | None = None
|
||||
store_id: int | None = None
|
||||
related_type: str | None = None
|
||||
related_id: int | None = None
|
||||
created_at: str | None = None
|
||||
sent_at: str | None = None
|
||||
error_message: str | None = None
|
||||
|
||||
|
||||
class EmailLogDetail(BaseModel):
|
||||
"""Full email log detail including body content."""
|
||||
|
||||
id: int
|
||||
recipient_email: str
|
||||
recipient_name: str | None = None
|
||||
subject: str
|
||||
status: str
|
||||
template_code: str | None = None
|
||||
provider: str | None = None
|
||||
store_id: int | None = None
|
||||
user_id: int | None = None
|
||||
related_type: str | None = None
|
||||
related_id: int | None = None
|
||||
from_email: str | None = None
|
||||
from_name: str | None = None
|
||||
reply_to: str | None = None
|
||||
body_html: str | None = None
|
||||
body_text: str | None = None
|
||||
error_message: str | None = None
|
||||
retry_count: int = 0
|
||||
provider_message_id: str | None = None
|
||||
created_at: str | None = None
|
||||
sent_at: str | None = None
|
||||
delivered_at: str | None = None
|
||||
opened_at: str | None = None
|
||||
clicked_at: str | None = None
|
||||
extra_data: str | None = None
|
||||
|
||||
|
||||
class EmailLogListResponse(BaseModel):
|
||||
"""Paginated email log list."""
|
||||
|
||||
items: list[EmailLogListItem]
|
||||
total: int
|
||||
page: int
|
||||
per_page: int
|
||||
total_pages: int
|
||||
|
||||
|
||||
class EmailLogStatsResponse(BaseModel):
|
||||
"""Email log statistics."""
|
||||
|
||||
by_status: dict[str, int] = Field(default_factory=dict)
|
||||
by_template: dict[str, int] = Field(default_factory=dict)
|
||||
total: int = 0
|
||||
|
||||
Reference in New Issue
Block a user