fix(audit): reorder routes to fix NestJS route collision

Move specific routes (logs/actions, logs/entity-types) before
parameterized route (logs/:id) to prevent NestJS from matching
'actions' and 'entity-types' as UUID parameters.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-25 08:40:56 -08:00
parent f95bc71254
commit ed5dc49b4a
1 changed files with 59 additions and 56 deletions

View File

@ -76,23 +76,59 @@ export class AuditController {
}
/**
* GET /audit/logs/:id
* Get single audit log detail
* GET /audit/logs/actions
* Get list of available action types
* NOTE: This must be defined BEFORE logs/:id to avoid route collision
*/
@Get('logs/:id')
async getAuditLogDetail(
@Get('logs/actions')
async getActionTypes(
@Headers('authorization') auth: string,
@Param('id') id: string,
): Promise<AuditLogDto> {
): Promise<{ actions: string[] }> {
await this.verifyAdmin(auth);
const log = await this.auditLogService.getLog(id);
// Common action types
return {
actions: [
'CREATE',
'UPDATE',
'DELETE',
'LOGIN',
'LOGOUT',
'PAYMENT',
'REFUND',
'EXPORT',
'IMPORT',
'DAILY_STATS_AGGREGATION',
'MONTHLY_REPORT_GENERATION',
],
};
}
if (!log) {
throw new NotFoundException('Audit log not found');
}
/**
* GET /audit/logs/entity-types
* Get list of entity types
* NOTE: This must be defined BEFORE logs/:id to avoid route collision
*/
@Get('logs/entity-types')
async getEntityTypes(
@Headers('authorization') auth: string,
): Promise<{ entityTypes: string[] }> {
await this.verifyAdmin(auth);
return log;
return {
entityTypes: [
'User',
'Conversation',
'Message',
'Order',
'Payment',
'Admin',
'KnowledgeArticle',
'Experience',
'DailyStatistics',
'MonthlyFinancialReport',
],
};
}
/**
@ -130,56 +166,23 @@ export class AuditController {
}
/**
* GET /audit/logs/actions
* Get list of available action types
* GET /audit/logs/:id
* Get single audit log detail
* NOTE: This must be defined LAST to avoid matching "actions", "entity-types", etc. as :id
*/
@Get('logs/actions')
async getActionTypes(
@Get('logs/:id')
async getAuditLogDetail(
@Headers('authorization') auth: string,
): Promise<{ actions: string[] }> {
@Param('id') id: string,
): Promise<AuditLogDto> {
await this.verifyAdmin(auth);
// Common action types
return {
actions: [
'CREATE',
'UPDATE',
'DELETE',
'LOGIN',
'LOGOUT',
'PAYMENT',
'REFUND',
'EXPORT',
'IMPORT',
'DAILY_STATS_AGGREGATION',
'MONTHLY_REPORT_GENERATION',
],
};
}
const log = await this.auditLogService.getLog(id);
/**
* GET /audit/logs/entity-types
* Get list of entity types
*/
@Get('logs/entity-types')
async getEntityTypes(
@Headers('authorization') auth: string,
): Promise<{ entityTypes: string[] }> {
await this.verifyAdmin(auth);
if (!log) {
throw new NotFoundException('Audit log not found');
}
return {
entityTypes: [
'User',
'Conversation',
'Message',
'Order',
'Payment',
'Admin',
'KnowledgeArticle',
'Experience',
'DailyStatistics',
'MonthlyFinancialReport',
],
};
return log;
}
}