feat: add Fail2ban security detection console
This commit is contained in:
@@ -7,6 +7,8 @@ import type { SessionRequest } from './session-validation.middleware';
|
||||
import { UsersService } from '../users/users.service';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { requestContext } from '../common/request-context';
|
||||
import { SecurityDetectionService } from '../security-detection/security-detection.service';
|
||||
|
||||
type CookieResponse = {
|
||||
cookie(name: string, value: string, options: Record<string, unknown>): void;
|
||||
@@ -16,7 +18,7 @@ type CookieResponse = {
|
||||
@ApiTags('auth')
|
||||
@Controller()
|
||||
export class AuthController {
|
||||
constructor(private readonly auth: AuthService, private readonly users: UsersService, private readonly sessions: SessionService, private readonly prisma: PrismaService) {}
|
||||
constructor(private readonly auth: AuthService, private readonly users: UsersService, private readonly sessions: SessionService, private readonly prisma: PrismaService, private readonly security: SecurityDetectionService) {}
|
||||
|
||||
@Get('admin/auth/captcha')
|
||||
adminCaptcha() {
|
||||
@@ -25,7 +27,14 @@ export class AuthController {
|
||||
|
||||
@Post('admin/auth/login')
|
||||
async adminLogin(@Body() body: LoginDto, @Req() request: SessionRequest, @Res({ passthrough: true }) response: CookieResponse) {
|
||||
return this.finishLogin(await this.auth.login(body, 'admin'), request, response);
|
||||
let result: Awaited<ReturnType<AuthService['login']>>;
|
||||
try {
|
||||
result = await this.auth.login(body, 'admin');
|
||||
} catch (error) {
|
||||
await this.recordLoginFailure('admin_login_failure', body.login, request).catch(() => undefined);
|
||||
throw error;
|
||||
}
|
||||
return this.finishLogin(result, request, response);
|
||||
}
|
||||
|
||||
@Get('client/auth/captcha')
|
||||
@@ -35,7 +44,14 @@ export class AuthController {
|
||||
|
||||
@Post('client/auth/login')
|
||||
async clientLogin(@Body() body: LoginDto, @Req() request: SessionRequest, @Res({ passthrough: true }) response: CookieResponse) {
|
||||
return this.finishLogin(await this.auth.login(body, 'client'), request, response);
|
||||
let result: Awaited<ReturnType<AuthService['login']>>;
|
||||
try {
|
||||
result = await this.auth.login(body, 'client');
|
||||
} catch (error) {
|
||||
await this.recordLoginFailure('client_login_failure', body.login, request).catch(() => undefined);
|
||||
throw error;
|
||||
}
|
||||
return this.finishLogin(result, request, response);
|
||||
}
|
||||
|
||||
@Get(['admin/auth/session', 'client/auth/session'])
|
||||
@@ -121,6 +137,17 @@ export class AuthController {
|
||||
return publicResult;
|
||||
}
|
||||
|
||||
private recordLoginFailure(ruleCode: 'admin_login_failure' | 'client_login_failure', account: string, request: SessionRequest) {
|
||||
return this.security.recordEvent({
|
||||
ruleCode,
|
||||
sourceIp: requestContext.getStore()?.ipAddress ?? '127.0.0.1',
|
||||
account,
|
||||
protocol: 'http',
|
||||
path: ruleCode === 'admin_login_failure' ? '/admin/auth/login' : '/client/auth/login',
|
||||
evidence: { userAgent: request.header('user-agent')?.slice(0, 256) },
|
||||
});
|
||||
}
|
||||
|
||||
private writeLog(request: SessionRequest, action: string, detail: Record<string, unknown>) {
|
||||
return this.prisma.operationLog.create({
|
||||
data: { userId: request.sessionUserId, action, resource: 'auth_session', userAgent: request.header('user-agent'), detail: JSON.parse(JSON.stringify(detail)) as Prisma.InputJsonValue },
|
||||
|
||||
@@ -5,9 +5,10 @@ import { AuthController } from './auth.controller';
|
||||
import { AuthService } from './auth.service';
|
||||
import { RecentAuthenticationGuard } from './recent-authentication.guard';
|
||||
import { SessionService } from './session.service';
|
||||
import { SecurityDetectionModule } from '../security-detection/security-detection.module';
|
||||
|
||||
@Module({
|
||||
imports: [UsersModule],
|
||||
imports: [UsersModule, SecurityDetectionModule],
|
||||
controllers: [AuthController],
|
||||
providers: [
|
||||
AuthService,
|
||||
|
||||
Reference in New Issue
Block a user