Commit Graph

314 Commits

Author SHA1 Message Date
Gérnyi Márk
d48714d17a
feat: add copy/duplicate trip from dashboard (#270)
New POST /api/trips/:id/copy endpoint that deep copies all trip
planning data (days, places, assignments, reservations, budget,
packing, accommodations, day notes) with proper FK remapping
inside a transaction. Skips files, collab data, and members.

Copy button on all dashboard card types (spotlight, grid, list,
archived) gated by trip_create permission. Translations for all
12 languages.

Also adds reminder_days to Trip interface (removes as-any casts).
2026-04-03 12:38:45 +02:00
Wojciech Chrzan
a0db42fbfe
feat(i18n): add Polish language support (#252) 2026-04-03 12:28:48 +02:00
Julien G.
f4d0ccb454
Merge pull request #344 from marco783/addPeopleCount
added trip member count to dashboard
2026-04-03 11:23:10 +02:00
Marco Pasquali
a40983e65e added trip member count to dashboard
added translations for  (generated with AI, so they could be wrong)
2026-04-03 11:10:21 +02:00
Julien G.
0b77fe5292
Merge pull request #277 from Cod3d1PA/feat/holiday-hover-tooltip
feat: show holiday name on hover in calendar
2026-04-03 04:27:39 +02:00
jubnl
9afb51fcc0
fix: ensure invite link shows the register page. Closes #335 2026-04-03 03:58:44 +02:00
micro92
1e44b25a0c Add Accomodation to PDF 2026-04-02 20:59:02 -04:00
jubnl
74e3f85866
fix: finish rename refactor 2026-04-02 19:09:43 +02:00
jubnl
bbf3f0cae8
fix: update import paths after client-side file renames
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 18:59:22 +02:00
jubnl
c0e9a771d6
feat: add in-app notification system with real-time delivery
Introduces a full in-app notification system with three types (simple,
boolean with server-side callbacks, navigate), three scopes (user, trip,
admin), fan-out persistence per recipient, and real-time push via
WebSocket. Includes a notification bell in the navbar, dropdown, dedicated
/notifications page, and a dev-only admin tab for testing all notification
variants.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 18:57:52 +02:00
Maurice
f0131632a7 fix: show icon-only trip tabs on mobile to prevent overflow 2026-04-02 15:05:36 +02:00
Maurice
ffe91604b5
Merge pull request #273 from lucaam/undo_button_v2
feat: undo button for trip planner (+ fix to route preview)
2026-04-02 14:59:16 +02:00
Maurice
e7fa8f5da9 fix: widen budget sidebar from 180px to 240px to prevent clipping 2026-04-02 14:55:10 +02:00
Maurice
3256f5156d fix: photo marker badge now renders above circle instead of clipped inside 2026-04-02 14:50:08 +02:00
jubnl
c944a7d101
fix: allow unauthenticated access to public share links
Skip loadUser() and exclude /shared/ from the 401 redirect interceptor
so unauthenticated users can open shared trip links without being
redirected to /login. Fixes #308.
2026-04-02 14:05:38 +02:00
jubnl
45e0c7e546
fix: replace toast.warn with toast.warning in Immich save handler
toast.warn does not exist in the toast library; calling it threw an error
that was caught and displayed as "Could not connect to Immich" even when
the save succeeded. Fixes #309.
2026-04-02 13:59:08 +02:00
jubnl
1a4c04e239
fix: resolve Immich 401 passthrough causing spurious login redirects
- Auth middleware now tags its 401s with code: AUTH_REQUIRED so the
  client interceptor only redirects to /login on genuine session failures,
  not on upstream API errors
- Fix /albums and album sync routes using raw encrypted API key instead
  of getImmichCredentials() (which decrypts it), causing Immich to reject
  requests with 401
- Add toast error notifications for all Immich operations in MemoriesPanel
  that previously swallowed errors silently

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 21:19:53 +02:00
jubnl
e71bd6768e
fix: show actual backend error messages on login page and add missing db import
- LoginPage now uses getApiErrorMessage() instead of err.message so
  backend validation errors (e.g. "Password must be at least 8 characters")
  are displayed instead of the generic "Request failed with status code 400"
- Add missing db import in server/src/index.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 20:37:01 +02:00
Maurice
71403e6303 fix: always fetch fresh photo URLs for map markers instead of using stored HTTP URLs 2026-04-01 19:48:58 +02:00
Maurice
43fc4db00e fix: convert stored HTTP photo URLs to base64 for map markers, add exchangerate-api to CSP 2026-04-01 19:40:19 +02:00
Maurice
228cb05932 chore: bump version to 2.7.2 2026-04-01 19:13:32 +02:00
Cod3d1PA
505bf04a1f feat: show holiday name on hover in calendar
Add a native title tooltip to calendar day cells so hovering over a
public holiday reveals its name (and custom label if configured).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 17:01:15 +00:00
Luca
41bfcf2f76
fix: stale closure in updateRouteForDay causes route to disappear on place click
useCallback captured tripStore at creation time (dep: [routeCalcEnabled]).
If assignments were empty on first render (trip still loading), the callback
would permanently see empty assignments and call setRoute(null) whenever
invoked — e.g. when clicking a place triggers onSelectDay → updateRouteForDay.

Fix: store tripStore in a ref updated on every render so the callback always
reads the latest assignments without needing to be recreated.
2026-04-01 18:29:40 +02:00
Luca
e308204808
feat: undo button for trip planner
Implements a full undo history system for the Plan screen.

New hook: usePlannerHistory (client/src/hooks/usePlannerHistory.ts)
- Maintains a LIFO stack (up to 30 entries) of reversible actions
- Exposes pushUndo(label, fn), undo(), canUndo, lastActionLabel

Tracked actions:
- Assign place to day (undo: remove the assignment)
- Remove place from day (undo: re-assign at original position)
- Reorder places within a day (undo: restore previous order)
- Move place to a different day (undo: move back)
- Optimize route (undo: restore original order)
- Lock / unlock place (undo: toggle back)
- Delete place (undo: recreate place + restore all day assignments)
- Add place (undo: delete it)
- Import from GPX (undo: delete all imported places)
- Import from Google Maps list (undo: delete all imported places)

UI: Undo button (Undo2 icon) in DayPlanSidebar header. PDF, ICS and
Undo buttons all use custom instant hover tooltips instead of native
title attributes.

A toast notification confirms each undo action.

Translations: undo.* keys added to all 12 language files.
2026-04-01 18:20:14 +02:00
Maurice
411d5408c1 fix: place inspector too narrow at intermediate window widths (#272)
Inspector now ignores sidebar widths when window is under 900px,
preventing it from being squeezed when sidebars are visually hidden
but their width values are still set.
2026-04-01 17:58:57 +02:00
Julien G.
edafe01387
Merge branch 'dev' into dev 2026-04-01 17:30:31 +02:00
Maurice
ef5b381f8e feat: collapse days hides map markers, Immich test-before-save (#216)
Map markers:
- Collapsing a day in the sidebar hides its places from the map
- Places assigned to multiple days only hide when all days collapsed
- Unplanned places always stay visible

Immich settings:
- New POST /integrations/immich/test endpoint validates credentials
  without saving them
- Save button disabled until test connection passes
- Changing URL or API key resets test status
- i18n: testFirst key for all 12 languages
2026-04-01 15:30:59 +02:00
Maurice
ef9880a2a5 feat: Immich album linking with auto-sync (#206)
- Link Immich albums to trips — photos sync automatically
- Album picker shows all user's Immich albums
- Linked albums displayed as chips with sync/unlink buttons
- Auto-sync on link: fetches all album photos and adds to trip
- Manual re-sync button for each linked album
- DB migration: trip_album_links table

fix: shared Immich photos visible to other trip members

- Thumbnail/original proxy now uses photo owner's Immich credentials
  when userId query param is provided, fixing 404 for shared photos
- i18n: album keys for all 12 languages
2026-04-01 15:21:20 +02:00
Maurice
95cb81b0e5 perf: major trip planner performance overhaul (#218)
Store & re-render optimization:
- TripPlannerPage uses selective Zustand selectors instead of full store
- placesSlice only updates affected days on place update/delete
- Route calculation only reacts to selected day's assignments
- DayPlanSidebar uses stable action refs instead of full store

Map marker performance:
- Shared photoService for PlaceAvatar and MapView (single cache, no duplicate requests)
- Client-side base64 thumbnail generation via canvas (CORS-safe for Wikimedia)
- Map markers use base64 data URL <img> tags for smooth zoom (no external image decode)
- Sidebar uses same base64 thumbnails with IntersectionObserver for visible-first loading
- Icon cache prevents duplicate L.divIcon creation
- MarkerClusterGroup with animate:false and optimized chunk settings
- Photo fetch deduplication and batched state updates

Server optimizations:
- Wikimedia image size reduced to 400px (from 600px)
- Photo cache: 5min TTL for errors (was 12h), prevents stale 404 caching
- Removed unused image-proxy endpoint

UX improvements:
- Splash screen with plane animation during initial photo preload
- Markdown rendering in DayPlanSidebar place descriptions
- Missing i18n keys added, all 12 languages synced to 1376 keys
2026-04-01 14:56:01 +02:00
Maurice
7d0ae631b8 fix: mobile place editing and detail view (#269)
- PlacesSidebar mobile: tap opens action sheet with view details,
  edit, assign to day, and delete options
- PlaceInspector renders as fullscreen portal overlay on mobile
- DayPlanSidebar mobile: tapping a place closes overlay and opens
  inspector
- Inspector closes when edit or delete is triggered on mobile
- i18n: added places.viewDetails for all 12 languages
2026-04-01 12:38:44 +02:00
Maurice
5c04074d54 fix: allow unauthenticated SMTP by saving empty user/pass fields (#265)
The test-smtp button filtered out empty SMTP user/password values
before saving, preventing unauthenticated SMTP setups from working.
Changed filter from truthy check to !== undefined so empty strings
are properly persisted.
2026-04-01 12:20:03 +02:00
Maurice
e89ba2ecfc fix: add referrerPolicy to TileLayer to fix OSM tile blocking (#264)
OpenStreetMap requires a Referer header per their tile usage policy.
Without it, tiles are blocked with "Access blocked" error.
2026-04-01 12:17:53 +02:00
Maurice
4ebf9c5f11 feat: add expense date and CSV export to budget
- New expense_date column on budget items (DB migration #42)
- Date column in budget table with custom date picker
- CSV export button with BOM, semicolon separator, localized dates,
  currency in header, per-person/day calculations
- CustomDatePicker compact/borderless modes for inline table use
- i18n keys for all 12 languages
2026-04-01 12:16:11 +02:00
jubnl
add0b17e04
feat(auth): migrate JWT storage from localStorage to httpOnly cookies
Eliminates XSS token theft risk by storing session JWTs in an httpOnly
cookie (trek_session) instead of localStorage, making them inaccessible
to JavaScript entirely.

- Add cookie-parser middleware and setAuthCookie/clearAuthCookie helpers
- Set trek_session cookie on login, register, demo-login, MFA verify, OIDC exchange
- Auth middleware reads cookie first, falls back to Authorization: Bearer (MCP unchanged)
- Add POST /api/auth/logout to clear the cookie server-side
- Remove all localStorage auth_token reads/writes from client
- Axios uses withCredentials; raw fetch calls use credentials: include
- WebSocket ws-token exchange uses credentials: include (no JWT param)
- authStore initialises isLoading: true so ProtectedRoute waits for /api/auth/me

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 11:02:45 +02:00
Maurice
60906cf1d1 fix: hide MCP tokens tab when addon inactive, move permissions to users tab
- MCP tokens tab only shown when MCP addon is enabled
- Permissions panel moved from own tab to users tab below invite links
- Fixed inconsistent dropdown widths in permissions panel
2026-04-01 10:39:43 +02:00
Julien G.
9292acb979
Merge branch 'dev' into dev 2026-04-01 10:27:51 +02:00
Maurice
be57b7130f feat: render markdown in place descriptions, notes and reservations
Use react-markdown with remark-gfm for place description/notes
in PlaceInspector and day note subtitles and reservation notes
in DayPlanSidebar. Reuses existing collab-note-md CSS styles.
2026-04-01 10:19:59 +02:00
Maurice
040840917c feat: add Google Maps list import
Import places from shared Google Maps lists via URL.
Button in places sidebar next to GPX import opens a modal
where users can paste a shared list link. Server fetches
list data from Google Maps and creates places with name,
coordinates and notes. i18n keys added for all 12 languages.

Closes #205
2026-04-01 10:13:35 +02:00
jubnl
7a314a92b1
fix: add SSRF protection for link preview and Immich URL
- Create server/src/utils/ssrfGuard.ts with checkSsrf() and createPinnedAgent()
  - Resolves DNS before allowing outbound requests to catch hostnames that
    map to private IPs (closes the TOCTOU gap in the old inline checks)
  - Always blocks loopback (127.x, ::1) and link-local/metadata (169.254.x)
  - RFC-1918, CGNAT (100.64/10), and IPv6 ULA ranges blocked by default;
    opt-in via ALLOW_INTERNAL_NETWORK=true for self-hosters running Immich
    on a local network
  - createPinnedAgent() pins node-fetch to the validated IP, preventing
    DNS rebinding between the check and the actual connection

- Replace isValidImmichUrl() (hostname-string check, no DNS resolution)
  with checkSsrf(); make PUT /integrations/immich/settings async
  - Audit log entry (immich.private_ip_configured) written when a user
    saves an Immich URL that resolves to a private IP
  - Response includes a warning field surfaced as a toast in the UI

- Replace ~20 lines of duplicated inline SSRF logic in the link-preview
  handler with a single checkSsrf() call + pinned agent

- Document ALLOW_INTERNAL_NETWORK in README, docker-compose.yml,
  server/.env.example, chart/values.yaml, chart/templates/configmap.yaml,
  and chart/README.md
2026-04-01 07:59:03 +02:00
jubnl
e03505dca2
fix: enforce consistent password policy across all auth flows
Replace duplicated inline validation with a shared validatePassword()
utility that checks minimum length (8), rejects repetitive and common
passwords, and requires uppercase, lowercase, a digit, and a special
character.

- Add server/src/services/passwordPolicy.ts as single source of truth
- Apply to registration, password change, and admin create/edit user
  (admin routes previously had zero validation)
- Fix client min-length mismatch (6 vs 8) in RegisterPage and LoginPage
- Add client-side password length guard to AdminPage forms
- Update register.passwordTooShort and settings.passwordWeak i18n keys
  in all 12 locales to reflect the corrected requirements
2026-04-01 07:58:46 +02:00
jubnl
6f5550dc50
fix: decouple at-rest encryption from JWT_SECRET, add JWT rotation
Introduces a dedicated ENCRYPTION_KEY for encrypting stored secrets
(API keys, MFA TOTP, SMTP password, OIDC client secret) so that
rotating the JWT signing secret no longer invalidates encrypted data,
and a compromised JWT_SECRET no longer exposes stored credentials.

- server/src/config.ts: add ENCRYPTION_KEY (auto-generated to
  data/.encryption_key if not set, same pattern as JWT_SECRET);
  switch JWT_SECRET to `export let` so updateJwtSecret() keeps the
  CJS module binding live for all importers without restart
- apiKeyCrypto.ts, mfaCrypto.ts: derive encryption keys from
  ENCRYPTION_KEY instead of JWT_SECRET
- admin POST /rotate-jwt-secret: generates a new 32-byte hex secret,
  persists it to data/.jwt_secret, updates the live in-process binding
  via updateJwtSecret(), and writes an audit log entry
- Admin panel (Settings → Danger Zone): "Rotate JWT Secret" button
  with a confirmation modal warning that all sessions will be
  invalidated; on success the acting admin is logged out immediately
- docker-compose.yml, .env.example, README, Helm chart (values.yaml,
  secret.yaml, deployment.yaml, NOTES.txt, README): document
  ENCRYPTION_KEY and its upgrade migration path
2026-04-01 07:57:55 +02:00
jubnl
78695b4e03
fix: replace JWT tokens in URL query params with short-lived ephemeral tokens
Addresses CWE-598: long-lived JWTs were exposed in WebSocket URLs, file
download links, and Immich asset proxy URLs, leaking into server logs,
browser history, and Referer headers.

- Add ephemeralTokens service: in-memory single-use tokens with per-purpose
  TTLs (ws=30s, download/immich=60s), max 10k entries, periodic cleanup
- Add POST /api/auth/ws-token and POST /api/auth/resource-token endpoints
- WebSocket auth now consumes an ephemeral token instead of verifying the JWT
  directly from the URL; client fetches a fresh token before each connect
- File download ?token= query param now accepts ephemeral tokens; Bearer
  header path continues to accept JWTs for programmatic access
- Immich asset proxy replaces authFromQuery JWT injection with ephemeral token
  consumption
- Client: new getAuthUrl() utility, AuthedImg/ImmichImg components, and async
  onClick handlers replace the synchronous authUrl() pattern throughout
  FileManager, PlaceInspector, and MemoriesPanel
- Add OIDC_DISCOVERY_URL env var and oidc_discovery_url DB setting to allow
  overriding the auto-constructed discovery endpoint (required for Authentik
  and similar providers); exposed in the admin UI and .env.example
2026-04-01 07:57:14 +02:00
jubnl
c9341eda3f
fix: remove RCE vector from admin update endpoint.
The POST /api/admin/update endpoint ran git pull, npm install, and npm run build via execSync, potentially giving any compromised admin account full code execution on the host in case repository is compromised. TREK ships as a Docker image so runtime self-updating is unnecessary.
- Remove the /update route and child_process import from admin.ts
- Remove the installUpdate API client method
- Replace the live-update modal with an info-only panel showing docker pull instructions and a link to the GitHub release
- Drop the updating/updateResult state and handleInstallUpdate handler
2026-04-01 07:55:34 +02:00
Maurice
fb2e8d8209 fix: keep marker tooltip visible on touch devices when selected
On mobile/touch devices, Leaflet tooltips disappear immediately on tap
since there is no hover state. This makes the info bubble permanent for
the selected marker on touch devices so it stays readable.

Fixes #249
2026-04-01 00:11:12 +02:00
Gérnyi Márk
9a2c7c5db6
fix: address PR review feedback
- Suppress note context menu when canEditDays is false instead of
  showing empty menu
- Untie poll voting from collab_edit — voting is participation, not
  editing; any trip member can vote
- Restore NoteFormModal props (note, tripId) to required; remove
  leftover canUploadFiles prop in favor of direct zustand hook
2026-03-31 23:56:19 +02:00
Gérnyi Márk
1fbc19ad4f
fix: add missing permission checks to file routes and map context menu
- Add checkPermission to 6 unprotected file endpoints (star, restore,
  permanent delete, empty trash, link, unlink)
- Gate map right-click place creation with place_edit permission
- Use file_upload permission for collab note file uploads
2026-03-31 23:45:11 +02:00
Gérnyi Márk
23edfe3dfc
fix: harden permissions system after code review
- Gate permissions in /app-config behind optionalAuth so unauthenticated
  requests don't receive admin configuration
- Fix trip_delete isMember parameter (was hardcoded false)
- Return skipped keys from savePermissions for admin visibility
- Add disabled prop to CustomSelect, use in BudgetPanel currency picker
- Fix CollabChat reaction handler returning false instead of void
- Pass canUploadFiles as prop to NoteFormModal instead of internal store read
- Make edit-only NoteFormModal props optional (onDeleteFile, note, tripId)
- Add missing trailing newlines to .gitignore and it.ts
2026-03-31 23:36:17 +02:00
Gérnyi Márk
1ff8546484
fix: i18n chat reply/delete titles, gate collab category settings 2026-03-31 23:36:17 +02:00
Gérnyi Márk
6d18d5ed2d
fix: gate collab notes category settings button with collab_edit 2026-03-31 23:36:16 +02:00
Gérnyi Márk
6d5067247c
refactor: remove dead isAdmin prop from dashboard cards
Permission gating via useCanDo() makes the isAdmin prop redundant —
admin bypass is handled inside the permission system itself.
2026-03-31 23:36:16 +02:00
Gérnyi Márk
5f71b85c06
feat: add client-side permission gating to all write-action UIs
Gate all mutating UI elements with useCanDo() permission checks:
- BudgetPanel (budget_edit), PackingListPanel (packing_edit)
- DayPlanSidebar, DayDetailPanel (day_edit)
- ReservationsPanel, ReservationModal (reservation_edit)
- CollabNotes, CollabPolls, CollabChat (collab_edit)
- FileManager (file_edit, file_delete, file_upload)
- PlaceFormModal, PlaceInspector, PlacesSidebar (place_edit, file_upload)
- TripFormModal (trip_edit, trip_cover_upload)
- DashboardPage (trip_edit, trip_cover_upload, trip_delete, trip_archive)
- TripMembersModal (member_manage, share_manage)

Also: fix redundant getTripOwnerId queries in trips.ts, remove dead
getTripOwnerId function, fix TripMembersModal grid when share hidden,
fix canRemove logic, guard TripListItem empty actions div.
2026-03-31 23:36:16 +02:00
Gérnyi Márk
015be3d53a
fix: incorrect hook order 2026-03-31 23:36:15 +02:00
Gérnyi Márk
7d3b37a2a3
feat: add configurable permissions system with admin panel
Adds a full permissions management feature allowing admins to control
who can perform actions across the app (trip CRUD, files, places,
budget, packing, reservations, collab, members, share links).

- New server/src/services/permissions.ts: 16 configurable actions,
  in-memory cache, checkPermission() helper, backwards-compatible
  defaults matching upstream behaviour
- GET/PUT /admin/permissions endpoints; permissions loaded into
  app-config response so clients have them on startup
- checkPermission() applied to all mutating route handlers across
  10 server route files; getTripOwnerId() helper eliminates repeated
  inline DB queries; trips.ts and files.ts now reuse canAccessTrip()
  result to avoid redundant DB round-trips
- New client/src/store/permissionsStore.ts: Zustand store +
  useCanDo() hook; TripOwnerContext type accepts both Trip and
  DashboardTrip shapes without casting at call sites
- New client/src/components/Admin/PermissionsPanel.tsx: categorised
  UI with per-action dropdowns, customised badge, save/reset
- AdminPage, DashboardPage, FileManager, PlacesSidebar,
  TripMembersModal gated via useCanDo(); no prop drilling
- 46 perm.* translation keys added to all 12 language files
2026-03-31 23:36:15 +02:00
Maurice
ff1c1ed56a Merge branch 'dev' of https://github.com/mauriceboe/TREK into dev 2026-03-31 23:23:17 +02:00
Maurice
d5674e9a11 fix: archive restore/delete buttons not visible in dark mode 2026-03-31 23:18:04 +02:00
Maurice
7eabe65bcf
Merge pull request #240 from Summerfeeling/feat/more-currencies
feat: added all supported currencies from exchangerate-api (#229)
2026-03-31 23:12:32 +02:00
Maurice
3444e3f446 Merge branch 'perf-test' of https://github.com/jubnl/TREK into dev
# Conflicts:
#	client/src/components/Map/MapView.tsx
2026-03-31 23:10:02 +02:00
Maurice
c38e70e244 fix: toggle switches not reflecting state in admin settings 2026-03-31 22:49:31 +02:00
Maurice
ce7215341f fix: 12h time format input and display in bookings
- Allow typing AM/PM in time input when 12h format is active
- Format end time correctly in reservations panel (handle time-only strings)
2026-03-31 22:40:59 +02:00
Maurice
4733955531 fix: render Lucide category icons on map markers instead of text/emoji 2026-03-31 22:35:43 +02:00
Maurice
36267de117 fix: bag modal cut off on small screens 2026-03-31 22:27:26 +02:00
Maurice
cd13399da5 fix: show selected map template in settings dropdown 2026-03-31 22:18:42 +02:00
Maurice
fbe3b5b17e
Merge pull request #225 from andreibrebene/improvements/various-improvements
Improvements/various improvements
2026-03-31 21:40:26 +02:00
Maurice
10107ecf31 fix: require auth for file downloads, localize atlas search, use flag images
- Block direct access to /uploads/files (401), serve via authenticated
  /api/trips/:tripId/files/:id/download with JWT verification
- Client passes auth token as query parameter for direct links
- Atlas country search now uses Intl.DisplayNames (user language) instead
  of English GeoJSON names
- Atlas search results use flagcdn.com flag images instead of emoji
2026-03-31 21:38:16 +02:00
Andrei Brebene
7522f396e7 feat: configurable trip reminders, admin full access, and enhanced audit logging
- Add configurable trip reminder days (1, 3, 9 or custom up to 30) settable by trip owner
- Grant administrators full access to edit, archive, delete, view and list all trips
- Show trip owner email in audit logs and docker logs when admin edits/deletes another user's trip
- Show target user email in audit logs when admin edits or deletes a user account
- Use email instead of username in all notifications (Discord/Slack/email) to avoid ambiguity
- Grey out notification event toggles when no SMTP/webhook is configured
- Grey out trip reminder selector when notifications are disabled
- Skip local admin account creation when OIDC_ONLY=true with OIDC configured
- Conditional scheduler logging: show disabled reason or active reminder count
- Log per-owner reminder creation/update in docker logs
- Demote 401/403 HTTP errors to DEBUG log level to reduce noise
- Hide edit/archive/delete buttons for non-owner invited users on trip cards
- Fix literal "0" rendering on trip cards from SQLite numeric is_owner field
- Add missing translation keys across all 14 language files

Made-with: Cursor
2026-03-31 22:23:38 +03: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
jubnl
9a949d7391
Performance on trip planner (Maybe ?) 2026-03-31 21:13:29 +02:00
Summerfeeling | Timo
13904fb702
feat: added all supported currencies from exchangerate-api (#229) 2026-03-31 21:04:59 +02:00
Maurice
f7160e6dec
Merge pull request #179 from shanelord01/audit/remediation-clean
Automated Security & Quality Audit via Claude Code
2026-03-31 20:53:48 +02:00
Maurice
1983691950 Merge branch 'feat/add-searchbar-in-atlas' of https://github.com/Akashic101/NOMAD into dev
# Conflicts:
#	client/src/i18n/translations/cs.ts
#	client/src/i18n/translations/it.ts
2026-03-31 20:29:23 +02:00
Maurice
6866644d0c
Merge pull request #189 from M-Enderle/feat/gpx-full-route-import
feat(add-gpx-tracks): adds better gpx track views
2026-03-31 20:17:22 +02:00
Maurice
1d442c1d7a
Merge pull request #182 from BKSalman/mobile-fixes
mobile UI fixes
2026-03-31 20:14:30 +02:00
Maurice
9a0294360c
Merge pull request #181 from BKSalman/accom-fix
fix: update dayAccommodations state after create/edit/delete
2026-03-31 20:10:42 +02:00
David Moll
8ff5ec486f
Merge branch 'main' into feat/add-searchbar-in-atlas 2026-03-31 12:31:14 +02:00
David Moll
5576339bcc
feat(atlas): add searchbar 2026-03-31 12:27:13 +02:00
Moritz Enderle
3aaa6e916b feat: adds better gpx track views 2026-03-31 10:29:49 +02:00
Salman Abuhaimed
299e26bebe
make day plan side bar icons more readable 2026-03-31 06:29:31 +03:00
Salman Abuhaimed
96b6d7d81f
fix: note modal hidden behind mobile sidebar due to z-index 2026-03-31 06:29:31 +03:00
Salman Abuhaimed
27d5c3400c
fix: update dayAccommodations state after create/edit/delete 2026-03-31 06:27:45 +03:00
Salman Abuhaimed
bb9c0c9b68
fix: day details on mobile not showing 2026-03-31 06:27:11 +03:00
Claude
483190e7c1
fix: XSS in GitHubPanel markdown renderer and RouteCalculator profile bug
Escape HTML entities before dangerouslySetInnerHTML in release notes
renderer to prevent stored XSS via malicious GitHub release bodies.
Fix RouteCalculator ignoring the profile parameter (was hardcoded to
'driving').

https://claude.ai/code/session_01SoQKcF5Rz9Y8Nzo4PzkxY8
2026-03-31 00:34:09 +00:00
Claude
2288f9d2fc
fix: harden PWA caching and client-side auth security
- Exclude sensitive API paths (auth, admin, backup, settings) from SW cache
- Restrict upload caching to public assets only (covers, avatars)
- Remove opaque response caching (status 0) for API and uploads
- Clear service worker caches on logout
- Only logout on 401 errors, not transient network failures
- Fix register() TypeScript interface to include invite_token parameter
- Remove unused RegisterPage and DemoBanner imports
- Disable source maps in production build
- Add SRI hash for Leaflet CSS CDN

https://claude.ai/code/session_01SoQKcF5Rz9Y8Nzo4PzkxY8
2026-03-31 00:33:58 +00:00
jubnl
fb643a1ade
fix: stop drop event bubbling causing duplicate place assignment 2026-03-31 01:32:20 +02:00
Maurice
069fd99341 Merge branch 'pr-169'
# Conflicts:
#	client/src/i18n/translations/ar.ts
#	client/src/i18n/translations/br.ts
#	client/src/i18n/translations/cs.ts
#	client/src/i18n/translations/de.ts
#	client/src/i18n/translations/en.ts
#	client/src/i18n/translations/es.ts
#	client/src/i18n/translations/fr.ts
#	client/src/i18n/translations/hu.ts
#	client/src/i18n/translations/it.ts
#	client/src/i18n/translations/nl.ts
#	client/src/i18n/translations/ru.ts
#	client/src/i18n/translations/zh.ts
#	client/src/pages/SettingsPage.tsx
2026-03-30 23:46:32 +02:00
Fernando Bona
13580ea5fb
Merge branch 'main' into feat/#155 2026-03-30 18:36:18 -03:00
Fernando Bona
aa5dd1abc6
Merge branch 'main' into fix/mfa-backup-codes 2026-03-30 18:27:46 -03:00
fgbona
de444bf770
fix(mfa-backup-codes): persist backup codes panel after enable and refresh
Keep MFA backup codes visible after enabling MFA by avoiding protected-route unmount during user reload (`loadUser({ silent: true })`) and restoring pending backup codes from sessionStorage until the user explicitly dismisses them.
2026-03-30 18:22:45 -03:00
Maurice
821f71ac28 fix: add MCP translation keys for cs, hu, it languages 2026-03-30 23:14:05 +02:00
Maurice
faebc62917 Merge branch 'pr-125'
# Conflicts:
#	client/src/api/client.ts
#	client/src/i18n/translations/ar.ts
#	client/src/i18n/translations/es.ts
#	client/src/i18n/translations/fr.ts
#	client/src/i18n/translations/nl.ts
#	client/src/i18n/translations/ru.ts
#	client/src/i18n/translations/zh.ts
#	client/src/pages/AdminPage.tsx
#	client/src/pages/SettingsPage.tsx
#	server/package.json
#	server/src/db/migrations.ts
#	server/src/index.ts
#	server/src/routes/admin.ts
2026-03-30 23:10:34 +02:00
Fernando Bona
41e572445c
Merge branch 'main' into feat/#155 2026-03-30 17:52:07 -03:00
fgbona
66f5ea50c5
feat(require-mfa): #155 enforce MFA via admin policy toggle across app access
Add an admin-controlled `require_mfa` policy in App Settings and expose it via `/auth/app-config` so the client can enforce it globally. Users without MFA are redirected to Settings after login and blocked from protected API/WebSocket access until setup is completed, while preserving MFA setup endpoints and admin recovery paths. Also prevent enabling the policy unless the acting admin already has MFA enabled, and block MFA disable while the policy is active. Includes UI toggle in Admin > Settings, required-policy notice in Settings, client-side 403 `MFA_REQUIRED` handling, and i18n updates for all supported locales.
2026-03-30 17:42:40 -03:00
Maurice
ce4b8088ec fix: force light mode on shared trip page 2026-03-30 22:32:58 +02: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
7272e0bbfd chore: bump version to 2.7.1 2026-03-30 21:25:35 +02:00
Maurice
c7eaf3aa79 feat: add Italian, Czech, Hungarian + sync all 12 languages
New languages: Italian (it), Czech (cs), Hungarian (hu)
Merged PRs #158, #130, #119 with conflict resolution.

All 12 language files synced to ~1238 keys each:
ar, br, cs, de, en, es, fr, hu, it, nl, ru, zh

Thanks @entropyst72 (Italian), @Numira-code (Czech),
@slashwarm (Hungarian) for the translations!
2026-03-30 21:22:53 +02:00
Maurice
deef5e6b81 Merge branch 'pr-130' into dev 2026-03-30 21:02:32 +02:00
Maurice
6d72006b28 Merge branch 'pr-158' into dev 2026-03-30 21:02:18 +02:00
Maurice
19c9e17884 Merge branch 'pr-120' into dev 2026-03-30 20:09:16 +02:00
Maurice
14ef2d4a4a Merge branch 'pr-117' into dev 2026-03-30 20:07:12 +02:00
Maurice
de859318fa feat: admin audit log — merged PR #118
Audit logging for admin actions, backups, auth events.
New AuditLogPanel in Admin tab with pagination.
Dockerfile security: run as non-root user.
i18n keys for all 9 languages.

Thanks @fgbona for the implementation!
2026-03-30 20:05:32 +02:00