175 lines
3.7 KiB
TypeScript
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,
|
|
};
|
|
}
|
|
}
|