إنتقل إلى المحتوى الرئيسي

كتابة سياسة بيانات

الهدف​

أضف قاعدة لا تشحنها المنصة — «ألّا يتجاوز حدّ اعتمادك»، «ليس بعد إصدار الفاتورة» — وصفِّ بها صلاحية دور.

المتطلبات المسبقة​

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

ثلاثة أنواع، واختيار الصحيح منها​

السياسات المدمجة تجيب عن أي السجلات — سجلاتي، سجلات وحدتي، سجلات الجميع. وهي تغطي معظم ما يحتاجه الدور. فاكتب سياسة من عندك حين لا تكفي، وأول ما تقرّره نوعها:

أي السجلاتقاعدة على كل سجل
ما هيشرط يتحوّل إلى تصفية في قاعدة البياناتقاعدة تُفحص عند حفظ السجل
متى تستعملهاتتوقّف الإجابة على من يسأل — منطقته، فريقهتتوقّف الإجابة على ما يقوله السجل — حدّ اعتماد، حالة
ماذا يرى المستخدمالسجلات ببساطة ليست هناكرسالة تقول لماذا رُفض الحفظ
مثالRecord.par_region == CurrentUser.par_region«هذا المبلغ يتجاوز حد اعتمادك.»

سياسة أي السجلات هي الأداة الأفضل كلّما صلحت: فالسجلات التي تستبعدها لا تغادر الخادم أصلًا، فلا يكلّف تطبيقُها شيئًا ولا رسالةَ لأحد يقرؤها. غير أنها لا تصلح لكل شيء — إذ تتحوّل إلى استعلام، فلا تستطيع إلا مقارنة الحقول بالقيم.

وسياسة قاعدة على كل سجل هي التي تستطيع قول «المبلغ دون حدّ اعتمادي»، لأن ذلك ليس سؤالًا عن أيّ السجلات موجودة. تُنفَّذ على كل سجل يُحفظ، وتستطيع أن تشرح نفسها.

وإن كانت قاعدتك في الحقيقة «على الجميع تعبئة هذا»، فما تريده قاعدة عمل أو خطوة إضافة على الجدول — فتلك تسري على الجميع، وهذا معنى قاعدة جودة البيانات. أما السياسة فتسري على من يحمل صلاحية تحتها، وهذا معنى الصلاحية.

أما النوع الثالث، سجلات مَن (بوابة)، فليس لمن يسجّلون الدخول إلى المنصّة أصلًا — إنه يجيب عن سؤال «أي السجلات» نفسه لزائر على بوابة، ويُعلَن على جدول بدل أن يُمنح لدور. فإن كان هذا ما تريده فليست هذه صفحتك: انظر تحديد سجلات مَن يراها الزائر.

الخطوات​

  1. افتح الحلول، ثم افتح الحل الذي يعيش فيه تطبيقك، واختر سياسات البيانات من تنقّله. تسرد الشاشة السياسات التي يحملها هذا الحل؛ أما الحل الافتراضي (Main) فيسرد كل سياسات البيئة.

  2. اختر جديد.

  3. أعطها اسم عرض — وهو ما ستُعرف به في قائمة السياسات على شاشة الأدوار. ويُملأ الاسم المنطقي تلقائيًّا تحت بادئة ناشرك؛ يمكنك تغييره الآن لا لاحقًا، لأنه الاسم الذي يشير إليه كل منح.

  4. اختر النوع. فهو يقرّر ما تسأله بقيةُ النموذج، ولا يمكن تغييره بعد الحفظ. والخطوات التالية لـقاعدة على كل سجل؛ أما أي السجلات فانتقل إلى كتابة سياسة «أي السجلات».

  5. اختر أي السجلات. هذه هي السياسة المدمجة التي تصفّي القوائم، وليست اختيارية — انظر لماذا هناك إجابتان أدناه. وكل السجلات تعني «كل شيء، رهنًا بقاعدتي».

  6. أشِّر على العمليات التي تُفحص عندها القاعدة. والافتراضي هو الإنشاء والتعديل والحذف. لا تفعّل القراءة إلا عن قصد: فالقاعدة التي ترفض قراءةً تُخفي السجلات من القوائم لسبب لا يراه أحد.

  7. اكتب القاعدة. وهي بلغة BS Lang، اللغة نفسها التي تُكتب بها قواعد العمل، وتُنفَّذ على سجل واحد:

    if (getValue("par_total") > currentUser("par_approvallimit")) {
    deny("هذا المبلغ يتجاوز حد اعتمادك.");
    }

    استدعِ ‎deny("…")‎ للرفض. والقاعدة التي لا ترفض شيئًا تسمح بالعملية. والرسالة التي تكتبها هي ما يراه المستخدم — فقل ما الذي يجعل السجل مقبولًا، لا أنّ شيئًا كان خطأً.

  8. اختر حفظ. وإن لم تُحلَّل القاعدة، فشل الحفظ وأخبرك أين. وهذا مقصود: فالبديل أن تكتشف الأمر حين يُرفض أحدهم بقاعدة لا تستطيع العمل.

  9. افتح شاشة الأدوار في الحل، واضبط خليّة الصلاحية التي تريد تصفيتها على سياستك الجديدة. تظهر في القائمة نفسها التي فيها السياسات المدمجة.

