first commit v3 initialiazed a temporary repository for darmanet client

This commit is contained in:
2026-09-08 16:04:01 +03:30
commit 5c7fd95052
216 changed files with 30050 additions and 0 deletions

View File

@@ -0,0 +1,201 @@
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { AuditLogModel } from 'src/database/model/audit-log.model';
import { Socket } from 'socket.io';
export interface AuditLogData {
userId?: string;
action: string;
resource?: string;
resourceId?: string;
oldValues?: Record<string, any>;
newValues?: Record<string, any>;
changes?: Record<string, { from: any; to: any }>;
ipAddress?: string;
userAgent?: string;
method?: string;
endpoint?: string;
statusCode?: number;
metadata?: Record<string, any>;
}
@Injectable()
export class AuditLogService {
constructor(
@InjectModel(AuditLogModel.name)
private readonly auditLogModel: Model<AuditLogModel>,
) {}
/**
* Extract IP address and user agent from Socket.io client
*/
private extractClientInfo(client: Socket): { ipAddress?: string; userAgent?: string } {
const ipAddress =
(client.handshake.headers['x-forwarded-for'] as string)?.split(',')[0]?.trim() ||
(client.handshake.headers['x-real-ip'] as string) ||
client.handshake.address ||
client.conn?.remoteAddress ||
undefined;
const userAgent =
(client.handshake.headers['user-agent'] as string) || undefined;
return { ipAddress, userAgent };
}
/**
* Calculate changes between old and new values
*/
private calculateChanges(
oldValues?: Record<string, any>,
newValues?: Record<string, any>,
): Record<string, { from: any; to: any }> | undefined {
if (!oldValues || !newValues) {
return undefined;
}
const changes: Record<string, { from: any; to: any }> = {};
const allKeys = new Set([...Object.keys(oldValues), ...Object.keys(newValues)]);
for (const key of allKeys) {
const oldVal = oldValues[key];
const newVal = newValues[key];
// Only include if values actually changed
if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
changes[key] = { from: oldVal, to: newVal };
}
}
return Object.keys(changes).length > 0 ? changes : undefined;
}
/**
* Log an audit event
*/
async log(data: AuditLogData, client?: Socket): Promise<void> {
try {
// Extract client info if socket is provided
const clientInfo = client ? this.extractClientInfo(client) : {};
// Calculate changes if both old and new values are provided
const changes = data.changes || this.calculateChanges(data.oldValues, data.newValues);
const auditLog = new this.auditLogModel({
userId: data.userId ? (data.userId as any) : undefined,
action: data.action,
resource: data.resource,
resourceId: data.resourceId,
oldValues: data.oldValues,
newValues: data.newValues,
changes,
ipAddress: data.ipAddress || clientInfo.ipAddress,
userAgent: data.userAgent || clientInfo.userAgent,
method: data.method,
endpoint: data.endpoint,
statusCode: data.statusCode,
metadata: data.metadata,
createdAt: new Date(),
});
await auditLog.save();
} catch (error) {
// Don't throw errors - audit logging should not break the main flow
console.error('Failed to save audit log:', error);
}
}
/**
* Log a WebSocket event
*/
async logWebSocketEvent(
action: string,
client: Socket,
options: {
userId?: string;
resource?: string;
resourceId?: string;
oldValues?: Record<string, any>;
newValues?: Record<string, any>;
statusCode?: number;
metadata?: Record<string, any>;
} = {},
): Promise<void> {
const clientInfo = this.extractClientInfo(client);
await this.log(
{
action,
resource: options.resource,
resourceId: options.resourceId,
oldValues: options.oldValues,
newValues: options.newValues,
ipAddress: clientInfo.ipAddress,
userAgent: clientInfo.userAgent,
method: action, // For WebSocket, method is the event name
endpoint: options.resourceId ? `room:${options.resourceId}` : undefined,
statusCode: options.statusCode || 200,
metadata: options.metadata,
userId: options.userId,
},
client,
);
}
/**
* Log an HTTP request (for future use)
*/
async logHttpRequest(
action: string,
req: any,
options: {
userId?: string;
resource?: string;
resourceId?: string;
oldValues?: Record<string, any>;
newValues?: Record<string, any>;
statusCode?: number;
metadata?: Record<string, any>;
} = {},
): Promise<void> {
const ipAddress =
req.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
req.headers['x-real-ip'] ||
req.ip ||
req.connection?.remoteAddress ||
undefined;
const userAgent = req.headers['user-agent'] || undefined;
await this.log({
action,
resource: options.resource,
resourceId: options.resourceId,
oldValues: options.oldValues,
newValues: options.newValues,
ipAddress,
userAgent,
method: req.method,
endpoint: req.path || req.url,
statusCode: options.statusCode || 200,
metadata: options.metadata,
userId: options.userId,
});
}
}