مخطط قاعدة البيانات (ERD)
مخطط بصري لجداول النظام وعلاقاتها، مع توضيح عزل بيانات كل عميل عبر client_id
عزل بيانات Multi-Tenant عبر client_id
كل جدول (باستثناء clients) يحتوي على عمود client_id يشير إلى الجدول الجذر. تُفعَّل سياسة Row Level Security على كل جدول لتضمن أن كل استعلام يُرجع فقط الصفوف التي تنتمي إلى العميل الحالي، حتى لو حاول مستخدم قراءة بيانات مباشرة عبر API.
-- Example RLS policy applied to every tenant table ALTER TABLE public.tweets ENABLE ROW LEVEL SECURITY; CREATE POLICY "tenant_isolation_select" ON public.tweets FOR SELECT TO authenticated USING (client_id = public.current_client_id()); CREATE POLICY "tenant_isolation_write" ON public.tweets FOR ALL TO authenticated USING (client_id = public.current_client_id()) WITH CHECK (client_id = public.current_client_id());
مفتاح رئيسي (PK)
مفتاح خارجي (FK)
NNغير فارغ
UQفريد
client_idعمود العزل
مرّر المؤشر فوق جدول لإبراز الجداول المرتبطة
clients
العملاء (Tenants)
iduuidNN
nametextNN
logo_urltext
primary_colortext
plantextNN
expires_attimestamptz
statustextNN
created_attimestamptzNN
users
المستخدمون
iduuidNN
client_iduuidNN
emailtextNNUQ
full_nametext
roleapp_roleNN
last_logintimestamptz
statustextNN
RLS: client_id = auth.client_id()
settings
الإعدادات
iduuid
client_iduuidNNUQ
languagetext
currencytext
timezonetext
brand_nametext
RLS: client_id = auth.client_id()
tweets
التغريدات والمنشورات
iduuid
client_iduuidNN
author_iduuid
contenttextNN
scheduled_attimestamptz
statustextNN
RLS: client_id = auth.client_id()
attack_log
سجل الهجمات
iduuid
client_iduuidNN
attacker_handletextNN
typetextNN
severitytextNN
statustextNN
reported_byuuid
RLS: client_id = auth.client_id()
responses
بنك الردود
iduuid
client_iduuidNN
bodytextNN
categorytext
tonetext
usage_countint
RLS: client_id = auth.client_id()
reports
التقارير
iduuid
client_iduuidNN
period_startdateNN
period_enddateNN
kindtextNN
file_urltext
generated_byuuid
RLS: client_id = auth.client_id()
invoices
الفواتير
iduuid
client_iduuidNN
numbertextNNUQ
amountnumericNN
currencytextNN
statustextNN
due_atdate
RLS: client_id = auth.client_id()
activity_log
سجل النشاط
iduuid
client_iduuidNN
user_iduuid
actiontextNN
entitytextNN
entity_iduuid
created_attimestamptzNN
RLS: client_id = auth.client_id()
خريطة العلاقات
| الجدول الفرعي | العمود | يشير إلى | نوع العلاقة | عند الحذف |
|---|---|---|---|---|
| users | client_id | clients.id | Tenant Isolation | CASCADE |
| settings | client_id | clients.id | Tenant Isolation | CASCADE |
| tweets | client_id | clients.id | Tenant Isolation | CASCADE |
| tweets | author_id | users.id | N : 1 | SET NULL |
| attack_log | client_id | clients.id | Tenant Isolation | CASCADE |
| attack_log | reported_by | users.id | N : 1 | SET NULL |
| responses | client_id | clients.id | Tenant Isolation | CASCADE |
| reports | client_id | clients.id | Tenant Isolation | CASCADE |
| reports | generated_by | users.id | N : 1 | SET NULL |
| invoices | client_id | clients.id | Tenant Isolation | CASCADE |
| activity_log | client_id | clients.id | Tenant Isolation | CASCADE |
| activity_log | user_id | users.id | N : 1 | SET NULL |
ضمانات العزل
- كل جدول يفعّل RLS ولا يمكن قراءته بدون
client_idصحيح. - دالة
current_client_id()تُستخرج من JWT للمستخدم الحالي. - عند حذف عميل من
clientsتُحذف كل بياناته تلقائياً (ON DELETE CASCADE). - الأدوار محفوظة في جدول
user_rolesمنفصل لتفادي هجمات رفع الصلاحيات.
التدقيق والمراقبة
- كل عملية إنشاء/تعديل/حذف تُسجَّل في
activity_log. - يحتوي السجل على
user_idوclient_idوالزمن والإجراء. - لا يمكن للمستخدمين حذف سجلات التدقيق حتى لو كانوا مديرين.
- Super Admin فقط يمكنه رؤية سجلات جميع العملاء عبر عرض مخصص.