Per the updated plan, Gemeinde Teamer are no longer Authentik-backed; they
are local accounts a Gemeinde Verantwortliche/r provisions per KC.
Schema:
- User.authentikSub now nullable; add passwordHash + kcId (cascade from Kc)
so one User model covers Authentik members and local Teamer.
- new TeamerInvite model: shareable group link (email null, maxUses null)
or personal invite (email pinned, single use), with expiry + revoke.
- sync log now also replicates User / Membership / TeamerInvite.
Auth:
- TeamAuthService: bcrypt password login (POST /auth/team-login) and invite
redemption (POST /auth/teamer/register) issuing a JWT signed with
TEAM_JWT_SECRET, payload typ:"team".
- TeamJwtStrategy (AuthGuard('team')) resolves it to the same
AuthenticatedUser shape as AuthentikStrategy.
- TokenVerificationService.verifyEither() also accepts team tokens (WS).
- files + chat read endpoints accept 'team' tokens; Teamer see non-Konfi
files and can use chat / start DMs.
Teamer admin (teamer/ module, under /gemeinde/:gemeindeId):
- POST/GET teamer, DELETE teamer/:userId
- POST/GET teamer-invites, DELETE teamer-invites/:inviteId
- LT may manage any Gemeinde; a Verantwortliche/r only their own
(checked in TeamerService, since RolesGuard only scopes by kcId).
Tests: TeamAuthService + TeamerService specs added (Prisma/Sync mocked),
npm test green at 32. Docs (plan + backend README) updated.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
40 lines
1.4 KiB
Bash
40 lines
1.4 KiB
Bash
# Postgres connection used by Prisma
|
|
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/kcapp?schema=public"
|
|
|
|
# Authentik OIDC issuer, e.g. https://auth.example.org/application/o/kc-app/
|
|
AUTHENTIK_ISSUER_URL="https://authentik.example.org/application/o/kc-app"
|
|
|
|
# Secret used to sign guest/Konfi session tokens (local accounts only)
|
|
GUEST_JWT_SECRET="change-me"
|
|
|
|
# Secret used to sign local Gemeinde Teamer session tokens (password login)
|
|
TEAM_JWT_SECRET="change-me-too"
|
|
|
|
PORT=3000
|
|
|
|
# File storage: defaults to Nextcloud via WebDAV; set STORAGE_PROVIDER=s3 to
|
|
# use an S3-compatible bucket instead (see S3_* vars below).
|
|
STORAGE_PROVIDER="webdav"
|
|
WEBDAV_URL="https://nextcloud.example.org/remote.php/dav/files/kc-app"
|
|
WEBDAV_USERNAME="kc-app"
|
|
WEBDAV_PASSWORD="change-me"
|
|
|
|
# Only used when STORAGE_PROVIDER=s3
|
|
S3_BUCKET="kc-app"
|
|
S3_REGION="auto"
|
|
S3_ENDPOINT=""
|
|
S3_FORCE_PATH_STYLE="false"
|
|
S3_ACCESS_KEY_ID=""
|
|
S3_SECRET_ACCESS_KEY=""
|
|
|
|
# Unique id for THIS server instance (local on-site vs. cloud); used to tag
|
|
# replication log entries and avoid echoing changes back to their origin.
|
|
SERVER_ID="change-me-uuid"
|
|
|
|
# Local/cloud sync: set on the LOCAL (on-site) server to periodically push/
|
|
# pull against the cloud instance's API base URL. Leave SYNC_ENABLED=false
|
|
# on the cloud server (it only needs to expose /sync/ingest + /sync/export).
|
|
SYNC_ENABLED="false"
|
|
SYNC_PEER_URL="https://kc-app-cloud.example.org/api"
|
|
SYNC_SHARED_SECRET="change-me"
|