elearning/Backend/src/controllers/AuditController.ts

183 lines
6.4 KiB
TypeScript
Raw Normal View History

import { Get, Path, Query, Request, Response, Route, Security, SuccessResponse, Tags, Delete } from 'tsoa';
import { ValidationError } from '../middleware/errorHandler';
import { auditService } from '../services/audit.service';
import { AuditAction } from '@prisma/client';
import {
ListAuditLogsResponse,
AuditLogResponse,
AuditLogStats,
} from '../types/audit.types';
@Route('api/admin/audit-logs')
@Tags('Admin/AuditLogs')
export class AuditController {
/**
* audit logs
* Get all audit logs with filters and pagination
* @param userId - user ID
* @param action - action type
* @param entityType - entity type (Course, User, Lesson, etc.)
* @param entityId - entity ID
* @param startDate - (ISO format)
* @param endDate - (ISO format)
* @param page -
* @param limit -
*/
@Get('')
@Security('jwt', ['admin'])
@SuccessResponse('200', 'Audit logs retrieved successfully')
@Response('401', 'Unauthorized')
@Response('403', 'Forbidden - Admin only')
public async getAuditLogs(
@Request() request: any,
@Query() userId?: number,
@Query() action?: AuditAction,
@Query() entityType?: string,
@Query() entityId?: number,
@Query() startDate?: string,
@Query() endDate?: string,
@Query() page?: number,
@Query() limit?: number
): Promise<ListAuditLogsResponse> {
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) {
throw new ValidationError('No token provided');
}
return await auditService.getLogs({
userId,
action,
entityType,
entityId,
startDate: startDate ? new Date(startDate) : undefined,
endDate: endDate ? new Date(endDate) : undefined,
page: page || 1,
limit: limit || 50,
});
}
/**
* audit log by ID
* Get audit log detail by ID
* @param logId - audit log
*/
@Get('{logId}')
@Security('jwt', ['admin'])
@SuccessResponse('200', 'Audit log retrieved successfully')
@Response('401', 'Unauthorized')
@Response('403', 'Forbidden - Admin only')
@Response('404', 'Audit log not found')
public async getAuditLogById(
@Request() request: any,
@Path() logId: number
): Promise<AuditLogResponse> {
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) {
throw new ValidationError('No token provided');
}
const log = await auditService.getLogById(logId);
if (!log) {
throw new ValidationError('Audit log not found');
}
return log;
}
/**
* audit logs dashboard
* Get audit log statistics for admin dashboard
*/
@Get('stats/summary')
@Security('jwt', ['admin'])
@SuccessResponse('200', 'Audit stats retrieved successfully')
@Response('401', 'Unauthorized')
@Response('403', 'Forbidden - Admin only')
public async getAuditStats(@Request() request: any): Promise<AuditLogStats> {
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) {
throw new ValidationError('No token provided');
}
return await auditService.getStats();
}
/**
* history entity
* Get audit history for a specific entity
* @param entityType - entity (Course, User, Lesson, etc.)
* @param entityId - entity
*/
@Get('entity/{entityType}/{entityId}')
@Security('jwt', ['admin'])
@SuccessResponse('200', 'Entity history retrieved successfully')
@Response('401', 'Unauthorized')
@Response('403', 'Forbidden - Admin only')
public async getEntityHistory(
@Request() request: any,
@Path() entityType: string,
@Path() entityId: number
): Promise<AuditLogResponse[]> {
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) {
throw new ValidationError('No token provided');
}
return await auditService.getEntityHistory(entityType, entityId);
}
/**
* activity user
* Get activity logs for a specific user
* @param userId - user
* @param limit -
*/
@Get('user/{userId}/activity')
@Security('jwt', ['admin'])
@SuccessResponse('200', 'User activity retrieved successfully')
@Response('401', 'Unauthorized')
@Response('403', 'Forbidden - Admin only')
public async getUserActivity(
@Request() request: any,
@Path() userId: number,
@Query() limit?: number
): Promise<AuditLogResponse[]> {
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) {
throw new ValidationError('No token provided');
}
return await auditService.getUserActivity(userId, limit || 50);
}
/**
* audit logs (maintenance)
* Delete old audit logs for maintenance
* @param days - logs
*/
@Delete('cleanup')
@Security('jwt', ['admin'])
@SuccessResponse('200', 'Old logs deleted successfully')
@Response('401', 'Unauthorized')
@Response('403', 'Forbidden - Admin only')
public async deleteOldLogs(
@Request() request: any,
@Query() days: number = 90
): Promise<{ deleted: number; message: string }> {
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) {
throw new ValidationError('No token provided');
}
if (days < 30) {
throw new ValidationError('Cannot delete logs newer than 30 days');
}
const deleted = await auditService.deleteOldLogs(days);
return {
deleted,
message: `Deleted ${deleted} audit logs older than ${days} days`,
};
}
}