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:
@@ -173,8 +173,17 @@ class StoreTeamService:
|
||||
f"as {role_name} by {inviter.username}"
|
||||
)
|
||||
|
||||
# TODO: Send invitation email
|
||||
# self._send_invitation_email(email, store, invitation_token)
|
||||
try:
|
||||
self._send_invitation_email(
|
||||
db=db,
|
||||
email=email,
|
||||
store=store,
|
||||
token=invitation_token,
|
||||
inviter=inviter,
|
||||
role_name=role_name,
|
||||
)
|
||||
except Exception: # noqa: EXC003
|
||||
logger.exception(f"Failed to send invitation email to {email}")
|
||||
|
||||
audit_aggregator.log(
|
||||
db=db,
|
||||
@@ -827,14 +836,35 @@ class StoreTeamService:
|
||||
db.flush()
|
||||
return role
|
||||
|
||||
def _send_invitation_email(self, email: str, store: Store, token: str):
|
||||
"""Send invitation email (TODO: implement)."""
|
||||
# TODO: Implement email sending
|
||||
# Should include:
|
||||
# - Link to accept invitation: /store/invitation/accept?token={token}
|
||||
# - Store name
|
||||
# - Inviter name
|
||||
# - Expiry date
|
||||
def _send_invitation_email(
|
||||
self,
|
||||
db: Session,
|
||||
email: str,
|
||||
store: Store,
|
||||
token: str,
|
||||
inviter: User,
|
||||
role_name: str,
|
||||
):
|
||||
"""Send team invitation email."""
|
||||
from app.modules.messaging.services.email_service import EmailService
|
||||
|
||||
acceptance_link = f"/store/invitation/accept?token={token}"
|
||||
|
||||
email_service = EmailService(db)
|
||||
email_service.send_template(
|
||||
template_code="team_invitation",
|
||||
to_email=email,
|
||||
variables={
|
||||
"invited_by_name": inviter.username,
|
||||
"store_name": store.name or store.store_code,
|
||||
"role_name": role_name,
|
||||
"acceptance_link": acceptance_link,
|
||||
"expiry_days": "7",
|
||||
},
|
||||
store_id=store.id,
|
||||
user_id=inviter.id,
|
||||
related_type="store_user",
|
||||
)
|
||||
|
||||
|
||||
# Create service instance
|
||||
|
||||
Reference in New Issue
Block a user