Commit Graph

232 Commits

Author SHA1 Message Date
jubnl
c4c3ea1e6d fix(immich): remove album photos on unlink
When unlinking an Immich album, photos synced from that album are now
deleted. A new `album_link_id` FK column on `trip_photos` tracks the
source album link at sync time; `deleteAlbumLink` deletes matching
photos before removing the link. Individually-added photos are
unaffected. The client now refreshes the photo grid after unlinking.

Adds integration tests IMMICH-020 through IMMICH-024.

Closes #398
2026-04-04 16:37:14 +02:00
Julien G.
43c801232e Merge pull request #399 from mauriceboe/main
Align dev with main
2026-04-04 15:29:51 +02:00
github-actions[bot]
6825a4a0c1 chore: bump version to 2.8.4 [skip ci] 2026-04-04 13:20:50 +00:00
jubnl
8a4a8b58be fix(version): revert version and ensure nomad img is pushed to dockerhub 2026-04-04 15:20:33 +02:00
github-actions[bot]
be975f38a6 chore: bump version to 2.9.0 [skip ci] 2026-04-04 13:11:47 +00:00
jubnl
297cfda32b chore: resolve merge conflict in TRIP-002 test — keep dev version (checks both dates)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 14:57:32 +02:00
github-actions[bot]
d8367ec878 chore: bump version to 2.8.3 [skip ci] 2026-04-04 12:54:00 +00:00
jubnl
79057327fa Merge remote-tracking branch 'origin/main' 2026-04-04 14:53:40 +02:00
jubnl
0943184b1e test(trips): update TRIP-002 to reflect 7-day default window behavior 2026-04-04 14:53:12 +02:00
github-actions[bot]
a4752ae692 chore: bump version to 2.8.2 [skip ci] 2026-04-04 12:48:36 +00:00
jubnl
e6068d44b0 docs(oidc): fix OIDC_SCOPE default and clarify override behavior, skip CI for docs-only pushes, remove stale audit files 2026-04-04 14:48:11 +02:00
mauriceboe
50d2a211e5 fix(oidc): revert default scope to 'openid email profile'
Removes 'groups' from the default OIDC_SCOPE fallback, which caused
invalid_scope errors with providers that don't support it (e.g. Google).

Fixes #391
2026-04-04 13:33:54 +02:00
github-actions[bot]
5d3a740791 chore: bump version to 2.8.1 [skip ci] 2026-04-04 10:53:29 +00:00
mauriceboe
2c1c77f367 fix(oidc): revert default scope to 'openid email profile'
Removes 'groups' from the default OIDC_SCOPE fallback, which caused
invalid_scope errors with providers that don't support it (e.g. Google).

Fixes #391
2026-04-04 12:53:12 +02:00
github-actions[bot]
80d013dd19 chore: bump version to 2.8.0 [skip ci] 2026-04-03 22:35:37 +00:00
jubnl
846db9d076 test(trips): assert exact start/end dates in TRIP-002
Replace not-null checks with exact date assertions mirroring the
route's defaulting logic (tomorrow + 7-day window).
2026-04-04 00:19:54 +02:00
jubnl
a307d8d1c9 test(trips): update TRIP-002 to expect default 7-day window
Now that trips always default to a start+7 day window when no dates
are provided, the test expectation of null dates and zero dated days
is no longer valid.
2026-04-04 00:19:46 +02:00
jubnl
ae0d48ac83 fix(immich): check all trips when verifying shared photo access
canAccessUserPhoto was using .get() which only returned the first matching
trip, causing access to be incorrectly denied when a photo was shared across
multiple trips and the requester was a member of a non-first trip.
2026-04-04 00:14:34 +02:00
jubnl
6400c2d27d fix(mcp): wire check_in/check_out times through hotel accommodation tools
Adds optional check_in and check_out fields to create_reservation and
link_hotel_accommodation so MCP clients can set accommodation times,
matching the existing REST API behaviour.

