72 lines
2.2 KiB
TypeScript
72 lines
2.2 KiB
TypeScript
import { Injectable, Logger } from '@nestjs/common';
|
|
import { DatabaseService } from '../database/database.service';
|
|
|
|
/** Definierte Audit-Aktionen der Plattform. */
|
|
export const AUDIT_ACTIONS = {
|
|
LOGIN_SUCCESS: 'LOGIN_SUCCESS',
|
|
LOGIN_FAILED: 'LOGIN_FAILED',
|
|
LOGIN_LOCKED: 'LOGIN_FAILED_LOCKED',
|
|
LOGOUT: 'LOGOUT',
|
|
USER_CREATED: 'USER_CREATED',
|
|
USER_UPDATED: 'USER_UPDATED',
|
|
USER_ENABLED: 'USER_ENABLED',
|
|
USER_DISABLED: 'USER_DISABLED',
|
|
USER_DELETED: 'USER_DELETED',
|
|
USER_PASSWORD_RESET: 'USER_PASSWORD_RESET',
|
|
USER_PASSWORD_CHANGED: 'USER_PASSWORD_CHANGED',
|
|
MODULE_INSTALLED: 'MODULE_INSTALLED',
|
|
MODULE_UPDATED: 'MODULE_UPDATED',
|
|
MODULE_REMOVED: 'MODULE_REMOVED',
|
|
MODULE_STARTED: 'MODULE_STARTED',
|
|
MODULE_STOPPED: 'MODULE_STOPPED',
|
|
MODULE_RESTARTED: 'MODULE_RESTARTED',
|
|
MODULE_CONFIG_UPDATED: 'MODULE_CONFIG_UPDATED',
|
|
MODULE_ENABLED: 'MODULE_ENABLED',
|
|
MODULE_DISABLED: 'MODULE_DISABLED',
|
|
PERMISSION_GRANTED: 'PERMISSION_GRANTED',
|
|
PERMISSION_REVOKED: 'PERMISSION_REVOKED',
|
|
SETTINGS_CHANGED: 'SETTINGS_CHANGED',
|
|
} as const;
|
|
|
|
export type AuditAction = (typeof AUDIT_ACTIONS)[keyof typeof AUDIT_ACTIONS];
|
|
|
|
/**
|
|
* Zentrales Audit-Logging: Sicherheitsrelevante Ereignisse werden
|
|
* nachvollziehbar aufgezeichnet. Es werden niemals Passwörter,
|
|
* Tokens oder personenbezogene Daten geloggt.
|
|
*/
|
|
@Injectable()
|
|
export class AuditService {
|
|
private readonly logger = new Logger('Audit');
|
|
|
|
constructor(private readonly database: DatabaseService) {}
|
|
|
|
async record(input: {
|
|
userId: string | null;
|
|
username: string;
|
|
action: AuditAction;
|
|
details?: Record<string, unknown>;
|
|
ipAddress?: string | null;
|
|
}): Promise<void> {
|
|
try {
|
|
await this.database.query(
|
|
`INSERT INTO audit_logs (user_id, username, action, details, ip_address)
|
|
VALUES ($1, $2, $3, $4::jsonb, $5)`,
|
|
[
|
|
input.userId,
|
|
input.username,
|
|
input.action,
|
|
JSON.stringify(input.details ?? {}),
|
|
input.ipAddress ?? null,
|
|
],
|
|
);
|
|
} catch (error) {
|
|
// Audit-Fehler dürfen den eigentlichen Request niemals blockieren.
|
|
this.logger.error(
|
|
`Audit-Log fehlgeschlagen (${input.action})`,
|
|
error instanceof Error ? error.stack : String(error),
|
|
);
|
|
}
|
|
}
|
|
}
|