xpeditis2.0/apps/backend/src/domain/entities/audit-log.entity.ts
David-Henri ARNAUD c5c15eb1f9 feature phase 3
2025-10-13 17:54:32 +02:00

175 lines
3.7 KiB
TypeScript

/**
* AuditLog Entity
*
* Tracks all important actions in the system for security and compliance
*
* Business Rules:
* - Every sensitive action must be logged
* - Audit logs are immutable (cannot be edited or deleted)
* - Must capture user, action, resource, and timestamp
* - Support filtering and searching for compliance audits
*/
export enum AuditAction {
// Booking actions
BOOKING_CREATED = 'booking_created',
BOOKING_UPDATED = 'booking_updated',
BOOKING_CANCELLED = 'booking_cancelled',
BOOKING_STATUS_CHANGED = 'booking_status_changed',
// User actions
USER_LOGIN = 'user_login',
USER_LOGOUT = 'user_logout',
USER_CREATED = 'user_created',
USER_UPDATED = 'user_updated',
USER_DELETED = 'user_deleted',
USER_ROLE_CHANGED = 'user_role_changed',
// Organization actions
ORGANIZATION_CREATED = 'organization_created',
ORGANIZATION_UPDATED = 'organization_updated',
// Document actions
DOCUMENT_UPLOADED = 'document_uploaded',
DOCUMENT_DOWNLOADED = 'document_downloaded',
DOCUMENT_DELETED = 'document_deleted',
// Rate actions
RATE_SEARCHED = 'rate_searched',
// Export actions
DATA_EXPORTED = 'data_exported',
// Settings actions
SETTINGS_UPDATED = 'settings_updated',
}
export enum AuditStatus {
SUCCESS = 'success',
FAILURE = 'failure',
WARNING = 'warning',
}
export interface AuditLogProps {
id: string;
action: AuditAction;
status: AuditStatus;
userId: string;
userEmail: string;
organizationId: string;
resourceType?: string; // e.g., 'booking', 'user', 'document'
resourceId?: string;
resourceName?: string;
metadata?: Record<string, any>; // Additional context
ipAddress?: string;
userAgent?: string;
errorMessage?: string;
timestamp: Date;
}
export class AuditLog {
private readonly props: AuditLogProps;
private constructor(props: AuditLogProps) {
this.props = props;
}
/**
* Factory method to create a new audit log entry
*/
static create(props: Omit<AuditLogProps, 'id' | 'timestamp'> & { id: string }): AuditLog {
return new AuditLog({
...props,
timestamp: new Date(),
});
}
/**
* Factory method to reconstitute from persistence
*/
static fromPersistence(props: AuditLogProps): AuditLog {
return new AuditLog(props);
}
// Getters
get id(): string {
return this.props.id;
}
get action(): AuditAction {
return this.props.action;
}
get status(): AuditStatus {
return this.props.status;
}
get userId(): string {
return this.props.userId;
}
get userEmail(): string {
return this.props.userEmail;
}
get organizationId(): string {
return this.props.organizationId;
}
get resourceType(): string | undefined {
return this.props.resourceType;
}
get resourceId(): string | undefined {
return this.props.resourceId;
}
get resourceName(): string | undefined {
return this.props.resourceName;
}
get metadata(): Record<string, any> | undefined {
return this.props.metadata;
}
get ipAddress(): string | undefined {
return this.props.ipAddress;
}
get userAgent(): string | undefined {
return this.props.userAgent;
}
get errorMessage(): string | undefined {
return this.props.errorMessage;
}
get timestamp(): Date {
return this.props.timestamp;
}
/**
* Check if action was successful
*/
isSuccessful(): boolean {
return this.props.status === AuditStatus.SUCCESS;
}
/**
* Check if action failed
*/
isFailed(): boolean {
return this.props.status === AuditStatus.FAILURE;
}
/**
* Convert to plain object
*/
toObject(): AuditLogProps {
return {
...this.props,
metadata: this.props.metadata ? { ...this.props.metadata } : undefined,
};
}
}