Skip to content

Commit f7f0975

Browse files
Merge branch 'feat/role-permission'
2 parents d3c0720 + 667b5fe commit f7f0975

File tree

5 files changed

+344
-0
lines changed

5 files changed

+344
-0
lines changed

app/Models/User.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Illuminate\Database\Eloquent\Factories\HasFactory;
1111
use Illuminate\Foundation\Auth\User as Authenticatable;
1212
use Illuminate\Notifications\Notifiable;
13+
use Spatie\Permission\Traits\HasRoles;
1314

1415
/**
1516
* @property int $id
@@ -39,6 +40,7 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, MustVerif
3940
/** @use HasFactory<\Database\Factories\UserFactory> */
4041
use HasFactory;
4142

43+
use HasRoles;
4244
use Notifiable;
4345

4446
/**

app/Providers/Filament/AdminPanelProvider.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace App\Providers\Filament;
44

5+
use Althinect\FilamentSpatieRolesPermissions\FilamentSpatieRolesPermissionsPlugin;
56
use Filament\Http\Middleware\Authenticate;
67
use Filament\Http\Middleware\DisableBladeIconComponents;
78
use Filament\Http\Middleware\DispatchServingFilamentEvent;
@@ -40,6 +41,7 @@ public function panel(Panel $panel): Panel
4041
Widgets\AccountWidget::class,
4142
Widgets\FilamentInfoWidget::class,
4243
])
44+
->plugin(FilamentSpatieRolesPermissionsPlugin::make())
4345
->middleware([
4446
EncryptCookies::class,
4547
AddQueuedCookiesToResponse::class,

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
"license": "MIT",
1111
"require": {
1212
"php": "^8.2",
13+
"althinect/filament-spatie-roles-permissions": "^2.3",
1314
"filament/filament": "^3.3",
1415
"filament/spatie-laravel-settings-plugin": "^3.3",
1516
"laravel/framework": "^12.0",
1617
"laravel/tinker": "^2.10.1",
18+
"spatie/laravel-permission": "^6.21",
1719
"spatie/laravel-settings": "^3.4"
1820
},
1921
"require-dev": {

config/permission.php

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
<?php
2+
3+
return [
4+
5+
'models' => [
6+
7+
/*
8+
* When using the "HasPermissions" trait from this package, we need to know which
9+
* Eloquent model should be used to retrieve your permissions. Of course, it
10+
* is often just the "Permission" model but you may use whatever you like.
11+
*
12+
* The model you want to use as a Permission model needs to implement the
13+
* `Spatie\Permission\Contracts\Permission` contract.
14+
*/
15+
16+
'permission' => Spatie\Permission\Models\Permission::class,
17+
18+
/*
19+
* When using the "HasRoles" trait from this package, we need to know which
20+
* Eloquent model should be used to retrieve your roles. Of course, it
21+
* is often just the "Role" model but you may use whatever you like.
22+
*
23+
* The model you want to use as a Role model needs to implement the
24+
* `Spatie\Permission\Contracts\Role` contract.
25+
*/
26+
27+
'role' => Spatie\Permission\Models\Role::class,
28+
29+
],
30+
31+
'table_names' => [
32+
33+
/*
34+
* When using the "HasRoles" trait from this package, we need to know which
35+
* table should be used to retrieve your roles. We have chosen a basic
36+
* default value but you may easily change it to any table you like.
37+
*/
38+
39+
'roles' => 'roles',
40+
41+
/*
42+
* When using the "HasPermissions" trait from this package, we need to know which
43+
* table should be used to retrieve your permissions. We have chosen a basic
44+
* default value but you may easily change it to any table you like.
45+
*/
46+
47+
'permissions' => 'permissions',
48+
49+
/*
50+
* When using the "HasPermissions" trait from this package, we need to know which
51+
* table should be used to retrieve your models permissions. We have chosen a
52+
* basic default value but you may easily change it to any table you like.
53+
*/
54+
55+
'model_has_permissions' => 'model_has_permissions',
56+
57+
/*
58+
* When using the "HasRoles" trait from this package, we need to know which
59+
* table should be used to retrieve your models roles. We have chosen a
60+
* basic default value but you may easily change it to any table you like.
61+
*/
62+
63+
'model_has_roles' => 'model_has_roles',
64+
65+
/*
66+
* When using the "HasRoles" trait from this package, we need to know which
67+
* table should be used to retrieve your roles permissions. We have chosen a
68+
* basic default value but you may easily change it to any table you like.
69+
*/
70+
71+
'role_has_permissions' => 'role_has_permissions',
72+
],
73+
74+
'column_names' => [
75+
/*
76+
* Change this if you want to name the related pivots other than defaults
77+
*/
78+
'role_pivot_key' => null, // default 'role_id',
79+
'permission_pivot_key' => null, // default 'permission_id',
80+
81+
/*
82+
* Change this if you want to name the related model primary key other than
83+
* `model_id`.
84+
*
85+
* For example, this would be nice if your primary keys are all UUIDs. In
86+
* that case, name this `model_uuid`.
87+
*/
88+
89+
'model_morph_key' => 'model_id',
90+
91+
/*
92+
* Change this if you want to use the teams feature and your related model's
93+
* foreign key is other than `team_id`.
94+
*/
95+
96+
'team_foreign_key' => 'team_id',
97+
],
98+
99+
/*
100+
* When set to true, the method for checking permissions will be registered on the gate.
101+
* Set this to false if you want to implement custom logic for checking permissions.
102+
*/
103+
104+
'register_permission_check_method' => true,
105+
106+
/*
107+
* When set to true, Laravel\Octane\Events\OperationTerminated event listener will be registered
108+
* this will refresh permissions on every TickTerminated, TaskTerminated and RequestTerminated
109+
* NOTE: This should not be needed in most cases, but an Octane/Vapor combination benefited from it.
110+
*/
111+
'register_octane_reset_listener' => false,
112+
113+
/*
114+
* Events will fire when a role or permission is assigned/unassigned:
115+
* \Spatie\Permission\Events\RoleAttached
116+
* \Spatie\Permission\Events\RoleDetached
117+
* \Spatie\Permission\Events\PermissionAttached
118+
* \Spatie\Permission\Events\PermissionDetached
119+
*
120+
* To enable, set to true, and then create listeners to watch these events.
121+
*/
122+
'events_enabled' => false,
123+
124+
/*
125+
* Teams Feature.
126+
* When set to true the package implements teams using the 'team_foreign_key'.
127+
* If you want the migrations to register the 'team_foreign_key', you must
128+
* set this to true before doing the migration.
129+
* If you already did the migration then you must make a new migration to also
130+
* add 'team_foreign_key' to 'roles', 'model_has_roles', and 'model_has_permissions'
131+
* (view the latest version of this package's migration file)
132+
*/
133+
134+
'teams' => false,
135+
136+
/*
137+
* The class to use to resolve the permissions team id
138+
*/
139+
'team_resolver' => \Spatie\Permission\DefaultTeamResolver::class,
140+
141+
/*
142+
* Passport Client Credentials Grant
143+
* When set to true the package will use Passports Client to check permissions
144+
*/
145+
146+
'use_passport_client_credentials' => false,
147+
148+
/*
149+
* When set to true, the required permission names are added to exception messages.
150+
* This could be considered an information leak in some contexts, so the default
151+
* setting is false here for optimum safety.
152+
*/
153+
154+
'display_permission_in_exception' => false,
155+
156+
/*
157+
* When set to true, the required role names are added to exception messages.
158+
* This could be considered an information leak in some contexts, so the default
159+
* setting is false here for optimum safety.
160+
*/
161+
162+
'display_role_in_exception' => false,
163+
164+
/*
165+
* By default wildcard permission lookups are disabled.
166+
* See documentation to understand supported syntax.
167+
*/
168+
169+
'enable_wildcard_permission' => false,
170+
171+
/*
172+
* The class to use for interpreting wildcard permissions.
173+
* If you need to modify delimiters, override the class and specify its name here.
174+
*/
175+
// 'wildcard_permission' => Spatie\Permission\WildcardPermission::class,
176+
177+
/* Cache-specific settings */
178+
179+
'cache' => [
180+
181+
/*
182+
* By default all permissions are cached for 24 hours to speed up performance.
183+
* When permissions or roles are updated the cache is flushed automatically.
184+
*/
185+
186+
'expiration_time' => \DateInterval::createFromDateString('24 hours'),
187+
188+
/*
189+
* The cache key used to store all permissions.
190+
*/
191+
192+
'key' => 'spatie.permission.cache',
193+
194+
/*
195+
* You may optionally indicate a specific cache driver to use for permission and
196+
* role caching using any of the `store` drivers listed in the cache.php config
197+
* file. Using 'default' here means to use the `default` set in cache.php.
198+
*/
199+
200+
'store' => 'default',
201+
],
202+
];
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
$teams = config('permission.teams');
15+
$tableNames = config('permission.table_names');
16+
$columnNames = config('permission.column_names');
17+
$pivotRole = $columnNames['role_pivot_key'] ?? 'role_id';
18+
$pivotPermission = $columnNames['permission_pivot_key'] ?? 'permission_id';
19+
20+
throw_if(empty($tableNames), new Exception('Error: config/permission.php not loaded. Run [php artisan config:clear] and try again.'));
21+
throw_if($teams && empty($columnNames['team_foreign_key'] ?? null), new Exception('Error: team_foreign_key on config/permission.php not loaded. Run [php artisan config:clear] and try again.'));
22+
23+
Schema::create($tableNames['permissions'], static function (Blueprint $table) {
24+
// $table->engine('InnoDB');
25+
$table->bigIncrements('id'); // permission id
26+
$table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format)
27+
$table->string('guard_name'); // For MyISAM use string('guard_name', 25);
28+
$table->timestamps();
29+
30+
$table->unique(['name', 'guard_name']);
31+
});
32+
33+
Schema::create($tableNames['roles'], static function (Blueprint $table) use ($teams, $columnNames) {
34+
// $table->engine('InnoDB');
35+
$table->bigIncrements('id'); // role id
36+
if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing
37+
$table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable();
38+
$table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index');
39+
}
40+
$table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format)
41+
$table->string('guard_name'); // For MyISAM use string('guard_name', 25);
42+
$table->timestamps();
43+
if ($teams || config('permission.testing')) {
44+
$table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']);
45+
} else {
46+
$table->unique(['name', 'guard_name']);
47+
}
48+
});
49+
50+
Schema::create($tableNames['model_has_permissions'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) {
51+
$table->unsignedBigInteger($pivotPermission);
52+
53+
$table->string('model_type');
54+
$table->unsignedBigInteger($columnNames['model_morph_key']);
55+
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');
56+
57+
$table->foreign($pivotPermission)
58+
->references('id') // permission id
59+
->on($tableNames['permissions'])
60+
->onDelete('cascade');
61+
if ($teams) {
62+
$table->unsignedBigInteger($columnNames['team_foreign_key']);
63+
$table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index');
64+
65+
$table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'],
66+
'model_has_permissions_permission_model_type_primary');
67+
} else {
68+
$table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
69+
'model_has_permissions_permission_model_type_primary');
70+
}
71+
72+
});
73+
74+
Schema::create($tableNames['model_has_roles'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) {
75+
$table->unsignedBigInteger($pivotRole);
76+
77+
$table->string('model_type');
78+
$table->unsignedBigInteger($columnNames['model_morph_key']);
79+
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');
80+
81+
$table->foreign($pivotRole)
82+
->references('id') // role id
83+
->on($tableNames['roles'])
84+
->onDelete('cascade');
85+
if ($teams) {
86+
$table->unsignedBigInteger($columnNames['team_foreign_key']);
87+
$table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index');
88+
89+
$table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'],
90+
'model_has_roles_role_model_type_primary');
91+
} else {
92+
$table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'],
93+
'model_has_roles_role_model_type_primary');
94+
}
95+
});
96+
97+
Schema::create($tableNames['role_has_permissions'], static function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) {
98+
$table->unsignedBigInteger($pivotPermission);
99+
$table->unsignedBigInteger($pivotRole);
100+
101+
$table->foreign($pivotPermission)
102+
->references('id') // permission id
103+
->on($tableNames['permissions'])
104+
->onDelete('cascade');
105+
106+
$table->foreign($pivotRole)
107+
->references('id') // role id
108+
->on($tableNames['roles'])
109+
->onDelete('cascade');
110+
111+
$table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary');
112+
});
113+
114+
app('cache')
115+
->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null)
116+
->forget(config('permission.cache.key'));
117+
}
118+
119+
/**
120+
* Reverse the migrations.
121+
*/
122+
public function down(): void
123+
{
124+
$tableNames = config('permission.table_names');
125+
126+
if (empty($tableNames)) {
127+
throw new \Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.');
128+
}
129+
130+
Schema::drop($tableNames['role_has_permissions']);
131+
Schema::drop($tableNames['model_has_roles']);
132+
Schema::drop($tableNames['model_has_permissions']);
133+
Schema::drop($tableNames['roles']);
134+
Schema::drop($tableNames['permissions']);
135+
}
136+
};

0 commit comments

Comments
 (0)