پرش به مطلب اصلی

مجوزها و دسترسی (Authorization)

Authorizer هسته‌ی کنترل دسترسی و مجوزها در پکیج access-hub است و به شما کمک می‌کند نقش‌ها، مجوزها و دسترسی کاربران را به‌صورت منسجم مدیریت کنید.
این کلاس معمولاً در کنار Authenticator استفاده می‌شود؛ جایی که Authenticator مسئول احراز هویت است و Authorizer مسئول این است که کاربر احراز هویت‌شده به چه چیزهایی دسترسی دارد.

Namespace
Dornica\AccessHub\Authorization

روش های استفاده

برای استفاده از کلاس Authorizer و متدهای آن، دو روش وجود دارد:

استفاده مستقیم از کلاس با use

ابتدا کلاس را ایمپورت کرده و سپس با استفاده از Scope Resolution Operator (::) مستقیماً به متدهای آن دسترسی پیدا می‌کنید:

use Dornica\AccessHub\Authorization\Facades\Authorizer;

Authorizer::getRoles(); // فراخوانی متد به صورت مستقیم از کلاس

استفاده از تابع کمکی authorizer

در زیرساخت یک helper function برای دسترسی به Authorizer تعریف شده است:

authorizer()->getRoles();
authorizer()->hasAccess('permission_name');
اطلاع

معمولا در مثال‌های این مستندات فرض می‌شود شما از طریق یکی از این روش‌ها به متدهای Authorizer دسترسی دارید. بنابراین می‌توانید بسته به نیاز خود، هریک از این رویکردها را انتخاب و استفاده کنید.


امکانات اصلی Authorizer

در جدول زیر مهم‌ترین امکانات ارائه‌شده توسط Authorizer را مشاهده می‌کنید:

شرحمتد / بخش
دریافت لیست نقش‌ها از کش مرکزیRoles
دریافت لیست مجوزها از کش مرکزیPermissions
دریافت دسته‌بندی‌های مجوزها از کش مرکزیPermission Categories
مدیریت نقش‌های کاربران (اختصاص و حذف نقش)Role Management
مدیریت مجوزهای هر نقش (اتصال/حذف Permission به/از Role)Role Permissions
مدیریت مجوزهای مستقیم کاربران برای یک نقش خاصUser Direct Permissions
دریافت لیست مجوزهای کاربر و گروه‌بندی آن‌ها بر اساس دسته‌بندیPermission Queries
بررسی مجوز کاربر (یا نقش مشخص)hasAccess
Directive برای بررسی مجوز کاربرcanAccess
بررسی فعال بودن سرویس Authorization از روی کانفیگisEnabled

لیست نقش‌ها (Roles)

Authorizer با استفاده از DynamicCacheStorageAccess لیست نقش‌ها را در کش نگه می‌دارد تا بازیابی آن سریع و کم‌هزینه باشد.

متدهای Magic مرتبط با نقش‌ها


Authorizer::getRoles(): Collection
Authorizer::forgetRoles(): bool
Authorizer::refreshRoles(): bool

توضیحات

  • getRoles لیست کامل نقش‌های سیستم را از کش یا منبع داده‌ی اصلی برمی‌گرداند.
  • forgetRoles داده‌ی کش‌شده‌ی نقش‌ها را حذف می‌کند.
  • refreshRoles داده‌ی نقش‌ها را از منبع اصلی دوباره می‌خواند و در کش به‌روزرسانی می‌کند.

مثال

use Dornica\AccessHub\Authorization\Facades\Authorizer;


// دریافت نقش‌ها
$roles = Authorizer::getRoles();

// رفرش کش نقش‌ها
Authorizer::refreshRoles();

لیست مجوزها (Permissions)

مشابه نقش‌ها، مجوزها نیز در کش نگه‌داری می‌شوند تا درخواست‌های مکرر برای بررسی دسترسی، سریع‌تر انجام شوند.

متدهای Magic مرتبط با مجوزها


Authorizer::getPermissions(): Collection
Authorizer::forgetPermissions(): bool
Authorizer::refreshPermissions(): bool

