المقدمة
مرحبا عزيزي خابروفشان.
أواصل سلسلة مقالتي حول ترخيص الموارد المتقدمة في Laravel. لفهم أفضل لما سيتم مناقشته في هذه المقالة - تحتاج إلى قراءة الجزء الأول .
بادئ ذي بدء ، سأكرر بإيجاز بيان المشكلة: هناك عدد كبير من النماذج. من الضروري تصميم نظام مرن وقابل للتوسيع بسهولة لتفويض إجراءات المستخدم حسب دوره.
في هذا الجزء ، سنتحدث عن تكوين سياسة الارتباط <=> بوابة. ويقترح أيضًا أحد الخيارات لكتابة حقوق المستخدم في قاعدة البيانات.
وبالطبع ، سأوضح على الفور أن المادة مصممة لممارسة المبرمجين ، وسيكون من الصعب على المطور المبتدئ فهمها.
الجزء 3. السياسات والبوابات
الجزء النظري
يمكن العثور على الكثير من المواد على الإنترنت حول الموضوع - "ماذا تختار السياسة أو البوابة ؟". لبعض الوقت ، وصلت أيضًا إلى خطأ مماثل أنك بحاجة إلى اختيار شيء ما. ولكن في النهاية توصلت إلى الاستنتاج - هذان رابطان من نفس السلسلة ، وهما الأكثر استخدامًا بالتزامن.
في Laravel ، هناك اتجاهان رئيسيان لتحديد هذه الحزمة - يدوي وتلقائي. لن أفكر يدويًا ، نظرًا لأن دعم هذا النوع من الحزم سيتطلب جهودًا مبرمجة بشكل غير متناسب أكثر من إعداد حزمة تلقائية.
— , () . (Gate) — . — , . , . , app. . app/Models.
Gate::guessPolicyNamesUsing('callback'). , boot() App\Providers\AuthServiceProvider( ).
Gate
(callback), guessPolicyNamesUsing() , . . : Policy . , , Laravel ( ). SuperAdmin , , — super-admin . — .
PHP 7.4 . 7.4 .
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
$this->defineSuperAdmin();
$this->defineAutoDiscover();
}
private function defineAutoDiscover()
{
Gate::guessPolicyNamesUsing(function ($class) {
return str_replace("\\Models\\", "\\Policies\\" , $class) . 'Policy';
});
}
private function defineSuperAdmin()
{
Gate::before(function($user) {
return $user->hasRole('super-admin') ? true : null;
});
}
}
Policy
, , . . :
php artisan make:policy PostPolicy --model=Models/Post
. . , DRY,- , . , . , getModelClass() . , ( ). . (import export — )
<?php
protected function resourceAbilityMap()
{
return [
'index' => 'viewAny',
'show' => 'view',
'create' => 'create',
'store' => 'create',
'edit' => 'update',
'update' => 'update',
'destroy' => 'delete',
'import' => 'import',
'export' => 'export',
];
}
— , . , . . Spatie. laravel-permission. , — , , . , , . — , $user->can() $user->hasRole(), Spatie\Permission\Traits\HasRoles
(Models\User)
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use Notifiable;
use HasRoles;
}
, (Admin User, ) — HasRoles, .
.
(ModelPolicy)
<?php
namespace App\Policies;
use App\Models\User;
use App\Models\Post;
use Illuminate\Auth\Access\HandlesAuthorization;
use Illuminate\Database\Eloquent\Model;
abstract class ModelPolicy
{
use HandlesAuthorization;
abstract protected function getModelClass(): string;
public function viewAny(User $user)
{
return $user->can('view-any-' . $this->getModelClass());
}
public function view(User $user, Post $model)
{
return $user->can('view-' . $this->getModelClass());
}
public function create(User $user)
{
return $user->can('create-' . $this->getModelClass());
}
public function update(User $user, Post $model)
{
return $user->can('update-' . $this->getModelClass());
}
public function delete(User $user, Post $model)
{
return $user->can('delete-' . $this->getModelClass());
}
}
$user->can('ability') . . ''-' ', — ( ). (SoftDelete). , .
. Post getResourceName() .
(PostPolicy)
<?php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
class PostPolicy extends ModelPolicy
{
protected function getModelClass(): string
{
return Post::class;
}
public function import(User $user)
{
return $user->can('import-' . $this->getModelClass());
}
public function export(User $user, Post $model)
{
return $user->can('export-' . $this->getModelClass());
}
}
, import() , . — . . , .
, , . .
4. (Seeding)
, . .
spatie/laravel-permission, . .
:
composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
(seeder)
php artisan make:seeder PermissionsSeeder
run() database/seeds/DatabaseSeeder.php. PermissionsSeeder .
(DatabaseSeeder)
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run()
{
$this->call(PermissionsSeeder::class);
}
}
, — PermissionsSeeder. database/data php . :
role => model => action
// (permissions_roles.php)
<?php
return [
'admin' => [
'App\\Models\\Post' => [
'view',
'view-any',
'create',
'update',
'delete',
'import',
'export',
],
],
'App\\Models\\Post' => [
'post' => [
'view',
'view-any',
],
],
];
. , , — .
(PermissionsSeeder)
<?php
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
class PermissionsSeeder extends Seeder
{
private $data = [];
public function run()
{
$this->loadData();
$this->seedRoles();
}
public function loadData(): void
{
$this->data = require_once database_path("data/permissions_roles.php");
}
private function seedRoles(): void
{
Role::create(['name' => 'super-admin', 'guard_name' => 'api']);
foreach ($this->data as $roleName => $perms) {
$role = Role::create(['name' => $roleName, 'guard_name' => 'api']);
$this->seedRolePermissions($role, $perms);
}
}
private function seedRolePermissions(Role $role, array $modelPermissions): void
{
foreach ($modelPermissions as $model => $perms) {
$buildedPerms = collect($perms)
->crossJoin($model)
->map(function ($item) {
$perm = implode('-', $item);
Permission::findOrCreate($perm, 'api');
return $perm;
})->toArray();
$role->givePermissionTo($buildedPerms);
}
}
}
, - . , , . , , .
, :
- run() .
- loadData() database/data $data
- seedRoles() . , $data, . 'super-admin' , , .. ( AuthServiceProvider).
- seedRolePermissions() , , «» , (permission). . () — findOrCreate(), laravel-permissions. , , .
, . :
php artisan migrate --seed
. ! , :
- (Model).
- (Controller) ModelController.
- (Policy) ModelPolicy.
- .
, (. 1) (. ).
هذا كل شئ حتى الان. آمل أن تكون هذه المقالة مفيدة. وإذا كان أحد الأشخاص مهتمًا بالتوليف الدقيق لحقوق وقيود المستخدمين ، أي حق المستخدم في مشاهدة / تغيير سمة معينة للنموذج - تتم
مناقشة هذا في الجزء الثالث .