import { Body, Controller, Get, Headers, HttpCode, Ip, Post, Query, Res } from '@nestjs/common'; import type { Response } from 'express'; import { AuthService } from './auth.service'; import { LoginDto } from './dto/login.dto'; import { CurrentAdmin, Public } from './guards'; import type { AuthenticatedAdmin } from './jwt.strategy'; /** * Legacy endpoints (henza_server routes/admin.php): * POST admin-login -> AdminController::login * GET users/show -> UserController::showData * * Exposed here under the clean /api/admin/auth prefix; the admin panel's mapping * layer translates the legacy paths onto these. */ @Controller('admin/auth') export class AuthController { constructor(private readonly authService: AuthService) {} @Public() @Post('login') @HttpCode(200) login(@Body() dto: LoginDto, @Ip() ip: string, @Headers('user-agent') userAgent?: string) { // The IP is forwarded to the identity service (when delegation is on) so its // per-IP rate limit applies to the real admin, not to this API server; both // are also recorded on the session row when session tracking is on. return this.authService.login(dto, ip, userAgent); } @Public() @Get('sso/start') startSso(@Query('redirect_uri') redirectUri: string | undefined, @Res({ passthrough: true }) res: Response) { const started = this.authService.beginBrowserSso(redirectUri); if (!started) return { enabled: false, authorize_url: null }; res.setHeader('Set-Cookie', started.cookie); return { enabled: true, authorize_url: started.authorizeUrl }; } @Public() @Post('sso/callback') @HttpCode(200) ssoCallback( @Body() body: { code?: string; state?: string }, @Headers('cookie') cookieHeader: string | undefined, @Ip() ip: string, @Headers('user-agent') userAgent: string | undefined, @Res({ passthrough: true }) res: Response, ) { res.setHeader('Set-Cookie', 'gb_admin_iam_sso=; HttpOnly; Path=/; Max-Age=0; SameSite=Lax'); return this.authService.completeBrowserSso( readCookie(cookieHeader, 'gb_admin_iam_sso'), body.code ?? '', body.state ?? '', ip, userAgent, ); } @Public() @Get('sso/logout-url') ssoLogoutUrl(@Query('return_url') returnUrl?: string) { return { logout_url: this.authService.centralLogoutUrl(returnUrl) }; } /** Legacy `users/show` — the router guard's permission refresh. */ @Get('me') me(@CurrentAdmin() admin: AuthenticatedAdmin) { return this.authService.showData(admin.id); } } function readCookie(header: string | undefined, name: string): string | null { if (!header) return null; for (const part of header.split(';')) { const [key, ...rest] = part.trim().split('='); if (key === name) return decodeURIComponent(rest.join('=')); } return null; }