EinfĂĽhrung
Hallo lieber Chabrowitsch.
Ich setze meine Artikelserie zur erweiterten Ressourcenautorisierung in Laravel fort. Um besser zu verstehen, was in diesem Artikel behandelt wird, mĂĽssen Sie den ersten Teil lesen .
Zunächst möchte ich kurz auf die Problemstellung eingehen: Es gibt eine große Anzahl von Modellen. Es ist notwendig, ein flexibles und leicht erweiterbares System zu entwerfen, um Benutzeraktionen abhängig von seiner Rolle zu autorisieren.
In diesem Teil werden wir ĂĽber die Konfiguration des Verbindungsrichtlinien-Gateways <=> sprechen. AuĂźerdem wird eine der Optionen zum Schreiben von Benutzerrechten in die Datenbank vorgeschlagen.
Und natĂĽrlich werde ich sofort klarstellen, dass das Material fĂĽr das Ăśben von Programmierern gedacht ist und fĂĽr einen unerfahrenen Entwickler schwer zu verstehen sein wird.
Teil 3. Richtlinien, Gateways
Theoretischer Teil
Im Internet finden Sie eine Menge Material zum Thema „Was wählen Sie als Richtlinie oder Gate ?“. Für eine gewisse Zeit bin ich auch auf einen ähnlichen Fehler gestoßen, dass Sie etwas auswählen müssen. Aber am Ende bin ich zu dem Schluss gekommen - dies sind zwei Glieder derselben Kette, die am effektivsten zusammen verwendet werden.
In Laravel gibt es zwei Hauptrichtungen fĂĽr die Bestimmung dieses Bundles - manuell und automatisch. Ich werde nicht auf manuell eingehen, da die UnterstĂĽtzung dieser Art von Bundle ĂĽberproportional viel Programmieraufwand erfordert als die Einrichtung einer automatischen.
— , () . (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) (. ).
Das ist alles für jetzt. Hoffe, dieser Artikel war hilfreich. Und wenn jemand daran interessiert ist, die Rechte und Einschränkungen der Benutzer noch genauer abzustimmen, nämlich das Recht des Benutzers, ein bestimmtes Attribut des Modells zu beobachten / zu ändern, wird
dies im dritten Teil erörtert .