Files
Calendar_Frontend/CLAUDE.md
T
Paddy 7ce42324da Sign in through the admin app instead of this one
The frontend half of the calendar auth cutover (step 4 of
docs/calendar-auth-migration.md in the API repo). This app now shares one
identity with the tickets, feedback and admin apps.

Every call carries the session cookie via withCredentials rather than
appending sessionId/sessionKey to the URL, so there is no credential left in
api.service.ts at all - that was DEFERRED_SECURITY.md item 1.

The login and registration forms are gone. Accounts exist only by invitation
from the admin app, so both were one redirect; sign-out ends the session for
all four apps and returns here, so doing it by accident costs one click.

401 and 403 are deliberately not collapsed. Only 401 goes to the login page:
redirecting on 403 produces a loop where signing in succeeds and lands
straight back on the refusal, and doing it for an unreachable API produces the
same loop with no way out. Both of those now render a message instead.

src/app/models/session.ts and the unrouted LoginComponent are dead but left in
place; removing files is a separate decision.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 22:23:45 +02:00

3.9 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Commands

npm start          # Dev server at http://localhost:4200/ (live reload)
npm run build      # Production build
npm run watch      # Build with watch mode (development config)
npm test           # Run unit tests (Jasmine/Karma in Chrome)

No linter is configured in this project.

Architecture

Angular 18 single-page app for managing calendar events for the "Nachklang" organization. Uses Angular Material for UI, RxJS for async data, and reactive forms. No NgRx — state lives in component local variables.

Environments (src/environments/): apiUrl and adminAppUrl.

  • Dev: http://localhost:3000 (expects backend running locally) / http://localhost:3002
  • Prod: https://api.nachklang.art / https://admin.nachklang.art

Authentication

This app has no login form and no accounts of its own. Since the auth cutover (docs/calendar-auth-migration.md in the API repo) it shares one identity with the tickets, feedback and admin apps: accounts live in the admin app, and the session is an httpOnly cookie on .nachklang.art that the API's host sets. Consequences that cannot be designed around:

  • withCredentials: true is mandatory on every call (api.service.ts sets it once). Without it the browser sends no cookie and the API answers 401.
  • This app can never read or verify the session. It calls GET /admin/me and believes the answer; the API's requireAppAccess('calendar') is the actual gate.
  • 401 and 403 mean different things and must not be collapsed. 401 means "nobody is signed in" and is the only one worth redirecting to the login page - redirecting on 403 produces a loop where signing in succeeds and lands straight back on the refusal. See failure in admin.component.ts.
  • Sign-out ends the session for all four apps; there is only one.

The dev server must be reachable at a port the API trusts. ng serve defaults to 4200, which is in better-auth's dev localhostOrigins and in the admin app's NEXT_PUBLIC_ALLOWED_REDIRECT_ORIGINS; another port fails sign-out and the return redirect, not the sign-in.

The public calendar stays anonymous. GET /calendar/events/public/json needs no session at all, because nachklang.art reads it to show the next upcoming event.

Routing (app.routing.ts):

  • /LandingpageComponent
  • /adminAdminComponent (main calendar management page)
  • **NotfoundComponent

Service layer (src/app/services/):

  • api.service.ts — all HTTP calls to the backend REST API; carries the session cookie via withCredentials, holds no credential itself
  • admin-auth.service.ts — where signing in happens: the admin app's login URL (with a ?redirect= back here) and sign-out
  • utils.service.ts — caches the signed-in user's display name for unsaved draft rows. Cosmetic only; the server takes the author from the session

Data models (src/app/models/): Event, User, Session

Admin page (src/app/pages/admin/) is the core of the app. It owns events state and passes it down to EventsTableComponent via @Input(). Key features: multi-calendar support (public, members, choir, management, birthdays), event filtering (future/past/all), sorting, and an event-move dialog (EventMovePopupComponent via Angular Material Dialog).

Calendar-specific behavior: Birthday calendar auto-sets recurrence to YEARLY. Events have a status field (DRAFT / DELETED).

Session lifecycle: AdminComponent calls me() on init. 401 redirects to the admin app's login carrying this URL as the return target; 403 (or a signed-in account without the calendar permission) shows a refusal with Reload/Sign out; anything else shows "cannot be reached". None of those three redirect, on purpose.

Dead since the cutover, kept only because deleting files needs a decision: src/app/models/session.ts and the unrouted LoginComponent.