منتجك يحاول يقرأ جدول أو يضيف فيه، ويرجع: permission denied for table orders. أو permission denied for sequence orders_id_seq، أو permission denied for schema public. يشبه خطأ RLS، لكنه شي ثاني، وحله مختلف. لو خلطت بينهم، ممكن «تصلّحه» بطريقة تفتح الجدول لكل الناس.
الفرق بينه وبين RLS
قاعدة البيانات تتأكد من شيئين قبل ما تسمح بأي طلب، بالترتيب:
- الصلاحية على الجدول (GRANT): هل هذا الدور، مثلًا زائر
anonأو مستخدم مسجّلauthenticated، مسموح له أصلًا يقرأ أو يضيف في هالجدول؟ إذا لا، يطلعpermission denied. - قواعد السطور (RLS): إذا مسموح له بالجدول، أي سطور بالضبط يشوف ويعدّل؟ إذا ما فيه قاعدة تسمح، يطلع خطأ RLS، أو ترجع نتيجة فاضية.
يعني permission denied مثل إن البوابة نفسها مقفلة عليك. وخطأ RLS مثل إنك دخلت المبنى لكن الغرفة مو لك. شرحنا الثاني في new row violates row-level security policy.
ليش يصير
- جدول جديد بدون صلاحيات: في Supabase، الجداول اللي تنعمل في
publicكانت تاخذ صلاحيات للأدوار الأساسية تلقائيًا. المشاريع الجديدة من 30 مايو 2026، وكل المشاريع من 30 أكتوبر 2026، ما تاخذها: أي جدول جديد يحتاجgrantصريح، وإلا يطلعpermission denied، ورسالة الخطأ نفسها فيها أمر الـgrantالمطلوب. الجداول القديمة تبقى على صلاحياتها، وهذا الحين أشهر سبب للخطأ في المنتجات اللي تنبني بالذكاء الاصطناعي. - الجدول انعمل بدور ثاني: حتى في المشاريع القديمة، الجدول اللي ينعمل بدور غير المعتاد ما ياخذ صلاحيات الأدوار الأساسية.
- schema جديد: أداة الذكاء الاصطناعي حطت الجداول في schema اسمه مثلًا
app، وما منحت الأدوار صلاحية استخدامه، وما أضافته للـ schemas اللي يفتحها Supabase للواجهة. - الـ sequence: الجدول عليه صلاحية الإضافة، لكن العدّاد اللي يولّد رقم السطر، وهو sequence، ما عليه صلاحية. فالإضافة تفشل بـ
permission denied for sequence. - سكربت سحب الصلاحيات: أحيانًا الذكاء الاصطناعي، وهو «يأمّن» قاعدتك، يكتب أوامر
revokeتسحب أكثر من اللازم. - سيرفرك بمستخدم محدود: إذا السيرفر يتصل بقاعدة البيانات بمستخدم أنشأته أنت، هذا المستخدم يحتاج صلاحياته الخاصة على كل جدول. وفي Postgres 15 وبعده، المستخدمين الجدد ما يقدرون ينشئون جداول في
publicتلقائيًا.
كيف تتأكد بنفسك
- شوف رسالة الخطأ: جدول؟ sequence؟ schema؟ كل واحد حله مختلف.
- شوف مين يطلب: من المتصفح، يعني الدور
anonأوauthenticated؟ ولا من سيرفرك بمستخدم قاعدة بيانات؟ - في SQL Editor في Supabase شغّل:
select grantee, privilege_type from information_schema.role_table_grants where table_name = 'orders';واستبدلordersباسم جدولك. النتيجة تقول مين عنده إيش على هالجدول.
الحل اللي لا تسويه
أشهر اقتراح تسمعه من أدوات الذكاء الاصطناعي: grant all on all tables in schema public to anon, authenticated. الخطأ يختفي، لكن الأمر يعطي الزوار صلاحية كاملة على كل جدول، ويخلّي RLS الحاجز الوحيد. وأي جدول RLS مو مفعّل عليه، أو قاعدته true، يصير مفتوح لأي أحد يقرأه ويعدّله ويحذفه، بما فيها جداول ما تبي الواجهة تلمسها أصلًا.
والاقتراح الثاني: استخدام مفتاح service_role في الواجهة لأنه «ما يطلع خطأ صلاحيات». هذا المفتاح يتجاوز كل شي، ومكانه السيرفر فقط.
الحل الصح
- امنح الصلاحية اللي يحتاجها الدور على الجدول اللي يحتاجه فقط. مثلًا
grant select, insert on table public.orders to authenticated;بدون حذف، وبدون الزوار، إذا ما يحتاجونها. - إذا الإضافة تحتاج الـ sequence، امنح
usageعليه لنفس الدور. - لـ schema جديد: صلاحية
usageعلى الـ schema، وأضفه في إعدادات الـ API في Supabase إذا الواجهة لازم توصله. - وتأكد إن RLS مفعّل على كل جدول تفتحه للواجهة، مع قواعد مكتوبة لكل عملية.
بعدها جرّب بحسابين وزائر بدون دخول: كل واحد يشوف اللي له فقط. فحوصات من هالنوع في 5 ثغرات في تسجيل الدخول.
تبي أحد يرتّبها معك؟
ترتيب الصلاحيات والقواعد لجدول أو جدولين يتم في مكالمة استشارية. إذا ما تدري إيش مفتوح وإيش مقفول في قاعدتك كلها، تدقيق جاهزية الإطلاق يمر على كل جدول ويعطيك تقرير مكتوب.