90 lines
2.5 KiB
TypeScript
90 lines
2.5 KiB
TypeScript
import {
|
|
Controller,
|
|
Get,
|
|
Post,
|
|
Param,
|
|
UseGuards,
|
|
Query,
|
|
BadRequestException,
|
|
} from "@nestjs/common";
|
|
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from "@nestjs/swagger";
|
|
import { AdminGuard } from "./guards/admin.guard";
|
|
import { AuditService, AuditAction } from "@bff/infra/audit/audit.service";
|
|
import { UsersService } from "@bff/modules/users/users.service";
|
|
|
|
@ApiTags("auth-admin")
|
|
@ApiBearerAuth()
|
|
@UseGuards(AdminGuard)
|
|
@Controller("auth/admin")
|
|
export class AuthAdminController {
|
|
constructor(
|
|
private auditService: AuditService,
|
|
private usersService: UsersService
|
|
) {}
|
|
|
|
@Get("audit-logs")
|
|
@ApiOperation({ summary: "Get audit logs (admin only)" })
|
|
@ApiResponse({ status: 200, description: "Audit logs retrieved" })
|
|
async getAuditLogs(
|
|
@Query("page") page: string = "1",
|
|
@Query("limit") limit: string = "50",
|
|
@Query("action") action?: AuditAction,
|
|
@Query("userId") userId?: string
|
|
) {
|
|
const pageNum = parseInt(page, 10);
|
|
const limitNum = parseInt(limit, 10);
|
|
if (Number.isNaN(pageNum) || Number.isNaN(limitNum) || pageNum < 1 || limitNum < 1) {
|
|
throw new BadRequestException("Invalid pagination parameters");
|
|
}
|
|
|
|
const { logs, total } = await this.auditService.getAuditLogs({
|
|
page: pageNum,
|
|
limit: limitNum,
|
|
action,
|
|
userId,
|
|
});
|
|
|
|
return {
|
|
logs,
|
|
pagination: {
|
|
page: pageNum,
|
|
limit: limitNum,
|
|
total,
|
|
totalPages: Math.ceil(total / limitNum),
|
|
},
|
|
};
|
|
}
|
|
|
|
@Post("unlock-account/:userId")
|
|
@ApiOperation({ summary: "Unlock user account (admin only)" })
|
|
@ApiResponse({ status: 200, description: "Account unlocked" })
|
|
async unlockAccount(@Param("userId") userId: string) {
|
|
const user = await this.usersService.findById(userId);
|
|
if (!user) {
|
|
throw new BadRequestException("User not found");
|
|
}
|
|
|
|
await this.usersService.update(userId, {
|
|
failedLoginAttempts: 0,
|
|
lockedUntil: null,
|
|
});
|
|
|
|
await this.auditService.log({
|
|
userId,
|
|
action: AuditAction.ACCOUNT_UNLOCKED,
|
|
resource: "auth",
|
|
details: { adminAction: true, email: user.email },
|
|
success: true,
|
|
});
|
|
|
|
return { message: "Account unlocked successfully" };
|
|
}
|
|
|
|
@Get("security-stats")
|
|
@ApiOperation({ summary: "Get security statistics (admin only)" })
|
|
@ApiResponse({ status: 200, description: "Security stats retrieved" })
|
|
async getSecurityStats() {
|
|
return this.auditService.getSecurityStats();
|
|
}
|
|
}
|