لینک‌های مفید برای شرکت در مسابقه:

در زمان مسابقه می‌توانید سوال‌های خود را از قسمت "سوال بپرسید" مطرح کنید.

دو سری راهنمایی برای سوالات اضافه شده است.

RBAC


محدود کردن دسترسی بر اساس نقش (Role Based Access Control) نوعی مدیریت دسترسی است که در آن هر کاربر دارای یک نقش (Role) بوده و هر نقش دارای یک مجموعه دسترسی است. در این سؤال قرار است این سیستم را پیاده‌سازی کنید.

جزئیات پروژه🔗

پروژه‌ی اولیه را از این لینک دانلود کنید. ساختار فایل‌های این پروژه به‌صورت زیر است:

rbac_inital
├── app
│   ├── Console
│   │   └── Kernel.php
│   ├── Exceptions
│   │   └── Handler.php
│   ├── Http
│   │   ├── Controllers
│   │   │   ├── Controller.php
│   │   │   └── RBACController.php
│   │   ├── Middleware
│   │   │   ├── Authenticate.php
│   │   │   ├── EncryptCookies.php
│   │   │   ├── PreventRequestsDuringMaintenance.php
│   │   │   ├── RedirectIfAuthenticated.php
│   │   │   ├── TrimStrings.php
│   │   │   ├── TrustHosts.php
│   │   │   ├── TrustProxies.php
│   │   │   └── VerifyCsrfToken.php
│   │   └── Kernel.php
│   ├── Models
│   │   ├── Permission.php
│   │   ├── Role.php
│   │   └── User.php
│   └── Providers
│       ├── AppServiceProvider.php
│       ├── AuthServiceProvider.php
│       ├── BroadcastServiceProvider.php
│       ├── EventServiceProvider.php
│       └── RouteServiceProvider.php
├── bootstrap
│   ├── cache
│   │   ├── packages.php
│   │   └── services.php
│   └── app.php
├── config
│   ├── app.php
│   ├── auth.php
│   ├── broadcasting.php
│   ├── cache.php
│   ├── cors.php
│   ├── database.php
│   ├── filesystems.php
│   ├── hashing.php
│   ├── logging.php
│   ├── mail.php
│   ├── queue.php
│   ├── services.php
│   ├── session.php
│   └── view.php
├── database
│   ├── factories
│   │   └── UserFactory.php
│   ├── migrations
│   │   ├── 2014_10_12_000000_create_users_table.php
│   │   ├── 2014_10_12_100000_create_password_resets_table.php
│   │   ├── 2019_08_19_000000_create_failed_jobs_table.php
│   │   ├── 2020_09_27_092338_create_roles_table.php
│   │   ├── 2020_09_27_092758_create_permissions_table.php
│   │   ├── 2020_09_27_092917_create_permission_role_table.php
│   │   └── 2020_09_27_093704_create_role_user_table.php
│   ├── seeders
│   │   └── DatabaseSeeder.php
│   └── database.db
├── public
│   ├── favicon.ico
│   ├── index.php
│   ├── robots.txt
│   └── web.config
├── resources
│   ├── css
│   │   └── app.css
│   ├── js
│   │   ├── app.js
│   │   └── bootstrap.js
│   ├── lang
│   │   └── en
│   │       ├── auth.php
│   │       ├── pagination.php
│   │       ├── passwords.php
│   │       └── validation.php
│   └── views
│       └── welcome.blade.php
├── routes
│   ├── api.php
│   ├── channels.php
│   ├── console.php
│   └── web.php
├── storage
│   ├── app
│   │   └── public
│   ├── framework
│   │   ├── cache
│   │   │   └── data
│   │   ├── sessions
│   │   ├── testing
│   │   └── views
│   └── logs
│       └── laravel.log
├── tests
│   ├── Feature
│   │   └── RBACSampleTest.php
│   ├── Unit
│   ├── CreatesApplication.php
│   └── TestCase.php
├── README.md
├── artisan
├── composer.json
├── composer.lock
├── package.json
├── phpunit.xml
├── server.php
└── webpack.mix.js
Plain text
راه‌اندازی پروژه

برای اجرای پروژه، باید php و composer را از قبل نصب کرده باشید.

  • ابتدا پروژه‌ی اولیه را دانلود و از حالت فشرده خارج کنید.
  • دستور composer install را در پوشه‌ی اصلی پروژه برای نصب نیازمندی‌ها اجرا کنید.

مدل‌ها🔗

مدل‌ها در پروژه اولیه داده شده است. هم‌چنین می‌توانید با اجرای دستور php artisan migrate مایگریشن‌ها را اجرا کرده و پایگاه داده را به طور کامل داشته باشید. در این پروژه از پایگاه داده‌ی SQLite استفاده شده است. در ادامه، لیست مدل‌ها و توضیحات آمده است:

  1. User: مدل کاربر که دارای فیلدهای name، email و password است؛ فیلدهای name و password را می‌توانید دلخواه مقدار دهید.

  2. Role: مدل نقش که دارای فیلد name است

  3. Permission: مدل دسترسی که دارای فیلد name است

