Système avancé d'autorisation des ressources à Laravel. Partie 1. Modèle, contrôleur

introduction


Bonjour, cher Khabrovchans.
Au cours de mon travail sur la plate-forme api, j'ai passé beaucoup de temps à chercher la bonne façon d'autoriser les actions des utilisateurs. La tâche a été définie comme suit - créer un système assez étendu de contrôle d'accès et d'actions.
Dans le même temps, la plupart d'entre eux sont sur un CRUD régulier, mais d'autres actions du contrôleur devront être autorisées.
Il est donc nécessaire de créer un système simple et à la fois efficace et flexible. Il y avait beaucoup de cônes, car dans ces articles, j'ai décidé de démontrer une version quelque peu simplifiée de ce que j'ai fait.


Je voudrais ajouter séparément - le matériel est conçu pour les programmeurs pratiquants et sera difficile à comprendre pour un débutant. Cet article ne planifiera pas l'installation du projet et les paramètres de connexion à la base de données. Tout cela, vous pouvez facilement le trouver sur Internet.



Partie 1. Modèle, contrôleurs


Donc, la tâche: Il existe de nombreux modèles, dont le nombre peut augmenter et diminuer au cours du développement du projet.
Les actions sur chacun d'entre eux doivent être autorisées par les rôles.
Il existe des actions simples, telles que CRUD, et d'autres (par exemple, importation, exportation ).
Il est nécessaire de simplifier le travail du développeur (à votre bien-aimé) autant que possible pour leur introduire des modèles et des méthodes supplémentaires.
L'article fournit un exemple pour une application Api, mais la solution ne convient pas seulement à cela.


Modèle


Post. ( ) app.
app/Models Posts. ( , -).
. :


    php artisan make:model Models/Post --api --migration
    php artisan migrate

: , . , .



PostController CRUD
Controller.
ModelController Controller , , PostController.
PostControllerimport() export(Post $post).
, .



Laravel Illuminate\Foundation\Auth\Access\AuthorizesRequests.
App\Http\Controllers\Controller ModelController. Controller , .
authorizeResource($model).
, (Middleware) .
:


    can:viewAny,App\Models\Post
    can:view,post
    can:update,post

, , — :


  1. viewAny view apiResource
  2. , — .

:


. resourceAbilityMap() .


<?php
protected function resourceAbilityMap()
{
    return [
        'index' => 'viewAny',
        'show' => 'view',
        'create' => 'create',
        'store' => 'create',
        'edit' => 'update',
        'update' => 'update',
        'destroy' => 'delete',
    ];
}

. Laravel . , . index() , show(Post $post) . resourceMethodsWithoutModels()


<?php
protected function resourceMethodsWithoutModels()
{
    return ['index', 'create', 'store'];
}


(ModelController)

app/Http/Controllers ModelController. :


  • $guardedMethods « » => « ».
    (Policy) , , (Gate). .
  • $methodsWithoutModels .
  • getModelClass() .
    .
  • authorizeResource($this->getModelClass()) . ( (Route), )
  • resourceAbilityMap() resourceMethodsWithoutModels() , , .

<?php

namespace App\Http\Controllers;

abstract class ModelController extends Controller
{
    /** @var array 'method' => 'policy'*/
    protected $guardedMethods = [];

    protected $methodsWithoutModels = [];

    protected abstract function getModelClass(): string;

    public function __construct()
    {
        $this->authorizeResource($this->getModelClass());
    }

    protected function resourceAbilityMap()
    {
        $base = parent::resourceAbilityMap();

        return array_merge($base, $this->guardedMethods);
    }

    protected function resourceMethodsWithoutModels()
    {
        $base = parent::resourceMethodsWithoutModels();

        return array_merge($base, $this->methodsWithoutModels);
    }
}

(PostController)

:


  • getModelClass() .
  • $methodsWithoutModels « » => « » . . , =. , , .
  • $methodsWithoutModels , . import
  • — , . — .

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends ModelController
{
    /** @var array 'method' => 'policy'*/
    protected $guardedMethods = [
        'export' => 'export',
        'import' => 'import',
    ];

    protected $methodsWithoutModels = ['import'];

    protected function getModelClass(): string
    {
        return Post::class;
    }

    public function index()
    { /**     */ }

    public function store(Request $request)
    { /**    */ }

    public function show(Post $post)
    { /**    */ }

    public function update(Request $request, Post $post)
    { /**    */ }

    public function destroy(Post $post)
    { /**    */ }

    public function import()
    { /**     */ }

    public function export(Post $post)
    { /**    */ }
}

(Routes)


.
'routes/api.php' ( 'routes/web.php', ) .
, , .
— ( ) , Route::apiResource('posts', 'PostController'). Laravel. .
— 'auth:api'. , .


<?php

use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;

Route::group(['middleware' => ['auth:api']], static function () {
    Route::post('posts/import', 'PostController@import')->name('posts.import');
    Route::get('posts/{post}/export', 'PostController@export')->name('posts.export');
    Route::apiResource('posts', 'PostController');
});

. :


php artisan route:list

— ( )


+-----------------------+---------------------------+-------------------------------+
|URI                    |Action                     |Middleware                     |
+-----------------------+---------------------------+-------------------------------+
|api/posts              |...\PostController@index   |...,can:viewAny,App\Models\Post|
|api/posts              |...\PostController@store   |...,can:create,App\Models\Post |
|api/posts/import       |...\PostController@import  |...,can:import,App\Models\Post |
|api/posts/{post}       |...\PostController@show    |...,can:view,post              |
|api/posts/{post}       |...\PostController@update  |...,can:update,post            |
| api / posts / {post} | ... \ PostController @ destroy | ..., peut: supprimer, publier |
| api / posts / {post} / export | ... \ PostController @ export | ..., peut: exporter, publier |
+ ----------------------- + ------------------------- - + ------------------------------- +



L'étape suivante consiste à configurer la stratégie Link Gate (Gate) <->. Mais plus à ce sujet dans la deuxième partie .


All Articles