Commit Graph

9 Commits

Author SHA1 Message Date
jubnl
5cc81ae4b0 refactor(server): replace node-fetch with native fetch + undici, fix photo integrations
Replace node-fetch v2 with Node 22's built-in fetch API across the entire server.
Add undici as an explicit dependency to provide the dispatcher API needed for
DNS pinning (SSRF rebinding prevention) in ssrfGuard.ts. All seven service files
that used a plain `import fetch from 'node-fetch'` are updated to use the global.
The ssrfGuard safeFetch/createPinnedAgent is rewritten as createPinnedDispatcher
using an undici Agent, with correct handling of the `all: true` lookup callback
required by Node 18+. The collabService dynamic require() and notifications agent
option are updated to use the dispatcher pattern. Test mocks are migrated from
vi.mock('node-fetch') to vi.stubGlobal('fetch'), and streaming test fixtures are
updated to use Web ReadableStream instead of Node Readable.

Fix several bugs in the Synology and Immich photo integrations:
- pipeAsset: guard against setting headers after stream has already started
- _getSynologySession: clear stale SID and re-login when decrypt_api_key returns null
  instead of propagating success(null) downstream
- _requestSynologyApi: return retrySession error (not stale session) on retry failure;
  also retry on error codes 106 (timeout) and 107 (duplicate login), not only 119
- searchSynologyPhotos: fix incorrect total field type (Synology list_item returns no
  total); hasMore correctly uses allItems.length === limit
- _splitPackedSynologyId: validate cache_key format before use; callers return 400
- getImmichCredentials / _getSynologyCredentials: treat null from decrypt_api_key as
  a missing-credentials condition rather than casting null to string
- Synology size param: enforce allowlist ['sm', 'm', 'xl'] per API documentation
2026-04-05 21:12:51 +02:00
jubnl
7b37d337c1 fix(security): address notification system security audit findings
- SSRF: guard sendWebhook() with checkSsrf() + createPinnedAgent() to block
  requests to loopback, link-local, private network, and cloud metadata endpoints
- XSS: escape subject, body, and ctaHref in buildEmailHtml() via escapeHtml()
  to prevent HTML injection through user-controlled params (actor, preview, etc.)
- Encrypt webhook URLs at rest: apply maybe_encrypt_api_key on save
  (settingsService for user URLs, authService for admin URL) and decrypt_api_key
  on read in getUserWebhookUrl() / getAdminWebhookUrl()
- Log failed channel dispatches: inspect Promise.allSettled() results and log
  rejections via logError instead of silently dropping them
- Log admin webhook failures: replace fire-and-forget .catch(() => {}) with
  .catch(err => logError(...)) and await the call
- Migration 69: guard against missing notification_preferences table on fresh installs
- Migration 70: drop the now-unused notification_preferences table
- Refactor: extract applyUserChannelPrefs() helper to deduplicate
  setPreferences / setAdminPreferences logic
- Tests: add SEC-016 (XSS, 5 cases) and SEC-017 (SSRF, 6 cases) test suites;
  mock ssrfGuard in notificationService tests
2026-04-05 03:36:50 +02:00
jubnl
fc29c5f7d0 feat(notifications): add unified multi-channel notification system
Introduces a fully featured notification system with three delivery
channels (in-app, email, webhook), normalized per-user/per-event/
per-channel preferences, admin-scoped notifications, scheduled trip
reminders and version update alerts.

- New notificationService.send() as the single orchestration entry point
- In-app notifications with simple/boolean/navigate types and WebSocket push
- Per-user preference matrix with normalized notification_channel_preferences table
- Admin notification preferences stored globally in app_settings
- Migration 69 normalizes legacy notification_preferences table
- Scheduler hooks for daily trip reminders and version checks
- DevNotificationsPanel for testing in dev mode
- All new tests passing, covering dispatch, preferences, migration, boolean
  responses, resilience, and full API integration (NSVC, NPREF, INOTIF,
  MIGR, VNOTIF, NROUTE series)
 - Previous tests passing
2026-04-05 01:22:18 +02:00
Julien G.
905c7d460b Add comprehensive backend test suite (#339)
* add test suite, mostly covers integration testing, tests are only backend side

* workflow runs the correct script

* workflow runs the correct script

* workflow runs the correct script

* unit tests incoming

* Fix multer silent rejections and error handler info leak

- Revert cb(null, false) to cb(new Error(...)) in auth.ts, collab.ts,
  and files.ts so invalid uploads return an error instead of silently
  dropping the file
- Error handler in app.ts now always returns 500 / "Internal server
  error" instead of forwarding err.message to the client

* Use statusCode consistently for multer errors and error handler

- Error handler in app.ts reads err.statusCode to forward the correct
  HTTP status while keeping the response body generic
2026-04-03 13:17:53 +02:00
jubnl
d4e16ebe49 fix: use APP_URL is defined as base url in mails 2026-04-03 03:44:45 +02:00
jubnl
1b28bd96d4 fix: encrypt SMTP password at rest using AES-256-GCM
The smtp_pass setting was stored as plaintext in app_settings, exposing
SMTP credentials to anyone with database read access. Apply the same
encrypt_api_key/decrypt_api_key pattern already used for OIDC client
secrets and API keys. A new migration transparently re-encrypts any
existing plaintext value on startup; decrypt_api_key handles legacy
plaintext gracefully so in-flight reads remain safe during upgrade.
2026-04-01 07:56:43 +02:00
Andrei Brebene
9b2f083e4b 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
2026-03-31 22:23:23 +03:00
Maurice
b1138eb9db fix: shared page language redirect + skip TLS for self-signed certs — closes #163 #164
- Language change on public shared page no longer triggers API call / login redirect
- New "Skip TLS certificate check" toggle in Admin > SMTP settings
- Also configurable via SMTP_SKIP_TLS_VERIFY=true env var
2026-03-30 22:26:09 +02:00
Maurice
d189d6d776 feat: email notifications, webhook support, ICS export — closes #110
Email Notifications:
- SMTP configuration in Admin > Settings (host, port, user, pass, from)
- App URL setting for email CTA links
- Webhook URL support (Discord, Slack, custom)
- Test email button with SMTP validation
- Beautiful HTML email template with TREK logo, slogan, red heart footer
- All notification texts translated in 8 languages (en/de/fr/es/nl/ru/zh/ar)
- Emails sent in each user's language preference

Notification Events:
- Trip invitation (member added)
- Booking created (new reservation)
- Vacay fusion invite
- Photos shared (Immich)
- Collab chat message
- Packing list category assignment

User Notification Preferences:
- Per-user toggle for each event type in Settings
- Addon-aware: Vacay/Collab/Photos toggles hidden when addon disabled
- Webhook opt-in per user

ICS Calendar Export:
- Download button next to PDF in day plan header
- Exports trip dates + all reservations with details
- Compatible with Google Calendar, Apple Calendar, Outlook

Technical:
- Nodemailer for SMTP
- notification_preferences DB table with per-event columns
- GET/PUT /auth/app-settings for admin config persistence
- POST /notifications/test-smtp for validation
- Dynamic imports for non-blocking notification sends
2026-03-30 17:07:33 +02:00