From 6600422505a7d4d162230eddf5fe174707a0fde5 Mon Sep 17 00:00:00 2001 From: Fatih Alp Date: Wed, 4 Mar 2026 00:30:03 +0300 Subject: [PATCH] Delete .agents/skills/laravel-permission-development/SKILL.md --- .../laravel-permission-development/SKILL.md | 277 ------------------ 1 file changed, 277 deletions(-) delete mode 100644 .agents/skills/laravel-permission-development/SKILL.md diff --git a/.agents/skills/laravel-permission-development/SKILL.md b/.agents/skills/laravel-permission-development/SKILL.md deleted file mode 100644 index aa7f2b125..000000000 --- a/.agents/skills/laravel-permission-development/SKILL.md +++ /dev/null @@ -1,277 +0,0 @@ ---- -name: laravel-permission-development -description: Build and work with Spatie Laravel Permission features, including roles, permissions, middleware, policies, teams, and Blade directives. ---- - -# Laravel Permission Development - -## When to use this skill - -Use this skill when working with authorization, roles, permissions, access control, middleware guards, or Blade permission directives using spatie/laravel-permission. - -## Core Concepts - -- **Users have Roles, Roles have Permissions, Apps check Permissions** (not Roles). -- Direct permissions on users are an anti-pattern; assign permissions to roles instead. -- Use `$user->can('permission-name')` for all authorization checks (supports Super Admin via Gate). -- The `HasRoles` trait (which includes `HasPermissions`) is added to User models. - -## Setup - -Add the `HasRoles` trait to your User model: - -```php -use Spatie\Permission\Traits\HasRoles; - -class User extends Authenticatable -{ - use HasRoles; -} -``` - -## Creating Roles and Permissions - -```php -use Spatie\Permission\Models\Role; -use Spatie\Permission\Models\Permission; - -$role = Role::create(['name' => 'writer']); -$permission = Permission::create(['name' => 'edit articles']); - -// findOrCreate is idempotent (safe for seeders) -$role = Role::findOrCreate('writer', 'web'); -$permission = Permission::findOrCreate('edit articles', 'web'); -``` - -## Assigning Roles and Permissions - -```php -// Assign roles to users -$user->assignRole('writer'); -$user->assignRole('writer', 'admin'); -$user->assignRole(['writer', 'admin']); -$user->syncRoles(['writer', 'admin']); // replaces all -$user->removeRole('writer'); - -// Assign permissions to roles (preferred) -$role->givePermissionTo('edit articles'); -$role->givePermissionTo(['edit articles', 'delete articles']); -$role->syncPermissions(['edit articles', 'delete articles']); -$role->revokePermissionTo('edit articles'); - -// Reverse assignment -$permission->assignRole('writer'); -$permission->syncRoles(['writer', 'editor']); -$permission->removeRole('writer'); -``` - -## Checking Roles and Permissions - -```php -// Permission checks (preferred - supports Super Admin via Gate) -$user->can('edit articles'); -$user->canAny(['edit articles', 'delete articles']); - -// Direct package methods (bypass Gate, no Super Admin support) -$user->hasPermissionTo('edit articles'); -$user->hasAnyPermission(['edit articles', 'publish articles']); -$user->hasAllPermissions(['edit articles', 'publish articles']); -$user->hasDirectPermission('edit articles'); - -// Role checks -$user->hasRole('writer'); -$user->hasAnyRole(['writer', 'editor']); -$user->hasAllRoles(['writer', 'editor']); -$user->hasExactRoles(['writer', 'editor']); - -// Get assigned roles and permissions -$user->getRoleNames(); // Collection of role name strings -$user->getPermissionNames(); // Collection of permission name strings -$user->getDirectPermissions(); // Direct permissions only -$user->getPermissionsViaRoles(); // Inherited via roles -$user->getAllPermissions(); // Both direct and inherited -``` - -## Query Scopes - -```php -$users = User::role('writer')->get(); -$users = User::withoutRole('writer')->get(); -$users = User::permission('edit articles')->get(); -$users = User::withoutPermission('edit articles')->get(); -``` - -## Middleware - -Register middleware aliases in `bootstrap/app.php`: - -```php -->withMiddleware(function (Middleware $middleware) { - $middleware->alias([ - 'role' => \Spatie\Permission\Middleware\RoleMiddleware::class, - 'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class, - 'role_or_permission' => \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class, - ]); -}) -``` - -Use in routes (pipe `|` for OR logic): - -```php -Route::middleware(['permission:edit articles'])->group(function () { ... }); -Route::middleware(['role:manager|writer'])->group(function () { ... }); -Route::middleware(['role_or_permission:manager|edit articles'])->group(function () { ... }); - -// With specific guard -Route::middleware(['role:manager,api'])->group(function () { ... }); -``` - -For single permissions, Laravel's built-in `can` middleware also works: - -```php -Route::middleware(['can:edit articles'])->group(function () { ... }); -``` - -## Blade Directives - -Prefer `@can` (permission-based) over `@role` (role-based): - -```blade -@can('edit articles') - {{-- User can edit articles (supports Super Admin) --}} -@endcan - -@canany(['edit articles', 'delete articles']) - {{-- User can do at least one --}} -@endcanany - -@role('admin') - {{-- Only use for super-admin type checks --}} -@endrole - -@hasanyrole('writer|admin') - {{-- Has writer or admin --}} -@endhasanyrole -``` - -## Super Admin - -Use `Gate::before` in `AppServiceProvider::boot()`: - -```php -use Illuminate\Support\Facades\Gate; - -public function boot(): void -{ - Gate::before(function ($user, $ability) { - return $user->hasRole('Super Admin') ? true : null; - }); -} -``` - -This makes `$user->can()` and `@can` always return true for Super Admins. Must return `null` (not `false`) to allow normal checks for other users. - -## Policies - -Use `$user->can()` inside policy methods to check permissions: - -```php -class PostPolicy -{ - public function update(User $user, Post $post): bool - { - if ($user->can('edit all posts')) { - return true; - } - - return $user->can('edit own posts') && $user->id === $post->user_id; - } -} -``` - -## Enums - -```php -enum RolesEnum: string -{ - case WRITER = 'writer'; - case EDITOR = 'editor'; -} - -enum PermissionsEnum: string -{ - case EDIT_POSTS = 'edit posts'; - case DELETE_POSTS = 'delete posts'; -} - -// Creation requires ->value -Permission::findOrCreate(PermissionsEnum::EDIT_POSTS->value, 'web'); - -// Most methods accept enums directly -$user->assignRole(RolesEnum::WRITER); -$user->hasRole(RolesEnum::WRITER); -$role->givePermissionTo(PermissionsEnum::EDIT_POSTS); -$user->hasPermissionTo(PermissionsEnum::EDIT_POSTS); -``` - -## Seeding - -Always flush the permission cache when seeding: - -```php -class RolesAndPermissionsSeeder extends Seeder -{ - public function run(): void - { - // Reset cache - app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions(); - - // Create permissions - Permission::findOrCreate('edit articles', 'web'); - Permission::findOrCreate('delete articles', 'web'); - - // Create roles and assign permissions - Role::findOrCreate('writer', 'web') - ->givePermissionTo(['edit articles']); - - Role::findOrCreate('admin', 'web') - ->givePermissionTo(Permission::all()); - } -} -``` - -## Teams (Multi-Tenancy) - -Enable in `config/permission.php` before running migrations: - -```php -'teams' => true, -``` - -Set the active team in middleware: - -```php -setPermissionsTeamId($teamId); -``` - -When switching teams, unset cached relations: - -```php -$user->unsetRelation('roles')->unsetRelation('permissions'); -``` - -## Events - -Enable in `config/permission.php`: - -```php -'events_enabled' => true, -``` - -Available events: `RoleAttachedEvent`, `RoleDetachedEvent`, `PermissionAttachedEvent`, `PermissionDetachedEvent` in the `Spatie\Permission\Events` namespace. - -## Performance - -- Permissions are cached automatically. The cache is flushed when roles/permissions change via package methods. -- After direct DB operations, flush manually: `app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions()` -- For bulk seeding, use `Permission::insert()` for speed, but flush the cache afterward. \ No newline at end of file