feat: notifications, audit logging, and admin improvements

- Add centralized notification service with webhook (Discord/Slack) and
  email (SMTP) support, triggered for trip invites, booking changes,
  collab messages, and trip reminders
- Webhook sends one message per event (group channel); email sends
  individually per trip member, excluding the actor
- Discord invite notifications now include the invited user's name
- Add LOG_LEVEL env var (info/debug) controlling console and file output
- INFO logs show user email, action, and IP for audit events; errors
  for HTTP requests
- DEBUG logs show every request with full body/query (passwords redacted),
  audit details, notification params, and webhook payloads
- Add persistent trek.log file logging with 10MB rotation (5 files)
  in /app/data/logs/
- Color-coded log levels in Docker console output
- Timestamps without timezone name (user sets TZ via Docker)
- Add Test Webhook and Save buttons to admin notification settings
- Move notification event toggles to admin panel
- Add daily trip reminder scheduler (9 AM, timezone-aware)
- Wire up booking create/update/delete and collab message notifications
- Add i18n keys for notification UI across all 13 languages

Made-with: Cursor
This commit is contained in:
Andrei Brebene
2026-03-31 15:01:33 +03:00
parent f7160e6dec
commit 9b2f083e4b
35 changed files with 1004 additions and 249 deletions

View File

@@ -1,31 +1,30 @@
services:
init-permissions:
image: alpine:3.20
container_name: trek-init-permissions
user: "0:0"
command: >
sh -c "mkdir -p /app/data /app/uploads &&
chown -R 1000:1000 /app/data /app/uploads &&
chmod -R u+rwX /app/data /app/uploads"
volumes:
- ./data:/app/data
- ./uploads:/app/uploads
restart: "no"
app:
image: mauriceboe/trek:latest
container_name: trek
depends_on:
init-permissions:
condition: service_completed_successfully
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- CHOWN
- SETUID
- SETGID
tmpfs:
- /tmp:noexec,nosuid,size=64m
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- JWT_SECRET=${JWT_SECRET:-}
# - ALLOWED_ORIGINS=https://yourdomain.com # Optional: restrict CORS to specific origins
# ALLOWED_ORIGINS: restrict CORS + used as the app URL in email notification links
# If not set, same-origin CORS is used and email links default to http://localhost:PORT
- ALLOWED_ORIGINS=${ALLOWED_ORIGINS:-}
- PORT=3000
- TZ=${TZ:-UTC}
# LOG_LEVEL: info (default) or debug (verbose details in docker logs)
- LOG_LEVEL=${LOG_LEVEL:-info}
volumes:
- ./data:/app/data
- ./uploads:/app/uploads