Both permission forms in the admin panel can now render from the backend registry instead of their own hardcoded lists. Resources come back as an array so display order is part of the contract, each carrying its Persian label, its actions, and the clinic_only flag that used to live in the frontend. contextPermissions() normalizes the no-row branch through the registry too, so a doctor whose permission row was never provisioned sees the same shape as one who has it. Two existing assertions compared the API response against DEFAULT_PERMISSIONS by identity. The values are unchanged; only key order moved to the registry's, so both now compare through PermissionCatalog::merge. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5.4 KiB
Permission Catalog API
Prefix:
/api/v1/permission-catalog
چرا این اندپوینت هست
فهرستِ منابعِ قابلمجوزدهی تا پیش از این شش جا تکرار شده بود — دو Entity، سه فایل UI و یک interface تایپاسکریپت — و از هم واگرا شده بودند. نتیجهاش این بود که صفحهٔ تازه بهجای منبعِ خودش، مجوزِ نزدیکترین صفحهٔ موجود را قرض میگرفت.
حالا App\Shared\Security\PermissionCatalog تنها جایی است که میگوید چه منابع و
اکشنهایی وجود دارند. این اندپوینت همان رجیستری را به پنل میدهد تا هر دو فرمِ
مجوز — منشی و پزشکِ عضو کلینیک — بهجای فهرستِ هاردکد از آن رندر شوند.
افزودن صفحهٔ تازه = یک ردیف در PermissionCatalog::RESOURCES. فرانت تغییری لازم ندارد.
رجیستری فقط ساختار میدهد. مقدارِ پیشفرضِ هر نقش سیاست است و در Entity خودش
میماند: DoctorSecretary::DEFAULT_PERMISSIONS و ClinicDoctorPermission::DEFAULT_PERMISSIONS.
GET /api/v1/permission-catalog
فهرستِ کاملِ منابع و اکشنها با برچسب فارسی.
Permission: IS_AUTHENTICATED_FULLY
پاسخ به کاربر بستگی ندارد و تا وقتی رجیستری عوض نشود ثابت است، پس کلاینت میتواند
بلندمدت cache کند (staleTime: Infinity). مقدارِ واقعیِ مجوزِ هر رابطه از
اندپوینتهای خودِ منشی/پزشک میآید، نه از اینجا.
resources آرایه است نه object، تا ترتیبِ نمایش بخشی از قرارداد باشد؛ ترتیبِ
کلیدهای JSON قرارداد نیست.
Response 200 (خروجی واقعی، بریدهشده)
{
"success": true,
"data": {
"version": 1,
"resources": [
{
"key": "appointments",
"label": "مدیریت نوبتها",
"clinic_only": false,
"actions": [
{ "key": "view", "label": "مشاهده نوبتها" },
{ "key": "create", "label": "ایجاد نوبت" },
{ "key": "cancel", "label": "لغو نوبت" },
{ "key": "update_status", "label": "تغییر وضعیت نوبت" }
]
},
{
"key": "clinic_doctors",
"label": "مدیریت پزشکان کلینیک",
"clinic_only": true,
"actions": [
{ "key": "view", "label": "مشاهده پزشکان" },
{ "key": "create", "label": "افزودن پزشک" },
{ "key": "update", "label": "ویرایش پزشک" },
{ "key": "delete", "label": "حذف پزشک" }
]
}
]
}
}
| فیلد | نوع | توضیح |
|---|---|---|
version |
int | نسخهٔ شِمای مجوزها. همان چیزی که در envelope ذخیره میشود |
resources[].key |
string | کلیدِ منبع — همان چیزی که در permission JSON مینشیند |
resources[].label |
string | برچسب فارسی برای نمایش |
resources[].clinic_only |
bool | فقط در محیطِ کلینیک معنا دارد؛ پزشکِ مستقل نباید ببیندش |
resources[].actions[].key |
string | view / create / update / delete / cancel / update_status |
resources[].actions[].label |
string | برچسب فارسیِ همان اکشن |
منابعِ فعلی (۱۷)
appointments · patients · treatment · payments · insurances · addresses ·
clinic_info · services · inventory · staff · tags · discounts · sms ·
appointment_settings · resources · clinic_doctors · subscription
اکشنها یکسان نیستند: subscription فقط view/create دارد، و
clinic_info / appointment_settings / treatment فقط view/update.
Errors
| Status | شرایط |
|---|---|
401 |
بدون توکن یا توکنِ نامعتبر |
سازگاری با دادهٔ موجود
getPermissions() روی هر دو Entity، JSONِ ذخیرهشده را روی پیشفرضِ نقش merge میکند:
- منبعی که در رجیستری هست و در JSONِ ردیف نیست (یعنی بعد از ساختِ آن ردیف اضافه شده)
پیشفرضِ نقش را میگیرد، نه
false. بدون این، هر منبع تازه برای همهٔ ردیفهای موجود خاموش میماند. - مقدارِ صریحِ ذخیرهشده هرگز بازنویسی نمیشود — حتی
false. - هیچ migration دادهٔ انبوهی لازم نیست؛ ستون
permissionاز نوعjsonاست و schema عوض نمیشود.
نوشتنها از PermissionCatalog::filterPatch() عبور میکنند: منبع یا اکشنِ خارج از
رجیستری بیصدا کنار گذاشته میشود (نه 422) — همان رفتاری که کلاینتهای فعلی روی
آن حساب کردهاند. بقیهٔ کلیدهای همان درخواست اعمال میشوند.
مصرفکنندهها: secretary.md · clinic.md