كتابة سياسة «أي السجلات»​

تتحوّل سياسة أي السجلات إلى استعلام في قاعدة البيانات، فتُكتب على نحو مختلف وتسأل عن أشياء مختلفة.

  1. اختر الجدول. فبخلاف القاعدة، يُكتب هذا النوع على حقول جدول واحد، فلا بدّ أن يسمّيه — وتسميته هي ما يتيح للمنصة التحقّق من وجود تلك الحقول عند الحفظ. ولن تُعرض هذه السياسة إلا في صف ذلك الجدول على شاشة أدوار الحل.

  2. اكتب الشرط — شرطًا واحدًا لا برنامجًا:

    Record.par_region == CurrentUser.par_region && Record.par_status != "Closed"

    و‎Record.<field>‎ حقل في الجدول المختار. و‎CurrentUser.<name>‎ شيء عن الشخص الداخل — الأسماء نفسها المذكورة تحت ماذا تستطيع القاعدة أن تقرأ، مضافًا إليها أي حقل في جدول المستخدمين. وصِل الشروط بـ&& و||، وجمّعها بالأقواس.

  3. والمقارنة بـمجموعة تعني «واحد منها»: ‏Record.owning_unit == CurrentUser.UnitsAndBelow تختار السجلات المملوكة في وحدتك أو تحتها. ويمكنك المقارنة بقائمة تكتبها بنفسك: ‏Record.par_status == ["Draft", "Submitted"].

  4. اختر حفظ. وكل ما لا تستطيع المنصة تحويله إلى استعلام يُرفض الآن مع ذكر السبب.

ما لا يستطيع الشرط قوله​

هذا ضيّق عن قصد، لأن كل ما فيه لا بدّ أن يصير استعلامًا في قاعدة البيانات:

غير مسموحلماذابدلًا منه
>=، <=لا مُعامل لهما في الاستعلام> أو <
!(…)لا يمكن نفي الاستعلامقل ما تريد إبقاءه، مستعملًا !=
length(x) وأي دالّةكان لا بدّ أن تُنفَّذ، والتصفية لا تُنفَّذقارن الحقل مباشرة
Record.total * 2 > 100الحساب يمنع الاستعلام من استعمال الفهرسقارن بالرقم الذي تعنيه
Record.account.ownerتتبّع البحث ضمٌّ (join)، والضمّ الخفيّ بطيء على كل استعلامحقل في هذا الجدول
عدة شروط في عدة أسطرالسياسة شرط واحدصِلها بـ&&

وكل هذه تُرفض عند الحفظ، مع تسمية السطر. وهذا وحده سبب ضيق لغة الشرط: فشرطٌ تعجز المنصة عن فرضه بصمت سيُظهر سجلات ظنّ أحدهم أنه أخفاها.

ماذا تستطيع القاعدة أن تقرأ​

الاستدعاءما يعطيك
getValue("par_total")السجل كما سيكون بعد التغيير.
getPreValue("par_total")السجل كما هو مخزَّن الآن. فارغ عند الإنشاء.
currentUser("par_approvallimit")حقل في سجل المستخدم الخاص بالشخص الداخل.
isOwner()هل يملك هذا الشخص السجل.
hasRole("Manager")هل يحمل دورًا.
operation()Create أو Read أو Update أو Delete.
entityName()الاسم المنطقي للجدول.
deny("…")ارفض، مع السبب الذي سيقرؤه المستخدم.

يقرأ currentUser جدول المستخدمين في هذه البيئة، فللمقارنة بحدّ اعتماد تضيف ذلك الحقل إليه أولًا، تمامًا كما تفعل مع أي جدول آخر.

لماذا تحتاج سياسة القاعدة إلى نطاق أيضًا​

تحتاج القاعدة إلى سجل حُمِّل بالفعل. والقائمة هي بالضبط ما لديك قبل أن تحمّل أيّ سجل، فلا تستطيع القاعدة تصفيتها — إذ سيتعيّن على المنصة جلب كل صف لتقرّر أي الصفوف تجلب. أما سياسة أي السجلات فخاصيتها معاكسة، ولهذا بالضبط كانت نوعًا مستقلًّا لا قاعدةً أذكى.

لذلك تحمل سياسة القاعدة الأمرين معًا: أي السجلات سياسة مدمجة تدفعها المنصة إلى قاعدة البيانات، والقاعدة تُفحص بعد ذلك على كل سجل يفتحه أحدهم أو يحفظه أو يحذفه فعلًا. اضبط «أي السجلات» على أضيق مدمجة صادقة، ودع القاعدة تتولّى الباقي.

تعطيل واحدة​

