Introdução
Olá queridos Khabrovchans.
No decorrer do meu trabalho na plataforma da API, passei muito tempo procurando a maneira certa de autorizar ações do usuário. A tarefa foi definida da seguinte forma - para criar um sistema bastante extenso de controle de acesso e ações.
Ao mesmo tempo, a maioria deles usa CRUD regular, mas outras ações do controlador precisam ser autorizadas.
Portanto, é necessário criar um sistema simples e ao mesmo tempo eficaz e flexível. Havia muitos cones, porque nesses artigos eu decidi demonstrar uma versão um pouco simplificada do que fiz.
Gostaria de acrescentar separadamente - o material foi projetado para a prática de programadores e será difícil para um iniciante entender. Este artigo não agendará a instalação do projeto e as configurações para conectar-se ao banco de dados. Tudo isso você pode encontrar facilmente na Internet.
Parte 1. Modelo, Controladores
Portanto, a tarefa: existem muitos modelos, cujo número pode aumentar e diminuir durante o desenvolvimento do projeto.
As ações em cada um deles devem ser autorizadas por funções.
Existem ações simples, como CRUD, e outras adicionais (por exemplo, importação, exportação ).
É necessário simplificar o trabalho do desenvolvedor (para o seu amado), tanto quanto possível, para introduzir modelos e métodos adicionais a eles.
O artigo fornece um exemplo para um aplicativo Api, mas a solução é adequada não apenas para isso.
Modelo
Post. ( ) app.
app/Models Posts. ( , -).
. :
php artisan make:model Models/Post --api --migration
php artisan migrate
: , . , .
PostController CRUD
Controller.
ModelController Controller , , PostController.
PostController — import() 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
, , — :
- viewAny view apiResource
- , — .
:
. 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
{
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
{
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 | ..., pode: excluir, publicar |
| api / posts / {post} / export | ... \ PostController @ export | ..., pode: exportar, publicar |
+ ----------------------- + ------------------------- - + ------------------------------- +
O próximo passo é configurar o link Gate (Gate) <-> Policy. Mas mais sobre isso na segunda parte .