Closes #363
2026-04-04 00:09:56 +02:00
jubnl
93c0d6fe78 fix(trips): default to 7-day window when dates are omitted on creation
- No dates → tomorrow to tomorrow+7d
- Start only → end = start+7d
- End only → start = end-7d
- Both provided → unchanged

fix(ci): include client/package-lock.json in version bump commit
2026-04-03 23:58:39 +02:00
jubnl
d765a80ea3 fix(immich): proxy shared photos using owner's Immich credentials
Trip members viewing another member's shared photo were getting a 404
because the proxy endpoints always used the requesting user's Immich
credentials instead of the photo owner's. The ?userId= query param the
client already sent was silently ignored.

- Add canAccessUserPhoto() to verify the asset is shared and the
  requesting user is a trip member before allowing cross-user proxying
- Pass optional ownerUserId through proxyThumbnail, proxyOriginal, and
  getAssetInfo so credentials are fetched for the correct user
- Enforce shared=1 check so unshared photos remain inaccessible
2026-04-03 22:32:41 +02:00
jubnl
6c72295424 fix(vacay): fix entitlement counter, year deletion, and year creation bugs
- toggleCompanyHoliday now calls loadStats() so the entitlement sidebar
  updates immediately when a vacation day is converted to a company holiday
- deleteYear now deletes vacay_user_years rows for the removed year,
  preventing stale entitlement data from persisting and re-appearing
  when the year is re-created
- deleteYear recalculates carry-over for year+1 when year N is deleted,
  using the new actual previous year as the source
- removeYear store action now calls loadStats() so the sidebar reflects
  the recalculated carry-over without requiring a page refresh
- Add prev-year button (+[<] 2026 [>]+) so users can add years going
  backwards after deleting a past year; add vacay.addPrevYear i18n key
  to all 13 supported languages

Closes #371
2026-04-03 19:51:22 +02:00
jubnl
e0105115f4 fix(immich): detect http→https redirect on test connection and update URL
When a user enters an http:// Immich URL that redirects to https://,
the test succeeded (GET follows redirects fine) but subsequent POST
requests (e.g. photo search) broke due to method downgrade on 301/302.