توضیحات

  • getPermissions لیست کامل مجوزهای ثبت‌شده در سیستم را برمی‌گرداند.
  • forgetPermissions کش مربوط به مجوزها را خالی می‌کند.
  • refreshPermissions مجوزها را از منبع اصلی دوباره بارگذاری و در کش ذخیره می‌کند.

مثال

use Dornica\AccessHub\Authorization\Facades\Authorizer;


// دریافت لیست مجوزها برای نمایش در پنل مدیریت
$permissions = Authorizer::getPermissions();

دسته‌بندی‌های مجوزها (Permission Categories)

برای سازمان‌دهی بهتر مجوزها در UI، مجوزها معمولاً در دسته‌های مختلف گروه‌بندی می‌شوند.
Authorizer این دسته‌بندی‌ها را نیز در کش نگه می‌دارد.

متدهای Magic مرتبط با دسته‌بندی مجوزها


Authorizer::getPermissionCategories(): Collection
Authorizer::forgetPermissionCategories(): bool
Authorizer::refreshPermissionCategories(): bool

مثال

use Dornica\AccessHub\Authorization\Facades\Authorizer;


$categories = Authorizer::getPermissionCategories();

مدیریت نقش کاربران (Role Management)

این متدها برای اختصاص و حذف نقش از کاربران استفاده می‌شوند و به‌صورت خودکار وضعیت Super Admin و مجوزهای مرتبط را به‌روزرسانی می‌کنند.

متدهای کلیدی

assignRole(string|int $userId, string|int $roleId, ?array $attributes = []): object
removeRole(string|int $userId, string|int $roleId): bool

مثال: اختصاص نقش به کاربر

use Dornica\AccessHub\Authorization\Facades\Authorizer;


// اختصاص نقش با شناسه ۳ به کاربر با شناسه ۱۰
$userRole = Authorizer::assignRole(10, 3, [
'expired_at' => null,
]);

مثال: حذف نقش از کاربر

use Dornica\AccessHub\Authorization\Facades\Authorizer;


Authorizer::removeRole(10, 3);

مدیریت مجوزهای نقش (Role Permissions)

برای مدیریت این‌که هر Role چه Permissionهایی دارد، از متدهای زیر استفاده کنید. این متدها صرفاً نگاشت نقش ↔ مجوز را مدیریت می‌کنند و روی کاربران به‌طور مستقیم اعمال نمی‌شوند.

متدهای کلیدی

attachPermissionToRole(string|int $roleId, string|int|array $permissionIds): bool
detachPermissionFromRole(string|int $roleId, string|int|array $permissionIds): bool

مثال

use Dornica\AccessHub\Authorization\Facades\Authorizer;


// اضافه کردن چند دسترسی به یک نقش
Authorizer::attachPermissionToRole(3, [10, 11, 12]);

// حذف یک دسترسی از نقش
Authorizer::detachPermissionFromRole(3, 10);

مجوزهای مستقیم کاربران (User Direct Permissions)

این متدها برای زمانی است که می‌خواهید صرف‌نظر از Role، به یک کاربر (یا چند کاربر) مجوزهای خاصی را مستقیماً بدهید یا از او بگیرید. این مجوزها معمولاً در کنار مجوزهای Role استفاده می‌شوند.

متدهای کلیدی

attachPermissionToUser(
string|int|array $userIds,
string|int|array $permissionIds,
string|int $roleId
): void

detachPermissionFromUser(
string|int|array $userIds,
string|int|array $permissionIds,
string|int $roleId
): void

syncUserPermissions(
string|int|array $userIds,
string|int|array $permissionIds,
string|int $roleId
): void

copyPermissions(
string|int $fromUserId,
string|int $toUserId,
string|int $roleId = null,
?array $attributes = []
): void

مثال‌ها

use Dornica\AccessHub\Authorization\Facades\Authorizer;


// اضافه کردن چند دسترسی مستقیم به چند کاربر در یک نقش
Authorizer::attachPermissionToUser(
userIds: [10, 11],
permissionIds: [100, 101],
roleId: 3
);