أزل التأشير عن سارية واحفظ. تبقى السياسة موجودة ويظل كل منح تحتها يعمل — وفق إجابة أي السجلات وحدها، دون فحص القاعدة. وهذا هو التصرّف الآمن بينما تستكشف سبب رفض قاعدةٍ لشيء؛ أما حذف السياسة فليس آمنًا، ولن تدعك المنصة تحذف واحدة ما زال دور يستخدمها.

ولا مفتاح كهذا لسياسة أي السجلات، وليس ذلك سهوًا: فهي نفسها الجواب عن أي السجلات، فتعطيلها لا يعني إلا إظهار كل شيء أو لا شيء، وليس أيٌّ منهما ما يقصده أحد بإيقافها مؤقتًا. غيّر شرطها، أو غيّر المنح.

السياسات تسافر مع الحل​

تنتمي السياسة إلى حل، كما ينتمي إليه الجدول أو النموذج، وتذهب معه حين تصدّره وتصل معه حين تستورده في بيئة أخرى.

وهذا هو سبب كتابتها أصلًا. فـ«فاتورة تتجاوز حدّ اعتمادي ليس اعتمادها من شأني» جزء من طريقة عمل التطبيق، لا إعداد يضبطه أحد لكل بيئة — فشحن التطبيق دونها يترك بيئتي الاختبار والإنتاج تسمحان بصمت بما رفضته بيئة التطوير، وهو أسوأ اتجاه ممكن لفشل قاعدة أمنية.

ويترتّب على ذلك ثلاثة أمور:

  • تُفحص القاعدة من جديد عند الاستيراد، تمامًا كما فُحصت حين كتبتها. فالحزمة التي تحمل سياسة لم تعد تُترجَم تُرفض عند الاستيراد، بدل أن يكتشفها أول من تمنعه خطأً.
  • السياسة التي تُشحن معطَّلة تصل معطَّلة. أزِل علامة سارية عن قاعدة هيّأتها قبل الإطلاق، فتصلها البيئة الهدف بالحالة نفسها؛ والاستيراد لا يفعّل قاعدة لم يطلبها أحد بعد.
  • إلغاء تثبيت الحل يزيل السياسة — ويزيل معها المنح التي أُعطيت تحتها، وهي المرة الوحيدة التي تذهب فيها دون سؤال. فالمنحة التي اختفت سياستها كانت ستبدأ برفض كل ما كانت تسمح به، دون أن يقول شيء على الشاشة لماذا.

أما من مُنح شيئًا تحت تلك السياسة فلا يسافر: ذلك يسمّي أشخاصك، ويبقى في البيئة التي قرّرته فيها.

حل المشكلات​

  • «قاعدة السياسة لا تُحلَّل.» — خطأ مطبعي في القاعدة. والرسالة تسمّي الموضع.
  • «… إحدى سياسات المنصة نفسها.» — استعملت اسمًا مدمجًا. سياساتك تحمل بادئة ناشرك.
  • «… ما زالت تصفّي صلاحيات يحملها N من الأدوار.» — غيّر تلك المنوح أولًا في شاشة أدوار الحل. فحذف السياسة الآن يرفضها جميعًا.
  • لا أحد يستطيع حفظ شيء على الجدول. — راجع المقارنة في القاعدة. فالقاعدة التي تقرأ حقلًا غير موجود تحصل على قيمة فارغة، و‎"" > 100‎ ليست المقارنة التي قصدتها. أزل التأشير عن سارية ريثما تستكشف الأمر.
  • يبدو أن القاعدة لا تعمل أبدًا. — راجع العمليات التي أشّرت عليها، وأنّ منح الدور يشير فعلًا إلى سياستك لا إلى مدمجة.
  • يُرفض مستخدم برسالة عن سياسة تعذّر تقييمها. — لم تستطع القاعدة العمل. وتُرفض العملية بدل السماح بها، لأن قاعدة لم تستطع العمل لم تقل إن السجل مقبول. أصلح القاعدة، أو أزل التأشير عن سارية.
  • «لا يمكن تحويل هذا الشرط إلى استعلام.» — شرط في سياسة «أي السجلات» يستعمل شيئًا خارج ما يستطيع الاستعلام قوله. والرسالة تسمّي السطر والبديل؛ والجدول أعلاه يعدّدها كلّها.
  • سياسة «أي السجلات» لا تُعرض في الصف الذي أريده. — هي مكتوبة على جدول واحد، فلا تُعرض إلا في صف ذلك الجدول، ولا تُعرض أبدًا في كل الجداول. اكتب سياسة منفصلة للجدول الآخر.
  • سياسة «أي السجلات» لا تُظهر لأحد شيئًا. — الشرط الذي ينتهي إلى لا شيء يختار لا شيء، وهو الاتجاه الآمن الذي تسلكه المنصة دائمًا. راجع أسماء الحقول، وإن قارنت بمجموعة مثل CurrentUser.Teams، فتأكّد أن الشخص في فريق فعلًا.

سيناريوهات ذات صلة​