Now testConnection() checks resp.url against the input URL after a
successful fetch. If the only difference is http→https on the same
host and port, it returns a canonicalUrl so the frontend can update
the input field before the user saves — ensuring the correct URL is
stored.
2026-04-03 19:12:55 +02:00
jubnl
64d4a20403 feat: add MCP_RATE_LIMIT env variable to control MCP request rate
Document MCP_RATE_LIMIT in README, docker-compose, .env.example, Helm values and configmap.
2026-04-03 15:44:33 +02:00
jubnl
ce72f45d9a Merge remote-tracking branch 'origin/dev' into dev 2026-04-03 14:45:34 +02:00
jubnl
bf2eea18c3 Fix: add bypass for ssrf check to force dissallow internal ip 2026-04-03 14:45:12 +02:00
Maurice
501bab0f69 test: update cookie test to match sameSite lax change 2026-04-03 14:42:48 +02:00
Maurice
5dd80d5cb8 feat: Discord links, translation sync, iOS login fix, trip copy fix
- Add Discord button to admin GitHub panel and user menu
- Sync all 13 translation files to 1434 keys with native translations
- Fix duplicate keys in Polish translation (pl.ts)
- Fix iOS login race condition: sameSite strict→lax, loadUser sequence counter
- Fix trip copy route: add missing db, Trip, TRIP_SELECT imports
2026-04-03 14:39:44 +02:00
jubnl
bb54fda6dc fix: collab note attachments broken (#343)
- Fix attachment URLs to use /api/trips/:id/files/:id/download instead
  of /uploads/files/... which was unconditionally blocked with 401
- Use getAuthUrl() with ephemeral tokens for displaying attachments and
  opening them in a new tab (images, PDFs, documents)
- Replace htmlFor/id label pattern with ref.current.click() for the
  file picker button in NoteFormModal — fixes file not being added to
  pending list on first note creation
- Add integration tests COLLAB-028 to COLLAB-031 covering URL format,
  listing URLs, ephemeral token download, and unauthenticated 401
2026-04-03 14:11: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
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
jubnl
f32c103fe1 fix: deleted chats are not shown in share view anymore 2026-04-03 10:50:34 +02:00
jubnl
d4e16ebe49 fix: use APP_URL is defined as base url in mails 2026-04-03 03:44:45 +02:00
jubnl
40f7c00adb rename import 2026-04-02 19:47:50 +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
979322025d refactor: extract business logic from routes into reusable service modules 2026-04-02 17:14:53 +02:00
jubnl
a4d6348a79 fix: add raw.githubusercontent.com to CSP connect-src for Atlas map
The Atlas feature fetches country GeoJSON from GitHub raw content, which
was blocked by the Content Security Policy connect-src directive.

Closes #285
2026-04-02 14:10:14 +02:00
jubnl
32b63adc68 fix: add OIDC_SCOPE env var and document it across all config files
Fixes #306 — OIDC scopes were hardcoded to 'openid email profile',
causing OIDC_ADMIN_CLAIM-based role mapping to fail when the required
scope (e.g. 'groups') wasn't requested. The new OIDC_SCOPE variable
defaults to 'openid email profile groups' so group-based admin mapping
works out of the box. Variable is now documented in README, docker-compose,
.env.example, and the Helm chart values.
2026-04-02 07:46:58 +02:00
jubnl
50424fc574 feat: support ADMIN_EMAIL and ADMIN_PASSWORD env vars for initial admin setup
Allow the first-boot admin account to be configured via ADMIN_EMAIL and
ADMIN_PASSWORD environment variables. If both are set the account is created
with those credentials; otherwise the existing random-password fallback is
used. Documented across .env.example, docker-compose.yml, Helm chart
(values.yaml, secret.yaml, deployment.yaml), and CLAUDE.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 23:09:57 +02:00
jubnl
ae04071466 docs: document COOKIE_SECURE and OIDC_DISCOVERY_URL across all config files
Adds COOKIE_SECURE (fixes login loop on plain-HTTP setups) and the previously
undocumented OIDC_DISCOVERY_URL to .env.example, docker-compose.yml, README.md,
chart/values.yaml, chart/templates/configmap.yaml, and chart/README.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 21:44:02 +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
fabf5a7e26 fix: remove redundant db import alias in index.ts
db was already imported as addonDb; the extra db named import was
unnecessary. Updated the one stray db.prepare call at line 155 to use
addonDb consistently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 20:38:25 +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
e9ee2d4b0d fix: rebuild client assets with photoService and latest changes 2026-04-01 19:32:45 +02:00
Maurice
228cb05932 chore: bump version to 2.7.2 2026-04-01 19:13:32 +02:00
jubnl
0ebcff9504 Conflict resolution 2026-04-01 17:40:45 +02:00
Julien G.
edafe01387 Merge branch 'dev' into dev 2026-04-01 17:30:31 +02:00
Maurice
16277a3811 security: fix missing trip access checks on Immich routes (GHSA-pcr3-6647-jh72)
security: require auth for uploaded photos (GHSA-wxx3-84fc-mrx2)

GHSA-pcr3-6647-jh72 (HIGH):
- Add canAccessTrip check to all /trips/:tripId/photos and
  /trips/:tripId/album-links endpoints
- Prevents authenticated users from accessing other trips' photos

GHSA-wxx3-84fc-mrx2 (LOW):
- /uploads/photos now requires JWT auth token or valid share token
- Covers and avatars remain public (needed for login/share pages)
- Files were already blocked behind auth
2026-04-01 15:46:08 +02:00