نوشتن یک سیاست داده
هدف
قاعدهای بسازید که پلتفرم آن را عرضه نمیکند — «بیش از سقف تأیید شما نباشد»، «پس از صدور فاکتور نه» — و مجوز یک نقش را با آن محدود کنید.
پیشنیازها
- در مرکز کنترل مدیریت وارد شدهاید، محیطی برگزیده شده و راهحلی را که سیاست باید به آن تعلق داشته باشد باز کردهاید — صفحه همانجاست، چون سیاست در بستهٔ همان راهحل سفر میکند.
- نام منطقی فیلدهایی را که قاعدهتان میخواند میدانید. آنها در صفحهٔ فیلدهای جدولاند.
سه گونه، و برگزیدن گونهٔ درست
سیاستهای درونساخته به این پاسخ میدهند که کدام رکوردها — مالِ من، مالِ واحد من، مالِ همه. بیشترِ آنچه یک نقش نیاز دارد را پوشش میدهند. وقتی کفایت نکردند، سیاستی از خودتان بنویسید و نخستین چیزی که باید تصمیم بگیرید گونهٔ آن است:
| کدام رکوردها | قاعده روی هر رکورد | |
|---|---|---|
| چیست | شرطی که به فیلتری در پایگاه داده تبدیل میشود | قاعدهای که هنگام ذخیرهٔ رکورد بررسی میشود |
| کِی به کار میآید | پاسخ به پرسنده بستگی دارد — منطقهٔ او، تیم او | پاسخ به محتوای رکورد بستگی دارد — سقف تأیید، وضعیت |
| کاربر چه میبیند | رکوردها اصلاً آنجا نیستند | پیامی که میگوید چرا ذخیره رد شد |
| نمونه | Record.par_region == CurrentUser.par_region | «این مبلغ از سقف تأیید شما بیشتر است.» |
سیاست کدام رکوردها هر جا که بنشیند ابزار بهتری است: رکوردهایی که کنار میگذارد هرگز از سرور بیرون نمیروند، پس اعمالش هزینهای ندارد و پیامی هم نیست که کسی بخواند. اما همهکاره نیست — به یک کوئری تبدیل میشود، پس تنها میتواند فیلدها را با مقادیر بسنجد.
سیاست قاعده روی هر رکورد همان است که میتواند بگوید «مبلغ کمتر از سقف تأیید من باشد»، چون این پرسشی دربارهٔ کدام رکوردها نیست. روی هر رکوردی که ذخیره میشود اجرا میشود و میتواند خودش را توضیح دهد.
اگر قاعدهٔ شما در واقع «همه باید این را پر کنند» است، آنچه میخواهید یک قاعدهٔ کسبوکار یا یک گام افزونه روی جدول است — آنها برای همه اعمال میشوند، و معنای یک قاعدهٔ کیفیت داده همین است. سیاست برای هرکسی اعمال میشود که مجوزی زیر آن دارد، و معنای مجوز همین است.
گونهٔ سوم، رکوردهای چه کسی (درگاه)، اصلاً برای افراد واردشده به پلتفرم نیست — همان پرسشِ «کدام رکوردها» را برای بازدیدکنندهٔ یک درگاه پاسخ میدهد و روی یک جدول اعلام میشود، نه اینکه به نقشی اعطا شود. اگر دنبال همین هستید، این صفحه آن نیست: تعیین اینکه بازدیدکننده رکوردهای چه کسی را میبیند را ببینید.
گامها
-
راهحلها را باز کنید، راهحلی را که برنامهتان در آن است باز کنید و در ناوبری آن سیاستهای داده را بزنید. این صفحه سیاستهایی را فهرست میکند که همین راهحل حمل میکند؛ راهحل پیشفرض (Main) همهٔ سیاستهای محیط را فهرست میکند.
-
جدید را بزنید.
-
یک نام نمایشی بدهید — همان که در فهرست سیاستها در صفحهٔ نقشها دیده میشود. نام منطقی خودش زیر پیشوند ناشر شما پر میشود؛ اکنون میتوانید تغییرش دهید اما بعداً نه، چون همان نامی است که هر اعطایی به آن ارجاع میدهد.
-
گونه را برگزینید. این تعیین میکند بقیهٔ فرم چه میپرسد و بعداً تغییرپذیر نیست. گامهای زیر برای قاعده روی هر رکورد است؛ برای کدام رکوردها به بخش نوشتن سیاست کدام-رکوردها بروید.
-
کدام رکوردها را برگزینید. برای سیاست قاعدهای، این همان درونساختهای است که فهرستها را فیلتر میکند و اختیاری نیست — بخش چرا سیاست قاعدهای به دامنه هم نیاز دارد را ببینید. همهٔ رکوردها یعنی «همهچیز، مشروط به قاعدهٔ من».
-
عملیاتی را که قاعده روی آنها بررسی شود تیک بزنید. پیشفرض ساخت، ویرایش و حذف است. خواندن را جز بهعمد روشن نکنید: قاعدهای که خواندن را رد کند، رکوردها را به دلیلی که کسی نمیبیند از فهرستها ناپدید میکند.
-
قاعده را بنویسید. به BS Lang است، همان زبان قاعدهٔ کسبوکار، و روی یک رکورد اجرا میشود:
if (getValue("par_total") > currentUser("par_approvallimit")) {deny("این مبلغ از سقف تأیید شما بیشتر است.");}برای رد کردن
deny("…") را صدا بزنید. قاعدهای که چیزی را رد نکند، عملیات را اجازه میدهد. پیامی که مینویسید همان است که کاربر میبیند — پس بگویید چه چیزی رکورد را پذیرفتنی میکند، نه اینکه چیزی نادرست بود. -
ذخیره را بزنید. اگر قاعده تجزیه نشود، ذخیره ناکام میماند و میگوید کجا. این عمدی است: جایگزینش این است که وقتی کسی با قاعدهای که نمیتواند اجرا شود رد میشود، تازه بفهمید.
-
صفحهٔ نقشهای راهحل را باز کنید و خانهٔ مجوزی را که میخواهید محدود شود روی سیاست تازهتان بگذارید. در همان فهرستی که سیاستهای درونساخته هستند دیده میشود.
نوشتن سیاست کدام-رکوردها
سیاست کدام رکوردها به یک کوئری پایگاه داده تبدیل میشود، پس جور دیگری نوشته میشود و چیزهای دیگری میپرسد.
-
جدول را برگزینید. برخلاف قاعده، این گونه سیاست روی فیلدهای یک جدول نوشته میشود، پس باید یکی را نام ببرد — و همین نام بردن است که به پلتفرم اجازه میدهد هنگام ذخیره وجود آن فیلدها را بررسی کند. این سیاست تنها در سطر همان جدول در صفحهٔ نقشهای راهحل پیشنهاد میشود.
-
شرط را بنویسید — یک شرط، نه یک اسکریپت:
Record.par_region == CurrentUser.par_region && Record.par_status != "Closed"
Record.<field>فیلدی روی جدول برگزیده است. CurrentUser.<name>چیزی دربارهٔ شخص وارد شده است — همان نامهایی که در قاعده چه چیزهایی را میتواند بخواند آمده، بهعلاوهٔ هر فیلدی روی جدول کاربران. شرطها را با&&و||به هم بپیوندید و با پرانتز گروهبندی کنید. -
سنجیدن با یک مجموعه یعنی «یکی از اینها باشد»:
Record.owning_unit == CurrentUser.UnitsAndBelowرکوردهایی را برمیگزیند که مالکشان در واحد شما یا زیر آن است. با فهرستی که خودتان مینویسید هم میتوانید بسنجید: Record.par_status == ["Draft", "Submitted"]. -
ذخیره را بزنید. هرچه پلتفرم نتواند به کوئری تبدیل کند، همین حالا با ذکر دلیل رد میشود.
شرط چه چیزهایی را نمیتواند بگوید
این عمداً تنگ است، چون هر چیزی در آن باید به کوئری پایگاه داده تبدیل شود:
| مجاز نیست | چرا | بهجایش |
|---|---|---|
>=، <= | کوئری عملگری برایشان ندارد | > یا < |
!(…) | کوئری را نمیتوان نقض کرد | بگویید چه بماند، با != |
length(x) و هر تابعی | باید اجرا شود، و فیلتر اجرا نمیشود | فیلد را مستقیم بسنجید |
Record.total * 2 > 100 | حساب مانع استفادهٔ کوئری از ایندکس میشود | با عددی که منظورتان است بسنجید |
Record.account.owner | دنبال کردن لوکاپ یک جوین است، و جوین پنهان روی هر کوئری کُند است | فیلدی روی همین جدول |
| چند شرط در چند خط | سیاست یک شرط است | با && به هم بپیوندید |
همهٔ اینها هنگام ذخیره رد میشوند، با ذکر خط. دلیلِ تنگ بودنِ زبانِ شرط دقیقاً همین است: شرطی که پلتفرم بیسروصدا نتواند اعمالش کند، رکوردهایی را نشان میدهد که کسی گمان میکرد پنهانشان کرده است.
قاعده چه چیزهایی را میتواند بخواند
| فراخوانی | چه میدهد |
|---|---|
getValue("par_total") | رکورد آنگونه که پس از تغییر خواهد بود. |
getPreValue("par_total") | رکورد آنگونه که اکنون ذخیره شده. هنگام ساخت خالی است. |
currentUser("par_approvallimit") | فیلدی روی رکورد کاربرِ خودِ شخص وارد شده. |
isOwner() | اینکه این شخص مالک رکورد هست یا نه. |
hasRole("Manager") | اینکه نقشی را دارد یا نه. |
operation() | Create، Read، Update یا Delete. |
entityName() | نام منطقی جدول. |
deny("…") | رد کن، با دلیلی که کاربر میخواند. |
currentUser جدول کاربران این محیط را میخواند، پس برای مقایسه با یک سقف تأیید، نخست آن فیلد
را به آن جدول اضافه میکنید، درست مانند هر جدول دیگری.
چرا سیاست قاعدهای به دامنه هم نیاز دارد
یک قاعده به رکوردی نیاز دارد که پیشتر بارگذاری شده باشد. فهرست دقیقاً همان چیزی است که پیش از بارگذاری هر رکوردی دارید، پس قاعده نمیتواند فهرست را فیلتر کند — پلتفرم باید هر سطر را بیاورد تا تصمیم بگیرد کدام سطرها را بیاورد. سیاست کدام رکوردها ویژگی وارونهای دارد، و دقیقاً به همین دلیل گونهای جداگانه است نه قاعدهای زیرکتر.
پس سیاست قاعدهای هر دو را با خود دارد: کدام رکوردها یک درونساخته است که پلتفرم آن را به پایگاه داده میسپارد، و قاعده پس از آن روی هر رکوردی که کسی واقعاً باز، ذخیره یا حذف میکند بررسی میشود. «کدام رکوردها» را روی تنگترین درونساختهٔ درست بگذارید و بقیه را به قاعده بسپارید.
خاموش کردن یکی
تیک در اجرا را بردارید و ذخیره کنید. سیاست همچنان هست و هر اعطای زیر آن کار میکند — تنها با پاسخِ کدام رکوردها، بیآنکه قاعده بررسی شود. این کارِ ایمن است وقتی میخواهید بفهمید چرا قاعدهای چیزی را رد میکند؛ حذف سیاست ایمن نیست، و پلتفرم اجازه نمیدهد سیاستی را که نقشی هنوز از آن استفاده میکند حذف کنید.
سیاست کدام رکوردها چنین کلیدی ندارد، و این از قلم نیفتاده است: آن سیاست خودش پاسخِ «کدام رکوردها» است، پس خاموش کردنش تنها میتواند یعنی نشان دادن همهچیز یا هیچچیز، و هیچکدام آن چیزی نیست که کسی از «موقتاً متوقفش کن» مراد میکند. شرطش را عوض کنید، یا اعطا را.
سیاستها همراه راهحل سفر میکنند
یک سیاست به یک راهحل تعلق دارد، درست مثل یک جدول یا یک فرم، و هنگام برونبری با همان راهحل میرود و هنگام درونبری در جای دیگر مینشیند.
نوشتن یک سیاست دقیقاً برای همین است. «فاکتوری بیش از سقف تأیید من، تأییدش کار من نیست» بخشی از نحوهٔ کار برنامه است، نه تنظیمی که کسی برای هر محیط پیکربندی کند — پس فرستادن برنامه بدون آن، محیط آزمون و تولید را در حالتی میگذارد که خاموشوار همان چیزی را مجاز میکنند که محیط توسعه رد کرده بود، و این بدترین جهت ممکن برای شکست یک قاعدهٔ امنیتی است.
سه چیز از این نتیجه میشود:
- قاعده هنگام درونبری دوباره بررسی میشود، دقیقاً همانطور که هنگام نوشتنش بررسی شد. بستهای که سیاستی با کد دیگر کامپایلنشدنی حمل کند، در همان درونبری رد میشود، نه اینکه نخستین کسی که بهاشتباه محرومش میکند کشفش کند.
- سیاستی که خاموش فرستاده شود، خاموش میرسد. تیک در حال اجرا را از قاعدهای که پیش از راهاندازی آماده کردهاید بردارید و محیط مقصد آن را در همان حالت میگیرد؛ درونبری قاعدهای را که هنوز کسی نخواسته روشن نمیکند.
- حذف نصبِ راهحل، سیاست را برمیدارد — و اعطاهایی را که زیر آن انجام شده، که تنها موردی است که آنها بدون پرسش میروند. اعطایی که سیاستش رفته باشد وگرنه شروع میکرد به رد کردن هر چیزی که زمانی اجازه میداد، بیآنکه چیزی روی صفحه بگوید چرا.
اینکه چه کسی زیر آن سیاست چیزی دریافت کرده سفر نمیکند: آن نامِ افرادِ شماست و در همان محیطی میماند که در آن تصمیم گرفتهاید.
عیبیابی
- «قاعدهٔ سیاست تجزیه نمیشود.» — اشتباهی در قاعده. پیام جایش را میگوید.
- «… یکی از سیاستهای خود پلتفرم است.» — از نامی درونساخته استفاده کردهاید. سیاستهای خودتان پیشوند ناشر شما را دارند.
- «… هنوز مجوزهایی را که N نقش دارند فیلتر میکند.» — نخست آن اعطاها را در صفحهٔ نقشهای راهحل تغییر دهید. حذف سیاست اکنون همهٔ آنها را رد میکند.
- هیچکس نمیتواند چیزی روی جدول ذخیره کند. — مقایسهٔ قاعده را بررسی کنید. قاعدهای که فیلدی
ناموجود را میخواند مقداری خالی میگیرد، و
"" > 100 آن مقایسهای نیست که در نظر داشتید. تا وقتی بررسی میکنید تیک در اجرا را بردارید. - به نظر میرسد قاعده هرگز اجرا نمیشود. — عملیاتی را که تیک زدهاید بررسی کنید، و اینکه اعطای نقش واقعاً به سیاست شما اشاره میکند نه به یک درونساخته.
- کاربری با پیامی دربارهٔ سیاستی که ارزیابی نشد رد میشود. — قاعده اجرا نشده است. عملیات بهجای اجازه، رد میشود، چون قاعدهای که نتوانسته اجرا شود نگفته که رکورد پذیرفتنی است. قاعده را درست کنید، یا تیک در اجرا را بردارید.
- «این شرط را نمیتوان به کوئری تبدیل کرد.» — شرطی در سیاست کدام-رکوردها که چیزی بیرون از توانِ گفتنِ یک کوئری دارد. پیام خط و جایگزین را میگوید؛ جدو ل بالا همه را فهرست کرده است.
- سیاست کدام-رکوردهای من در سطری که میخواهم پیشنهاد نمیشود. — روی یک جدول نوشته شده، پس تنها در سطر همان جدول پیشنهاد میشود و هرگز در همهٔ جدولها. برای جدول دیگر سیاستی جدا بنویسید.
- سیاست کدام-رکوردها به هیچکس چیزی نشان نمیدهد. — شرطی که به هیچ میرسد هیچ برمیگزیند، و
این همان جهت ایمنی است که پلتفرم همیشه برمیگزیند. نام فیلدها را بررسی کنید و اگر با مجموعهای
مانند
CurrentUser.Teamsسنجیدهاید، اینکه آن شخص واقعاً در تیمی هست.