Add comprehensive audit trail tracking by integrating auditService throughout the application. Track user authentication (LOGIN, REGISTER), course lifecycle (CREATE, APPROVE_COURSE, REJECT_COURSE, ENROLL), content management (CREATE/DELETE Chapter/Lesson), file operations (UPLOAD_FILE, DELETE_FILE for videos and attachments), password management (CHANGE_PASSWORD, RESET_PASSWORD), user role updates (UPDATE
182 lines
6.4 KiB
TypeScript
182 lines
6.4 KiB
TypeScript
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`,
|
|
};
|
|
}
|
|
}
|