Sistem otorisasi sumber daya canggih di Laravel. Bagian 1. Model, Pengendali

pengantar


Halo, Khabrovchans sayang.
Dalam perjalanan pekerjaan saya di platform api, saya menghabiskan banyak waktu mencari cara yang tepat untuk mengotorisasi tindakan pengguna. Tugas ditetapkan sebagai berikut - untuk membuat sistem kontrol akses dan tindakan yang cukup luas.
Pada saat yang sama, sebagian besar dari mereka menggunakan CRUD biasa, tetapi tindakan pengontrol lainnya perlu disahkan.
Jadi perlu menciptakan sistem yang sederhana dan efektif serta fleksibel. Ada banyak kerucut, karena dalam artikel ini saya memutuskan untuk menunjukkan versi yang agak disederhanakan dari apa yang saya lakukan.


Saya ingin menambahkan secara terpisah - materi ini dirancang untuk melatih programmer, dan akan sulit bagi pemula untuk memahaminya. Artikel ini tidak akan menjadwalkan instalasi proyek, dan pengaturan untuk menghubungkan ke database. Semua ini dapat Anda temukan dengan mudah di Internet.



Bagian 1. Model, Pengendali


Jadi, tugasnya: Ada banyak model, yang jumlahnya dapat bertambah dan berkurang selama pengembangan proyek.
Tindakan pada masing-masing dari mereka harus disahkan oleh peran.
Ada tindakan sederhana, seperti CRUD, dan tindakan tambahan (misalnya, impor, ekspor ).
Penting untuk menyederhanakan pekerjaan pengembang (untuk kekasih Anda) sebanyak mungkin untuk memperkenalkan model dan metode tambahan kepada mereka.
Artikel ini memberikan contoh untuk aplikasi Api, tetapi solusinya cocok tidak hanya untuk itu.


Model


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

, , โ€” :


  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 | ..., dapat: hapus, posting |
| api / post / {post} / export | ... \ PostController @ export | ..., dapat: ekspor, posting |
+ ----------------------- + ------------------------- - + ------------------------------- +



Langkah selanjutnya adalah mengkonfigurasi tautan Gate (Gate) <-> Kebijakan. Tetapi lebih lanjut tentang itu di bagian kedua .


All Articles