From 25caff2a51e989d3d28e1142e3c281a2a96a6393 Mon Sep 17 00:00:00 2001 From: linus Date: Thu, 10 Sep 2026 08:46:18 +0200 Subject: [PATCH] feat(backend): GET /api/auth/me for role-aware clients Accepts any of the three token kinds and echoes back the identity behind it: {kind:"guest", guestId, kcId, gemeindeId} for a Konfi token, or {kind:"user", userId, email, memberships, isLeitungsteam} for an Authentik or local Teamer token. Lets the client pick the right screens without decoding the JWT itself. Co-Authored-By: Claude Sonnet 5 --- src/auth/auth.controller.ts | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 370d0d5..1a2e2dd 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -1,9 +1,12 @@ -import { Body, Controller, Post } from '@nestjs/common'; +import { Body, Controller, Get, Post, Req, UseGuards } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; import { GuestAuthService } from './guest-auth.service'; import { TeamAuthService } from './team-auth.service'; import { CreateGuestDto } from './dto/create-guest.dto'; import { TeamLoginDto } from './dto/team-login.dto'; import { RegisterTeamerDto } from './dto/register-teamer.dto'; +import { AuthenticatedRequest } from './authenticated-request'; +import { GuestJwtPayload } from './guest-auth.service'; @Controller('auth') export class AuthController { @@ -12,6 +15,34 @@ export class AuthController { private readonly teamAuth: TeamAuthService, ) {} + /// Returns the identity + scope behind whichever token was presented, so a + /// client can render a role-aware UI. `kind` is "guest" for a Konfi token, + /// "user" for an Authentik or local Teamer token. + @Get('me') + @UseGuards(AuthGuard(['authentik', 'team', 'guest'])) + me(@Req() req: AuthenticatedRequest & { user: unknown }) { + const user = req.user as + | AuthenticatedRequest['user'] + | GuestJwtPayload; + if (user && 'guestId' in user) { + return { + kind: 'guest', + guestId: user.guestId, + kcId: user.kcId, + gemeindeId: user.gemeindeId, + }; + } + const u = user as NonNullable; + return { + kind: 'user', + userId: u.userId, + email: u.email, + authentikSub: u.authentikSub, + memberships: u.memberships, + isLeitungsteam: u.memberships.some((m) => m.role === 'LEITUNGSTEAM'), + }; + } + /// Redeems a KC invite code and registers a new temporary guest/Konfi account. @Post('guest') createGuest(@Body() dto: CreateGuestDto) {