80 lines
2.8 KiB
TypeScript
80 lines
2.8 KiB
TypeScript
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;
|
|
}
|