داستان خیلی ساده نقشها و دسترسیها
این صفحه عمداً فنی نوشته نشده. هدفش این است که مدیر محصول، فرانتاند و حتی کسی که تازه پروژه را دیده، دقیقاً بفهمد چه اتفاقی میافتد.
داستان از کجا شروع شد؟
ما در اتوماسیون، فقط یک «منشی» ثابت نمیخواستیم. چون در دنیای واقعی دفتر املاک، آدمها شغلهای مختلف دارند: منشی، CRM، پشتیبانی، مدیر داخلی و هر نقش دیگری که بعداً ممکن است اضافه شود.
پس سیستم را اینطور ساختیم: اول «نوع کاربر» را مشخص میکنیم، بعد اگر کاربر از نوع
staff بود، یک «نقش سازمانی» به او میدهیم، و آن نقش تعیین میکند چه بخشهایی
را ببیند یا تغییر بدهد.
ادمین همهچیز را میبیند.
کارمند/مشاور فقط چیزهایی را میبیند که نقشش اجازه داده.
مشاور مثل قبل با منطق ملکهای خودش کار میکند.
سه تکه اصلی سیستم
| اسم ساده | در سیستم چیست؟ | مثال |
|---|---|---|
| نوع کاربر | User.role |
admin، staff، agent |
| نقش سازمانی | StaffRole |
منشی، CRM، پشتیبانی |
| دسترسی | AccessPermission |
دیدن لیست ملک، مدیریت شهر، حذف ملک |
یعنی در عمل این اتفاق میافتد:
کاربر = staff
↓
نقش سازمانی = مثلاً "منشی"
↓
دسترسیهای این نقش = مثلاً:
- دیدن لیست ملک
- ثبت ملک
- دیدن مشاوران
- نداشتن دسترسی حذف ملک
یک مثال واقعی
فرض کنید «مریم» کارمند جدید دفتر است. شما در پنل مدیریت برایش نقش «منشی» را انتخاب میکنید. نقش منشی از قبل چند دسترسی دارد: دیدن لیست ملک، ثبت ملک، دیدن مشاوران و مثلاً دیدن شهرها.
حالا وقتی مریم وارد فرانت میشود، فرانت از بکاند میپرسد: «این کاربر کیست و چه اجازههایی دارد؟»
بکاند جواب میدهد:
{
"role": "staff",
"staff_role": {
"id": 1,
"code": "secretary",
"title": "منشی"
},
"permissions": [
"properties.list.view",
"properties.create",
"agents.view"
]
}
فرانت این را میخواند و تصمیم میگیرد: منوی «لیست املاک» را نشان بده، دکمه «ثبت ملک» را نشان بده، اما دکمه «حذف ملک» را نشان نده.
پس فرانت باید چه فکری بکند؟
فرانت نباید با خودش بگوید «اگر user منشی بود این دکمه را نشان بدهم». فرانت باید بگوید: «اگر این permission را داشت، این دکمه را نشان میدهم».
UI را بر اساس
permissions[] بسازید، نه فقط بر اساس اسم نقش.
روایت خیلی ساده استفاده در فرانت
- کاربر لاگین میکند.
- فرانت بلافاصله
GET /auth/me/را صدا میزند. - پاسخ شامل
role،staff_roleوpermissionsاست. - فرانت این اطلاعات را در state/context نگه میدارد.
- هر صفحه و هر دکمه قبل از نمایش، permission لازم خودش را چک میکند.
- اگر permission نبود، یا آیتم را مخفی میکند یا disabled نشان میدهد.
- اگر کاربر با زور URL رفت، بکاند باز هم چک میکند و در صورت نداشتن دسترسی،
403میدهد.
صفحه مدیریت نقشها در فرانت باید چطور باشد؟
دقیقاً همان چیزی که گفتی: کاملاً گرافیکی. یعنی مدیر سیستم نباید کد بنویسد یا با اسمهای سخت درگیر شود.
فرانت میتواند یک فرم خیلی ساده داشته باشد:
- نام نقش: مثلاً «منشی شیفت صبح»
- کد نقش: مثلاً
morning_secretary - لیست دستهبندیشده دسترسیها
- کنار هر دسترسی یک checkbox
- دکمه ذخیره
مثلاً در UI:
| بخش | دسترسیها |
|---|---|
| املاک |
مشاهده لیست
ثبت ملک حذف ملک |
| شهرها |
مشاهده شهرها
مدیریت شهرها |
البته این checkboxها در داک فقط برای تصویر ذهنی هستند. در فرانت واقعی باید
دادهها را از GET /auth/permissions/ بگیرید و group-by ماژول نمایش دهید.
فرانت برای ساخت نقش چه میکند؟
وقتی مدیر سیستم در UI چند checkbox را تیک زد، فرانت لیست permissionهای انتخابشده را جمع میکند و به بکاند میفرستد.
{
"code": "support",
"title": "پشتیبانی",
"description": "پاسخگویی تلفنی",
"permission_codes": [
"properties.list.view",
"properties.detail.view",
"properties.owners.view"
]
}
این درخواست به این endpoint میرود:
POST /auth/roles/
فرانت برای دادن نقش به کارمند چه میکند؟
در فرم ساخت یا ویرایش کارمند، یک select برای نقش سازمانی میگذاری.
گزینههای این select از GET /auth/roles/ میآید.
بعد موقع ذخیره کارمند:
{
"phonenumber": "09123334455",
"password": "Pass12345",
"first_name": "مریم",
"last_name": "کریمی",
"personnel_code": "S-12",
"organizational_role_id": 1
}
یعنی به زبان ساده: «این کارمند، نقش منشی را دارد».
سادهترین الگوی کدنویسی در فرانت
function can(user, permissionCode) {
if (user?.is_system_admin) return true;
return (user?.permissions || []).includes(permissionCode);
}
const me = await fetch('/auth/me/', {
headers: { Authorization: `Bearer ${accessToken}` },
}).then((r) => r.json());
if (can(me, 'properties.create')) {
// دکمه ثبت ملک را نشان بده
}
if (can(me, 'properties.cities.manage')) {
// منوی مدیریت شهرها را نشان بده
}
الان دقیقاً چه چیزهایی آماده شده؟
- مدل نقش سازمانی برای staff ساخته شده.
- مدل دسترسیهای ریزدانهای ساخته شده.
- دو نقش پیشفرض
secretaryوcrmساخته میشوند. - API برای لیست دسترسیها و ساخت/ویرایش نقشها آماده است.
/auth/me/حالا دسترسیهای موثر کاربر را برمیگرداند.- بخشهایی از املاک، staff و agents به این RBAC وصل شدهاند.
سفر مدیر سیستم در یک نگاه
- مدیر سیستم وارد پنل مدیریت فرانت میشود.
- یک نقش جدید میسازد: مثلاً «پشتیبانی».
- در صفحه نقشها، چند دسترسی را با checkbox انتخاب میکند.
- نقش را ذخیره میکند.
- وارد صفحه کارمندان یا مشاوران میشود.
- برای یک نفر، نقش «پشتیبانی» را انتخاب میکند.
- آن کاربر از این لحظه فقط همان بخشها را میبیند.
کاتالوگ فعلی دسترسیها
| کد | معنی ساده |
|---|---|
properties.list.view | دیدن لیست املاک |
properties.detail.view | دیدن جزئیات ملک |
properties.create | ثبت ملک |
properties.edit | ویرایش ملک |
properties.delete | حذف ملک |
properties.cities.view | دیدن شهرها |
properties.cities.manage | مدیریت شهرها |
properties.locations.view | دیدن مناطق |
properties.locations.manage | مدیریت مناطق |
properties.types.view | دیدن انواع ملک |
properties.types.manage | مدیریت انواع ملک |
properties.owners.view | دیدن مالکها |
properties.owners.manage | مدیریت مالکها |
agents.view | دیدن مشاوران |
agents.manage | مدیریت مشاوران |
staff.view | دیدن کارمندان |
staff.manage | مدیریت کارمندان |
roles.view | دیدن نقشها |
roles.manage | مدیریت نقشها |
crm.view | دیدن CRM |
crm.manage | مدیریت CRM |
APIهای مهم برای فرانت
| کار | آدرس | چه زمانی استفاده میشود؟ |
|---|---|---|
| تشخیص کاربر جاری | GET /auth/me/ | بعد از login |
| لیست همه دسترسیها | GET /auth/permissions/ | صفحه ساخت/ویرایش نقش |
| لیست نقشها | GET /auth/roles/ | صفحه کارمندان و صفحه نقشها |
| ساخت نقش | POST /auth/roles/ | وقتی مدیر نقش جدید میسازد |
| ویرایش نقش | PATCH /auth/roles/<id>/ | وقتی تیکها تغییر میکنند |
| ساخت کارمند با نقش | POST /staff/ | وقتی ادمین کارمند جدید میسازد |
| ساخت مشاور با نقش | POST /agents/ | وقتی ادمین مشاور جدید میسازد |
نقشهای پیشفرض موجود
| کد | عنوان | توضیح ساده |
|---|---|---|
secretary |
منشی | میتواند لیست ملک را ببیند، ملک ثبت کند، بعضی اطلاعات پایه را ببیند و مشاوران را ببیند. |
crm |
کارشناس CRM | برای بخش CRM آماده شده و فعلاً دسترسیهای مرتبط اولیه را دارد. |
اگر خواستی کاتالوگ و نقشهای پیشفرض را دوباره بسازی
python manage.py sync_rbac --roles
اگر بعداً ماژول جدید اضافه شد چه؟
مثلاً فردا ماژول «گزارشها» یا «مالی» اضافه شد. لازم نیست سیستم را از نو بنویسیم. فقط permissionهای جدید را تعریف میکنیم، در صفحه نقشها checkboxهای جدید ظاهر میشوند، و مدیر سیستم تصمیم میگیرد چه نقشی آنها را داشته باشد.
یعنی کل سیستم برای توسعه آینده طراحی شده، نه فقط برای منشی و CRM امروز.
اگر کاربر دسترسی نداشت چه میشود؟
- در فرانت بهتر است آیتم را نشان ندهید یا غیرفعال کنید.
- اگر کاربر با URL مستقیم یا درخواست دستی جلو برود، بکاند
403میدهد. - اگر توکن نداشته باشد،
401میگیرد.
جمعبندی یکخطی
در این سیستم، مدیر با چند checkbox نقش میسازد، نقش را به کارمند میدهد،
و فرانت هم فقط با نگاه کردن به permissions[] میفهمد چه چیزی را باید نشان بدهد.