2025-12-14 20:36:05 +00:00
|
|
|
import 'dart:convert';
|
|
|
|
|
import 'package:drift/drift.dart';
|
|
|
|
|
import '../database.dart';
|
|
|
|
|
import '../tables/audit.dart';
|
|
|
|
|
|
|
|
|
|
part 'audit_dao.g.dart';
|
|
|
|
|
|
|
|
|
|
@DriftAccessor(tables: [AuditLogs])
|
|
|
|
|
class AuditDao extends DatabaseAccessor<AppDatabase> with _$AuditDaoMixin {
|
|
|
|
|
AuditDao(super.db);
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-14 20:36:05 +00:00
|
|
|
/// Записать событие в audit log
|
2025-12-20 18:26:15 +00:00
|
|
|
///
|
2025-12-14 20:36:05 +00:00
|
|
|
/// ⚠️ ВАЖНО: Пока не используется в коде. Инфраструктура создана для будущего использования.
|
2025-12-20 18:26:15 +00:00
|
|
|
///
|
2025-12-14 20:36:05 +00:00
|
|
|
/// Параметры:
|
2025-12-14 21:10:06 +00:00
|
|
|
/// - table: имя таблицы (например, 'Users', 'Payments')
|
2025-12-14 20:36:05 +00:00
|
|
|
/// - recordId: ID записи, которая изменилась
|
|
|
|
|
/// - action: тип операции ('INSERT', 'UPDATE', 'DELETE', 'SOFT_DELETE', 'RESTORE')
|
|
|
|
|
/// - userId: ID пользователя, который сделал изменение (null для системных операций)
|
|
|
|
|
/// - oldData: данные до изменения (для UPDATE, DELETE)
|
|
|
|
|
/// - newData: данные после изменения (для INSERT, UPDATE)
|
|
|
|
|
/// - ipAddress: IP адрес пользователя
|
|
|
|
|
/// - userAgent: User-Agent браузера
|
|
|
|
|
Future<void> log({
|
2025-12-14 21:10:06 +00:00
|
|
|
required String table,
|
2025-12-14 20:36:05 +00:00
|
|
|
required String recordId,
|
|
|
|
|
required String action,
|
|
|
|
|
String? userId,
|
|
|
|
|
Map<String, dynamic>? oldData,
|
|
|
|
|
Map<String, dynamic>? newData,
|
|
|
|
|
String? ipAddress,
|
|
|
|
|
String? userAgent,
|
|
|
|
|
}) async {
|
|
|
|
|
await into(auditLogs).insert(
|
|
|
|
|
AuditLogsCompanion.insert(
|
2025-12-14 21:10:06 +00:00
|
|
|
table: table,
|
2025-12-14 20:36:05 +00:00
|
|
|
recordId: recordId,
|
|
|
|
|
action: action,
|
|
|
|
|
userId: Value(userId),
|
|
|
|
|
oldData: Value(oldData != null ? jsonEncode(oldData) : null),
|
|
|
|
|
newData: Value(newData != null ? jsonEncode(newData) : null),
|
|
|
|
|
ipAddress: Value(ipAddress),
|
|
|
|
|
userAgent: Value(userAgent),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-14 20:36:05 +00:00
|
|
|
/// Получить историю изменений для конкретной записи
|
2025-12-20 18:26:15 +00:00
|
|
|
///
|
2025-12-14 20:36:05 +00:00
|
|
|
/// Возвращает список записей audit log, отсортированных по дате создания (новые первыми)
|
|
|
|
|
Future<List<AuditLog>> getLogsByRecord({
|
2025-12-14 21:10:06 +00:00
|
|
|
required String table,
|
2025-12-14 20:36:05 +00:00
|
|
|
required String recordId,
|
|
|
|
|
int? limit,
|
|
|
|
|
}) {
|
|
|
|
|
final query = select(auditLogs)
|
2025-12-14 21:10:06 +00:00
|
|
|
..where((a) => a.table.equals(table) & a.recordId.equals(recordId))
|
2025-12-14 20:36:05 +00:00
|
|
|
..orderBy([(a) => OrderingTerm.desc(a.createdAt)]);
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-14 20:36:05 +00:00
|
|
|
if (limit != null) {
|
|
|
|
|
query.limit(limit);
|
|
|
|
|
}
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-14 20:36:05 +00:00
|
|
|
return query.get();
|
|
|
|
|
}
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-14 20:36:05 +00:00
|
|
|
/// Получить последние события (для мониторинга)
|
2025-12-20 18:26:15 +00:00
|
|
|
///
|
2025-12-14 20:36:05 +00:00
|
|
|
/// Возвращает последние N записей audit log, отсортированных по дате создания (новые первыми)
|
|
|
|
|
Future<List<AuditLog>> getRecentLogs({int limit = 100}) {
|
|
|
|
|
return (select(auditLogs)
|
2025-12-20 18:26:15 +00:00
|
|
|
..orderBy([(a) => OrderingTerm.desc(a.createdAt)])
|
|
|
|
|
..limit(limit))
|
|
|
|
|
.get();
|
2025-12-14 20:36:05 +00:00
|
|
|
}
|
|
|
|
|
}
|