// حذف چند دسترسی مستقیم از کاربران
Authorizer::detachPermissionFromUser(
userIds: [10, 11],
permissionIds: [100],
roleId: 3
);

// جایگزینی کامل لیست دسترسی های مستقیم کاربران برای یک نقش
Authorizer::syncUserPermissions(
userIds: [10, 11],
permissionIds: [200, 201, 202],
roleId: 3
);

// کپی‌کردن مجوزهای فعال یک کاربر به کاربر دیگر (برای نقش خاص)
Authorizer::copyPermissions(
fromUserId: 10,
toUserId: 20,
roleId: 3
);
نکته

بعد از هر تغییر در مجوزهای مستقیم، وضعیت has_special_permission روی مدل کاربر مطابق کد به‌روزرسانی می‌شود تا بتوانید وجود مجوزهای ویژه را به‌سادگی تشخیص دهید.


دریافت لیست مجوزهای کاربر (Permission Queries)

برای نمایش یا گزارش‌گیری از مجوزهای یک کاربر، می‌توانید از متدهای Query محور زیر استفاده کنید.

متدهای کلیدی

getUserPermissions(string|int $userId, string|int|null $roleId = null): array
getUserPermissionsByCategories(string|int $userId, string|int|null $roleId = null): array

خروجی نمونه

[
'userId' => 10,
'permissions' => [
['id' => 1, 'name' => 'مشاهده کاربران', 'is_special' => false],
// ...
],
]
خروجی دسته‌بندی‌شده
[
'userId' => 10,
'permissionsByCategory' => [
'مدیریت کاربران' => [
['id' => 1, 'name' => 'مشاهده کاربران', 'slug' => 'users.view', 'is_special' => false],
// ...
],
// ...
],
]

مثال

use Dornica\AccessHub\Authorization\Facades\Authorizer;


$flat = Authorizer::getUserPermissions(10);
$grouped = Authorizer::getUserPermissionsByCategories(10);

بررسی دسترسی با hasAccess

Signature
hasAccess(string $slug, object $role = null, mixed $user = null, $onlyOne = true): bool

پارامترها

نامنوعتوضیح
slugstring|arrayاسلاگ یا اسلاگ های مجوز هایی که می‌خواهید بررسی کنید.
roleobject|null(اختیاری) نقش خاصی که می‌خواهید دسترسی را برای آن بررسی کنید.
usermixed(اختیاری) کاربر خاصی که می‌خواهید دسترسی را برای او بررسی کنید.
onlyOnebool(اختیاری) با غیر فعال کردن این پارامتر باید کاربر به تمامی اسلاگ های وارد شده دسترسی داشته باشد.

توضیح

متد hasAccess بررسی می‌کند که آیا کاربر (یا نقش مشخص‌شده) مجوزی با اسلاگ داده‌شده دارد یا خیر.
در صورت ارسال پارامتر user یا role، این مقادیر به‌طور موقت روی authenticator ست می‌شوند و سپس لیست مجوزهای محاسبه‌شده برای همان کاربر/نقش بررسی خواهد شد.

مثال ساده


if (!hasAccess('admin.users.magagement.index')) {
abort(403, 'شما مجوز دسترسی را ندارید');
}

مثال با کاربر/نقش خاص

// بررسی دسترسی برای یک کاربر مشخص (بدون نیاز به لاگین بودن او در سشن فعلی)
if (hasAccess('admin.reports.index', $role, $user)) {
// کاربر/نقش به این گزارش دسترسی دارد
}

مثال با وارد کردن چندین اسلاگ

// بررسی تمامی دسترسی های وارد شده و اگر کاربر به یکی از دسترسی های وارد شده دسترسی داشته باشد مقدار شرط true می شود
if (hasAccess(['admin.reports.index' , 'admin.settings.index'])) {
// نمایش در صورت دسترسی به تنظیمات یا گزارش
}

// با دادن مقدار false به onlyOne باید کاربر به تمامی موارد دسترسی داشته باشد
if (hasAccess(slug: ['admin.reports.index' , 'admin.settings.index'], onlyOne: false)) {
// نمایش در صورت دسترسی کاربر به تنظیمات و گزارش به صورت همزمان
}

