Laravel Spatie Permission Package – Kurz mal erklärt

Die belgische „SoftwareGang“ Spatie haut ein coole Laravel Package nach dem anderen raus. Super nützlich und sehr angenehm zu nutzen. Heute gibt es einen Einstieg in das Package Spatie Permission Package.

I. Einrichten

1. Schritt:

composer require spatie/laravel-permission 

2. Schritt: Permission Service Provider anmelden

Füge dafür den „PermissionServiceProvider“ in der Datei config/app.php ein.

 'providers' => [
     // ...
     Spatie\Permission\PermissionServiceProvider::class,
 ]; 

3. Schritt: Kopiere die migration aus dem Vendor in das Projektverzeichnis

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" 

4. Nun noch den Config cache bereinigen

php artisan config:clear

5. Migration starten

php artisan migrate 

6. Füge den Trait zum User Model hinzu.

 class User extends Authenticatable
 {
     use HasApiTokens, HasFactory, Notifiable, HasRoles;
 
 

Dadurch haben wir nun Zugriff auf die Spatie Permissions Methoden um dem User Rolen zuzuweisen.

Das war das einrichten und nun gehen wir über zum nutzen.

II. Anwenden

Dafür gehen wir aus, dass wir einen Blog bauen. Hier haben wir unterschiedliche Rollen wie zum Beispiel: Admin, Writer, Reviewer. Der Weiter hat folgende Berechtigung: „edit post“.

Um die Rollen und Berechtigungen zu erstellen, nutzen wir einen Seeder. Den erstellt man in Laravel mit:

php artisan make:seeder RolesSeeder 

In deren run Methode definieren wir unser Model.

 <?php
 namespace Database\Seeders;
 
 
 use Illuminate\Database\Seeder;
 use Spatie\Permission\Models\Role;
 
 
 class RolesSeeder extends Seeder
 {
     /**
      * Run the database seeds.
      *
      * @return void
      */
     public function run()
     {
         $roles = ['admin', 'provider', 'customer'];
 
 
         foreach($roles as $role) {
             Role::create(['name' => $role]);
         }         
     }
 } 

Das Gleiche nun auch für die Berechtigungen:

php artisan make:seeder PermissionsSeeder 
 <?php
 namespace Database\Seeders;
 
 
 use Illuminate\Database\Seeder;
 use Spatie\Permission\Models\Permission;
 
 
 class PermissionsSeeder extends Seeder
 {
     /**
      * Run the database seeds.
      *
      * @return void
      */
     public function run()
     {
         $permissions = ['edit post', 'delete post'];
 
 
         foreach($permissions as $permission) {
             Permission::create(['name' => $permission]);
         }                 
     }
 } 

Jetzt deklarieren wir der DatabaseSeeder Klasse, welche Seeds er „runen“ soll.

<?php
 namespace Database\Seeders;
 
 
 use Illuminate\Database\Seeder;
 
 
 class DatabaseSeeder extends Seeder
 {
     /**
      * Seed the application's database.
      *
      * @return void
      */
     public function run()
     {
         $this->call(RolesSeeder::class);
         $this->call(PermissionsSeeder::class);
 
 
         // create User
         $user = \App\Models\User::create([
             'name' => 'Martin',
             'email' => 'martin@peoplehelper.org',
             'password' => bcrypt('password')
         ]);
 
 
         // asaign user a role as writer
         $user->assignRole('writer');
 
 
         // assign permission to an role (1 = edit post)
         $role = $user->roles[0];
         $role->givePermissionTo(\Spatie\Permission\Models\Permission::find(1));
     }
 } 

Sobald wir das haben können wir mal die Migration durchlaufen lassen:

php artisan db:seed  
// bzw.
php artisan migrate:refresh –seed 

Ein Blick in unsere Datenbank zeigt, dass wir erfolgreich die Role Writer dem User Martin zugewiesen haben.

Für das Wiederrufen einer Berechtigung ($user->revokePermissionTo(‘delete post‘) ) oder das entfernen einer Role vom User ($user->removeRole(‘writer‘)) könnt das ganz gut in der Spatie Doku nachlesen. Das Gleiche gilt für die Konditional Abfragen wie zum Beispiel $user→can(‘delete post‘).

Die „Blade Directives“

Hier kann man mit:

 @can(‘edit post‘)
 ...
 @endcan
 
 
 @role(‘writer‘)
 …
 @endrole
 
 
 @hasrole(‘writer‘)
 ...
 @endhasrole
 
 
 @hasanyrole(Collection || Array )
 @endhasanyrol
 
 
 @hasanyrole(‘writer|admin‘)
 ...
 @endhasanyrole
 
 
 @unlessrole('admin')
 ...
 @end unlessrole 

Logiksecurity statt nur Viewhidding

Ich musste mal mit einem Indischen PHP Entwickler zusammen arbeiten, der die Berechtigungslogiken nur in den Blades abbildete. Im Controller und bzw. oder Serviceklassen hat er es weitestgehend vermieden. Was zu einem Sicherheitsproblem wurde.

Deshalb sein es hier wichtig zu erwähnen, dass nicht zu vergessen. Ein eleganter und einfacher Ansatz wäre hier mit einer Middleware zu arbeiten. Somit kann man die Routes ohne viel Umwege gut vor unberechtigten URL aufrufen schützen.

Alles was wir machen müssen ist:

1: Schritt: Das PermissionRole Package der Route Middleware hinzufügen.

Das passiert in der Kernel.php Datei in der Membervariablen $routeMiddleware. Hier fügen wir dem Array folgende Middlewarepakete hinzu.

protected $routeMiddleware = [
     // ...
     'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
     'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
     'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
 ]; 

Ab diesem Moment können wir in den Routes über Rollen und Berechtigungen schützen.

 Route::group(['middleware' => ['role:admin']], function () {
     //
 });
 
 // bzw.   
 
 Route::get(‘posts/create‘, [\App\Controllers\PostController,])→ ‘create‘])->middleware(['middleware' => ['role:admin']);
 
 
 Route::group(['middleware' => ['permission:publish articles']], function () {
     //
 });
 
 
 Route::group(['middleware' => ['role:super-admin','permission:publish articles']], function () {
     //
 });
 
 
 Route::group(['middleware' => ['role_or_permission:super-admin|edit articles']], function () {
     //
 });
 
 
 Route::group(['middleware' => ['role_or_permission:publish articles']], function () {
     //
 }); 

Wer die routes aus einem Grund nicht schützen kann oder will, kann das im Controller oder in der ServiceKlasse Deiner Anwendung auch vornehmen. Dort lädt man im Konstruktor der jeweiligen Klasse die Middleware und überprüft dann die Userberechtigung bzw. Userrolle.

 public function __construct()
 {
     $this->middleware(['role:admin','permission:publish articles|edit articles']);  
     // oder
     $this->middleware(['role_or_permission:super-admin|edit articles']);
 } 

Das war es auch schon für den kurzen Einstieg. Viel Spaß beim ausprobieren und nutzen!


Leave a Comment

Your email address will not be published. Required fields are marked *

*

*

Empfholende Artikel


Meine wichtigsten Artisan Commands

September 6, 2021

Als Laravel Entwickler braucht man sie ständig. Wenn man etwas länger Frontendarbeiten gemacht hat, kommt es schon mal vor, dass man etwas vergessen hat. Daher hier die Liste mit den häufigsten Artisan Commands: php artisan migrate:rollback –step=1 Ihr wollte eine oder x-beliebige Migrationen zurückspulen? Dann rollback und die Anzahl der Migrationssteps eingeben. php artisan migrate:refresh […]

Laravel – Slugs einrichten

September 2, 2021

Slugs machen die URLs Sprechender und damit auch SEO-(Freund)licher. Statt domain.de/posts/1 würde man mit domain.de/posts/mein-erster-blog-eintrag arbeiten. Um das in Laravel zu realisieren, bedient man sich in der Regel externer Bibliotheken. Einmal eine von Spartie und eine cviebrock. Man kann es natürlich aber auch selber machen. Die Bibliotheken sind hier aber vorzuziehen. Weil es ist keine […]

Laravel Blade Components

August 27, 2021

Componets – Aus VueJS kennen wir es und haben es bereits lieben gelernt. In Laravel können wir im Blade auch sehr dynamisch in Componenten arbeiten. Von Hause gibt uns Laravel Componets mit. Am Beispiel erklärt Stellen wir uns vor, wir wollen ein Blog erstellen. In der Übersichtsseite, sollen die Blogartikel untereinander gelistet werden. Wer ohne […]

Laravel Resource – Kurz mal erklärt

August 26, 2021

Nutzen wir zum Beispiel Larvel als Backend und beliefern das Frontend via api Route mit Daten, dann stellt sich manchmal die Frage, welche Daten braucht das Frontend eigentlich? Braucht man wirklich created_at oder updated_at mit auszuliefern? Sobald man sich so eine oder ähnliche Frage stellt wird es Zeit sich mal mit Laravel Resource auseinander zu […]

Laravel Test möglicher Fehler – Unknown formatter “name”

April 17, 2021

Falls Du gerade Dein Test geschrieben hast und du deinen Test mit php artisan test startest kann es sein, dass Du folgende Fehlermeldung erhalten kannst: Was ist passiert? Wahrscheinlich hast Du in deiner seUp() Methode oder in deiner Testfunktion ein factory eingebaut. Zum Beispiel Da Laravel einige Optimierungen vorgenommen hat, kannst Du nicht die Standard […]

Eine einzelne Migration in Laravel ausführen

March 25, 2021

Aus unterschiedlichen Gründen kann es sein, dass man in einem Laravel Projekt eine spezielle Migration ausführen möchte. Zum Beispiel die zuletzt erstellte Migration. Ein anscheinend häufiger Grund für dieses Vorgehen könnte sein, dass in einer vorherigen Migrationsdatei ein Fehler auftreten würde. Und da Laravel die Migrationsdateien von der ältestesten zur jüngsten Migration abarbeitet, würde man […]