Changes
This commit is contained in:
@@ -18,31 +18,6 @@ function methodToAction(method: string): AuditAction {
|
||||
}
|
||||
}
|
||||
|
||||
function extractSection(path: string): string {
|
||||
const cleanPath = path.replace(/^\/api\//, '').replace(/^\//, '');
|
||||
const segments = cleanPath.split('/').filter(s => s.length > 0);
|
||||
|
||||
if (segments.length === 0) return 'general';
|
||||
|
||||
const sectionMapping: Record<string, string> = {
|
||||
'auth': 'authentication',
|
||||
'me': 'profile',
|
||||
'users': 'user-management',
|
||||
'roles': 'role-management',
|
||||
'meters': 'meters',
|
||||
'concentrators': 'concentrators',
|
||||
'gateways': 'gateways',
|
||||
'devices': 'devices',
|
||||
'projects': 'projects',
|
||||
'readings': 'readings',
|
||||
'bulk-upload': 'bulk-operations',
|
||||
'audit-logs': 'audit',
|
||||
'webhooks': 'webhooks',
|
||||
};
|
||||
|
||||
return sectionMapping[segments[0]] || segments[0];
|
||||
}
|
||||
|
||||
function extractTableName(path: string): string {
|
||||
const cleanPath = path.replace(/^\/api\//, '').replace(/^\//, '');
|
||||
const segments = cleanPath.split('/').filter(s => s.length > 0);
|
||||
@@ -52,48 +27,22 @@ function extractTableName(path: string): string {
|
||||
}
|
||||
|
||||
const baseTableMapping: Record<string, string> = {
|
||||
'auth': 'users',
|
||||
'me': 'users',
|
||||
'users': 'users',
|
||||
'roles': 'roles',
|
||||
'meters': 'meters',
|
||||
'concentrators': 'concentrators',
|
||||
'gateways': 'gateways',
|
||||
'devices': 'devices',
|
||||
'projects': 'projects',
|
||||
'readings': 'readings',
|
||||
'webhooks': 'webhooks',
|
||||
'bulk-upload': 'bulk_operations',
|
||||
'audit-logs': 'audit_logs',
|
||||
};
|
||||
|
||||
const operations = new Set([
|
||||
'password',
|
||||
'stats',
|
||||
'health',
|
||||
'template',
|
||||
'summary',
|
||||
'statistics',
|
||||
'my-activity',
|
||||
'record',
|
||||
'refresh',
|
||||
'logout',
|
||||
'uplink',
|
||||
'join',
|
||||
'ack',
|
||||
'dev-eui',
|
||||
]);
|
||||
|
||||
const nestedResourceMapping: Record<string, string> = {
|
||||
'meters/readings': 'readings',
|
||||
'concentrators/meters': 'meters',
|
||||
'gateways/devices': 'devices',
|
||||
'projects/meters': 'meters',
|
||||
'projects/concentrators': 'concentrators',
|
||||
};
|
||||
|
||||
const firstSegment = segments[0];
|
||||
const baseTable = baseTableMapping[firstSegment] || firstSegment;
|
||||
const baseTable = baseTableMapping[firstSegment];
|
||||
|
||||
if (!baseTable) {
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
if (segments.length === 1) {
|
||||
return baseTable;
|
||||
@@ -109,36 +58,9 @@ function extractTableName(path: string): string {
|
||||
return nestedResourceMapping[nestedKey];
|
||||
}
|
||||
|
||||
if (operations.has(thirdSegment)) {
|
||||
return baseTable;
|
||||
}
|
||||
|
||||
if (baseTableMapping[thirdSegment] || isPluralResourceName(thirdSegment)) {
|
||||
return baseTableMapping[thirdSegment] || thirdSegment;
|
||||
}
|
||||
|
||||
return baseTable;
|
||||
}
|
||||
|
||||
if (firstSegment === 'bulk-upload' && secondSegment) {
|
||||
return baseTableMapping[secondSegment] || secondSegment;
|
||||
}
|
||||
|
||||
if (firstSegment === 'audit-logs') {
|
||||
if (secondSegment === 'record' && segments.length >= 4) {
|
||||
return segments[3];
|
||||
}
|
||||
return 'audit_logs';
|
||||
}
|
||||
|
||||
if (firstSegment === 'auth') {
|
||||
return 'users';
|
||||
}
|
||||
|
||||
if (firstSegment === 'devices' && secondSegment === 'dev-eui') {
|
||||
return 'devices';
|
||||
}
|
||||
|
||||
if (segments.length === 2 && isUUID(secondSegment)) {
|
||||
return baseTable;
|
||||
}
|
||||
@@ -151,10 +73,6 @@ function isUUID(str: string): boolean {
|
||||
return uuidRegex.test(str) || /^\d+$/.test(str);
|
||||
}
|
||||
|
||||
function isPluralResourceName(str: string): boolean {
|
||||
return str.endsWith('s') || str.endsWith('ies') || str.includes('-');
|
||||
}
|
||||
|
||||
function extractRecordId(req: Request): string | undefined {
|
||||
if (req.params.id) {
|
||||
return req.params.id;
|
||||
@@ -166,23 +84,10 @@ function extractRecordId(req: Request): string | undefined {
|
||||
return match ? match[0] : undefined;
|
||||
}
|
||||
|
||||
const EXCLUDED_PATHS = [
|
||||
'/api/auth/refresh',
|
||||
'/api/audit-logs',
|
||||
'/webhooks',
|
||||
'/health',
|
||||
];
|
||||
|
||||
function shouldExclude(path: string): boolean {
|
||||
return EXCLUDED_PATHS.some(excluded => path.startsWith(excluded));
|
||||
}
|
||||
|
||||
function generateDescription(
|
||||
fullPath: string,
|
||||
action: AuditAction,
|
||||
tableName: string,
|
||||
recordId?: string,
|
||||
section?: string
|
||||
recordId?: string
|
||||
): string {
|
||||
const actionDescriptions: Record<AuditAction, string> = {
|
||||
'CREATE': 'Created',
|
||||
@@ -198,55 +103,17 @@ function generateDescription(
|
||||
};
|
||||
|
||||
const tableLabels: Record<string, string> = {
|
||||
'users': 'user',
|
||||
'roles': 'role',
|
||||
'meters': 'meter',
|
||||
'concentrators': 'concentrator',
|
||||
'gateways': 'gateway',
|
||||
'devices': 'device',
|
||||
'projects': 'project',
|
||||
'readings': 'reading',
|
||||
'bulk_operations': 'bulk operation',
|
||||
};
|
||||
|
||||
const actionLabel = actionDescriptions[action] || action;
|
||||
const tableLabel = tableLabels[tableName] || tableName;
|
||||
|
||||
if (fullPath === '/api/me' || fullPath === '/me' || fullPath.endsWith('/auth/me')) {
|
||||
return 'Viewed own profile';
|
||||
}
|
||||
|
||||
if (fullPath.includes('/users') && action === 'READ' && !recordId) {
|
||||
return 'Viewed users list';
|
||||
}
|
||||
|
||||
if (fullPath.includes('/meters') && action === 'READ' && !recordId) {
|
||||
return 'Viewed meters list';
|
||||
}
|
||||
|
||||
if (fullPath.includes('/concentrators') && action === 'READ' && !recordId) {
|
||||
return 'Viewed concentrators list';
|
||||
}
|
||||
|
||||
if (fullPath.includes('/projects') && action === 'READ' && !recordId) {
|
||||
return 'Viewed projects list';
|
||||
}
|
||||
|
||||
if (fullPath.includes('/readings') && action === 'READ' && !recordId) {
|
||||
return 'Viewed readings list';
|
||||
}
|
||||
|
||||
if (recordId) {
|
||||
if (tableName === 'unknown' && section) {
|
||||
return `${actionLabel} record in ${section} (ID: ${recordId.substring(0, 8)}...)`;
|
||||
}
|
||||
return `${actionLabel} ${tableLabel} (ID: ${recordId.substring(0, 8)}...)`;
|
||||
}
|
||||
|
||||
if (tableName === 'unknown' && section) {
|
||||
return `${actionLabel} in ${section} section`;
|
||||
}
|
||||
|
||||
return `${actionLabel} ${tableLabel}`;
|
||||
}
|
||||
|
||||
@@ -256,11 +123,6 @@ export function auditMiddleware(
|
||||
next: NextFunction
|
||||
): void {
|
||||
|
||||
if (shouldExclude(req.path)) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!req.path.startsWith('/api')) {
|
||||
next();
|
||||
return;
|
||||
@@ -286,24 +148,18 @@ export function auditMiddleware(
|
||||
return;
|
||||
}
|
||||
|
||||
const action = methodToAction(req.method);
|
||||
const fullPath = (req.originalUrl || req.url).split('?')[0];
|
||||
const section = extractSection(fullPath);
|
||||
const tableName = extractTableName(fullPath);
|
||||
|
||||
const allowedTables = ['concentrators', 'meters'];
|
||||
if (!allowedTables.includes(tableName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const action = methodToAction(req.method);
|
||||
const recordId = extractRecordId(req);
|
||||
const success = res.statusCode >= 200 && res.statusCode < 400;
|
||||
|
||||
let description = generateDescription(fullPath, action, tableName, recordId, section);
|
||||
|
||||
if (fullPath.includes('/login')) {
|
||||
description = 'User logged in successfully';
|
||||
} else if (fullPath.includes('/logout')) {
|
||||
description = 'User logged out';
|
||||
} else if (fullPath.includes('/password')) {
|
||||
description = 'Password changed';
|
||||
} else if (fullPath.includes('/bulk-upload')) {
|
||||
description = `Bulk upload for ${tableName}`;
|
||||
}
|
||||
const description = generateDescription(action, tableName, recordId);
|
||||
|
||||
let newValues: unknown = undefined;
|
||||
let oldValues: unknown = undefined;
|
||||
|
||||
Reference in New Issue
Block a user