مثال استفاده از hasAccess در Authorizer

use Dornica\AccessHub\Authorization\Facades\Authorizer;

//نکته : اگر از روش استفاده کنید فقط می توانید دسترسی یک اسلاگ مشخص را بررسی کنید .
if (!Authorizer::hasAccess('admin.users.magagement.index')) {
//نمایش گزارش
}

نکته

این متد برای استفاده در Policyها، Middlewareها و لایه‌ی سرویس توصیه می‌شود تا منطق مجوزها در یک نقطه‌ی متمرکز قرار بگیرد.


بررسی دسترسی با canAccess

Signature
@canAccess(string $slug, object $role = null, mixed $user = null, $onlyOne = true): bool

پارامترها

نامنوعتوضیح
slugstring|arrayاسلاگ یا اسلاگ های مجوز هایی که می‌خواهید بررسی کنید.
roleobject|null(اختیاری) نقش خاصی که می‌خواهید دسترسی را برای آن بررسی کنید.
usermixed(اختیاری) کاربر خاصی که می‌خواهید دسترسی را برای او بررسی کنید.
onlyOnebool(اختیاری) با غیر فعال کردن این پارامتر باید کاربر به تمامی اسلاگ های وارد شده دسترسی داشته باشد.

توضیح

این directive دقیقا مانند hasAccess می باشد و عملکرد یکسانی با آن دارد .

مثال ساده


@canAccess('admin.basic.banks.store')
{!! FormValidator::formRequest(Modules\Bank\Http\Requests\StoreBankRequest::class, "#create-bank") !!}
@endcanAccess

مثال با کاربر/نقش خاص

// بررسی دسترسی برای یک کاربر مشخص (بدون نیاز به لاگین بودن او در سشن فعلی)
@canAccess('admin.basic.banks.store', $role, $user)
{!! FormValidator::formRequest(Modules\Bank\Http\Requests\StoreBankRequest::class, "#create-bank") !!}
@endcanAccess

مثال با وارد کردن چندین اسلاگ

// بررسی تمامی دسترسی های وارد شده و اگر کاربر به یکی از دسترسی های وارد شده دسترسی داشته باشد مقدار شرط صحیح می شود
@canAccess(['admin.basic.banks.store', 'admin.basic.banks.create'])
{!! FormValidator::formRequest(Modules\Bank\Http\Requests\StoreBankRequest::class, "#create-bank") !!}
@endcanAccess

// با دادن مقدار false به onlyOne باید کاربر به تمامی موارد دسترسی داشته باشد
@canAccess(slug: ['admin.basic.banks.store', 'admin.basic.banks.create'], onlyOne : false)
{!! FormValidator::formRequest(Modules\Bank\Http\Requests\StoreBankRequest::class, "#create-bank") !!}
@endcanAccess


بررسی فعال بودن سرویس Authorization

در بعضی محیط‌ها ممکن است سرویس Authorization به‌صورت کامل غیرفعال باشد (مثلاً در تست‌های ساده یا محیط‌های خاص).
برای بررسی این موضوع می‌توانید از متد زیر استفاده کنید:

authorizer()->isEnabled(): bool

این متد مقدار تنظیم authorization.enable را از فایل کانفیگ dornica-access-hub خوانده و برمی‌گرداند.


نکات مهم و ملاحظات فنی

  • هماهنگی با Authenticator: Authorizer::hasAccess برای تشخیص کاربر و نقش فعلی از authenticator استفاده می‌کند؛ اطمینان حاصل کنید که جریان احراز هویت (Login) به‌درستی پیاده‌سازی شده باشد.
  • استفاده در لایه‌ی Policy/Middleware: توصیه می‌شود منطق دسترسی به‌جای قرار گرفتن در Controllerها، در Policyها یا Middlewareها و با استفاده از hasAccess پیاده شود.
  • مدیریت کش: بعد از اعمال تغییرات روی نقش‌ها، مجوزها یا دسته‌بندی آن‌ها، متدهای refresh را صدا بزنید تا داده‌های کش‌شده با وضعیت جدید هم‌گام شوند.