علاوه بر این مدل‌ها، دو جدول permission_role و role_user نیز وجود دارند که جدول‌های رابطه هستند.

شما باید متدهای زیر را در کلاس RBACController پیاده‌سازی کنید:

  1. createRole($name): این متد با ورودی گرفتن نام نقش آن را اضافه می‌کند.

  2. addPermissionToRole($class, $function, $role): این متد با گرفتن نام کلاس، نام متد و نام نقش، اجازه دسترسی یک نقش به یک متد از یک کلاس را می‌دهد.

  3. addUser($email): این متد یک کاربر با ایمیل داده شده را ایجاد می‌کند.

  4. addRoleToUser($role, $email): این متد با با دریافت نام نقش و ایمیل کاربر، آن نقش را به کاربر مورد نظر می‌دهد. هر کاربر می‌تواند چند نقش داشته باشد.

برنامه‌ی شما به این صورت داوری می‌شود که کلاسی با ارث‌بری از کنترلر اصلی لاراول (App\Http\Controllers\Controller) به کد شما اضافه می‌شود. شما باید چهار متد create، update، store و edit را در کلاس Controller طوری پیاده‌سازی کنید که به‌ترتیب چهار دسترسی create، update، store و edit برای کلاسی که از Controller ارث‌بری کرده است را بررسی کند. در صورتی که برای کاربر لاگین‌شده دسترسی موردنظر وجود نداشته باشد، متد موجود در Controller باید عدد 403 را برگرداند (return 403;). در غیر این‌صورت، این متدها نباید مقداری را برگردانند. تضمین می‌شود که هنگام تست این متدها، کاربر در سایت لاگین کرده است (با استفاده از Auth::user() می‌توانید اطلاعات کاربر را دریافت کنید).

توجه: شما تنها مجاز به تغییر فایل‌های موجود در پوشه‌ی /app هستید.

آن‌چه باید آپلود کنید🔗

پس از اعمال تغییرات، کل پروژه به غیر از پوشه‌ی vendor را Zip کرده و آپلود کنید. نام فایل Zip اهمیتی ندارد.

قسمت آموزشی🔗

در این قسمت راهنمایی‌های سوال، به مرور اضافه می‌شود. مشکلات‌تان در راستای حل سوال را می‌توانید از بخش "سوال بپرسید" مطرح کنید.

راهنمایی ۱

برای پیاده‌سازی متد createRole، می‌توان از متد create در مدل Role استفاده کرد. متد addUser نیز مشابه این متد پیاده‌سازی می‌شود:

public function createRole($name)
{
    Role::create([
        'name' => $name
    ]);

    return response()->json();
}
PHP

برای پیاده‌سازی متد addRoleToUser، می‌توان ابتدا Role متناظر با نام ورودی و User متناظر با ایمیل ورودی را دریافت کرد و سپس Role را به User attach کرد:

public function addRoleToUser($role, $email)
{
    $role = Role::where('name', $role)->first();
    $user = User::where('email', $email)->first();
    $user->roles()->attach($role);

    return response()->json();
}
PHP

برای پیاده‌سازی متد addPermissionToRole، یک روش برای ذخیره‌سازی نام کلاس و نام متد در فیلد name دسترسی، جداسازی آن‌ها با استفاده از یک کاراکتر space است:

public function addPermissionToRole($class, $function, $role)
{
    $permission = Permission::firstOrCreate([
        'name' => $class . ' ' . $function
    ]);
    $role = Role::where('name', $role)->first();
    $role->permissions()->attach($permission);

    return response()->json();
}
PHP
راهنمایی ۲

برای پیاده‌سازی متد create در کلاس Controller، باید ابتدا Roleهای کاربر و سپس Permissionهای متناظر با Roleها را دریافت کرد. نام کلاسی که این متد را صدا می‌زند با استفاده از کلاس ReflectionClass یا get_called_class قابل دریافت است. در صورتی که دسترسی موردنظر وجود نداشته باشد، باید عدد 403 را برگرداند.

برای جلوگیری از مشکل N+1N+1، می‌توان از join استفاده کرد:

public function create()
{
    $className = str_replace(__NAMESPACE__ . '\\', '', get_called_class());
    $hasPermission = Auth::user()
        ->roles()
        ->join('permission_role', 'roles.id', '=', 'permission_role.role_id')
        ->join('permissions', 'permission_role.permission_id', '=', 'permissions.id')
        ->where('permissions.name', $className . ' create')
        ->exists();
    if (!$hasPermission) {
        return 403;
    }
}
PHP

سایر متدهای کلاس Controller نیز مشابه متد create پیاده‌سازی می‌شوند.

ارسال پاسخ برای این سؤال
در حال حاضر شما دسترسی ندارید.