Skip to content

سجل المراجعة

يوفر FORGE تسجيل نشاط تلقائي يُسجّل جميع الإجراءات المهمة في تطبيقك. يتم التقاط كل حدث إنشاء وتحديث وحذف وتسجيل دخول وتسجيل خروج مع السياق الكامل، مما يُمكّن من تدقيق الامتثال وتصحيح الأخطاء ومراقبة الأمان.

نظرة عامة

يلتقط نظام المراجعة سجلات منظمة لإجراءات المستخدمين مع لقطات الحالة قبل/بعد وبيانات الطلب الوصفية وتعريف المستخدم. سجلات المراجعة غير قابلة للتغيير -- بمجرد كتابتها، لا يمكن تعديلها أو حذفها من خلال التطبيق.

مخطط قاعدة البيانات

يخزن جدول audit_logs جميع سجلات النشاط:

العمودالنوعالوصف
idUUIDالمفتاح الأساسي
user_idUUID (nullable)معرّف المستخدم المُنفّذ (null للنظام أو مفتاح API)
user_emailVARCHAR(255)بريد المستخدم المُخزّن للعرض السريع
api_key_idUUID (nullable)مفتاح API المُستخدم للإجراء (إن وُجد)
actionVARCHAR(20)نوع الإجراء: created، updated، deleted، login، logout
resource_typeVARCHAR(100)اسم النموذج أو المورد (مثل user، content)
resource_idVARCHAR(100)المفتاح الأساسي للمورد المتأثر
old_valuesJSONBالحالة قبل التغيير (للتحديثات والحذف)
new_valuesJSONBالحالة بعد التغيير (للإنشاء والتحديثات)
ip_addressVARCHAR(45)عنوان IP للعميل (يدعم IPv4 و IPv6)
user_agentTEXTسلسلة user agent للعميل
urlVARCHAR(2000)رابط الطلب الذي أطلق الإجراء
created_atTIMESTAMPوقت حدوث الحدث

مثال على سجل

json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "user_id": "user-uuid-123",
  "user_email": "admin@example.com",
  "api_key_id": null,
  "action": "updated",
  "resource_type": "content",
  "resource_id": "content-uuid-456",
  "old_values": {
    "title": "العنوان القديم",
    "is_active": false
  },
  "new_values": {
    "title": "العنوان الجديد",
    "is_active": true
  },
  "ip_address": "192.168.1.100",
  "user_agent": "Mozilla/5.0...",
  "url": "/api/admin/contents/content-uuid-456",
  "created_at": "2025-01-15T10:30:00Z"
}

نصيحة

تحتوي أعمدة old_values و new_values فقط على الحقول التي تغيرت، وليس السجل بأكمله. هذا يُبقي التخزين فعالاً ويُسهّل رؤية ما تم تعديله بالضبط.

التسجيل التلقائي

تُولّد سجلات المراجعة تلقائياً عند عمليات CRUD. لا حاجة لإضافة أدوات قياس يدوياً في معالجاتك -- يعترض النظام عمليات الكتابة ويُسجّل البيانات ذات الصلة.

الإجراءات المُسجّلة

الإجراءالمُحفّزold_valuesnew_values
createdإدخال سجل جديد--كل الحقول
updatedتعديل سجل موجودالحقول المتغيرة (قبل)الحقول المتغيرة (بعد)
deletedإزالة سجلكل الحقول--
loginمصادقة مستخدم بنجاح----
logoutإنهاء جلسة مستخدم----

البريد الإلكتروني المُخزّن

يُخزّن حقل user_email مباشرة في سجل المراجعة حتى تبقى إدخالات السجل قابلة للقراءة حتى لو تم حذف أو تعديل حساب المستخدم لاحقاً. هذا يتجنب استعلامات JOIN عند عرض سجل المراجعة.

واجهة الإدارة

توفر لوحة الإدارة عارض سجل مراجعة قابل للتصفية:

  • تصفية بالمستخدم -- التصفية حسب بريد أو معرّف المستخدم المُنفّذ
  • تصفية بالإجراء -- عرض أنواع إجراءات محددة فقط (created، updated، deleted، login، logout)
  • تصفية بنوع المورد -- التصفية حسب اسم النموذج (مثل عرض تغييرات content فقط)
  • نطاق التاريخ -- تصفية الأحداث ضمن فترة زمنية محددة
  • عرض التفاصيل -- توسيع إدخال لرؤية فروقات القيم القديمة/الجديدة الكاملة

تحذير

سجلات المراجعة غير قابلة للتغيير. توفر واجهة الإدارة وصولاً للقراءة فقط. لا توجد عمليات تحديث أو حذف متاحة لسجلات المراجعة من خلال التطبيق.

سياسة الاحتفاظ

الاحتفاظ بسجلات المراجعة قابل للإعداد لإدارة نمو قاعدة البيانات:

yaml
# forge.yaml
audit:
  retention_days: 365    # الاحتفاظ بالسجلات لمدة سنة
  cleanup_schedule: daily # تشغيل مهمة التنظيف يومياً

عند تشغيل مهمة التنظيف، تُحذف السجلات الأقدم من فترة الاحتفاظ المُعدّة نهائياً من قاعدة البيانات.

تحذير

تأكد من أن سياسة الاحتفاظ تتوافق مع المتطلبات التنظيمية لمؤسستك. بعض القطاعات تتطلب الاحتفاظ بسجلات المراجعة لعدد أدنى من السنوات.

إسناد مفتاح API

عندما يُنفّذ إجراء عبر مفتاح API بدلاً من جلسة مستخدم، يُملأ حقل api_key_id بدلاً من user_id. هذا يتيح لك تتبع أي تكامل طرف ثالث قام بتغيير محدد.

json
{
  "user_id": null,
  "user_email": null,
  "api_key_id": "api-key-uuid-789",
  "action": "created",
  "resource_type": "content",
  "resource_id": "content-uuid-101"
}

الاستعلام عن سجلات المراجعة

الخلفية

rust
// Get all changes for a specific resource
let logs = audit_service.get_for_resource("content", content_id).await?;

// Get all actions by a specific user
let logs = audit_service.get_for_user(user_id).await?;

// Get recent login events
let logs = audit_service.get_by_action("login", page, per_page).await?;

نصيحة

للتطبيقات عالية الحركة، ضع في الاعتبار إنشاء فهرس على جدول audit_logs على (resource_type, resource_id) و (user_id, created_at) للاستعلام الفعال.

Released under the MIT License.