diff --git a/config/shinobi.php b/config/shinobi.php index 352acd6..a93ac5d 100644 --- a/config/shinobi.php +++ b/config/shinobi.php @@ -2,6 +2,32 @@ return [ - // + 'models' => [ + /* + |-------------------------------------------------------------------------- + | Model References + |-------------------------------------------------------------------------- + | + | Shinobi needs to know which Eloquent Models should be referenced during + | actions such as registering and checking for permissions, assigning + | permissions to roles and users, and assigning roles to users. + */ + + 'role' => Caffeinated\Shinobi\Models\Role::class, + 'permission' => Caffeinated\Shinobi\Models\Permission::class, + + ], + + /* + |-------------------------------------------------------------------------- + | Use Migrations + |-------------------------------------------------------------------------- + | + | Shinobi comes packaged with everything out of the box for you, including + | migrations. If instead you wish to customize or extend Shinobi beyond + | its offering, you may disable the provided migrations for your own. + */ + + 'migrate' => true, ]; diff --git a/src/Concerns/HasPermissions.php b/src/Concerns/HasPermissions.php index 67ee5be..c39c5e3 100644 --- a/src/Concerns/HasPermissions.php +++ b/src/Concerns/HasPermissions.php @@ -2,7 +2,8 @@ namespace Caffeinated\Shinobi\Concerns; -use Caffeinated\Shinobi\Models\Permission; +use Caffeinated\Shinobi\Facades\Shinobi; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; trait HasPermissions { @@ -11,9 +12,9 @@ trait HasPermissions * * @return \Illuminate\Database\Eloquent\Model */ - public function permissions() + public function permissions(): BelongsToMany { - return $this->belongsToMany(Permission::class)->withTimestamps(); + return $this->belongsToMany(config('shinobi.models.permission'))->withTimestamps(); } /** @@ -21,10 +22,10 @@ public function permissions() * by Shinobi - checking for special flags, role permissions, and * individual user permissions; in that order. * - * @param \Caffeinated\Shinobi\Models\Permission $permission + * @param Permission $permission * @return boolean */ - public function hasPermissionTo($permission) + public function hasPermissionTo($permission): bool { // Check role flags if ($this->hasPermissionFlags()) { @@ -44,7 +45,7 @@ public function hasPermissionTo($permission) return false; } - public function givePermissionTo(...$permissions) + public function givePermissionTo(...$permissions): self { $permissions = array_flatten($permissions); $permissions = $this->getPermissions($permissions); @@ -58,7 +59,7 @@ public function givePermissionTo(...$permissions) return $this; } - public function revokePermissionTo(...$permissions) + public function revokePermissionTo(...$permissions): self { $permissions = array_flatten($permissions); $permissions = $this->getPermissions($permissions); @@ -68,7 +69,7 @@ public function revokePermissionTo(...$permissions) return $this; } - public function syncPermissions(...$permissions) + public function syncPermissions(...$permissions): self { $permissions = array_flatten($permissions); $permissions = $this->getPermissions($permissions); @@ -78,9 +79,15 @@ public function syncPermissions(...$permissions) return $this; } + /** + * Get specified permissions. + * + * @param array $permissions + * @return Permission + */ protected function getPermissions(array $permissions) { - return Permission::whereIn('slug', $permissions)->get(); + return Shinobi::permission()->whereIn('slug', $permissions)->get(); } /** @@ -89,7 +96,7 @@ protected function getPermissions(array $permissions) * @param \Caffeinated\Shinobi\Models\Permission $permission * @return boolean */ - protected function hasPermission($permission) + protected function hasPermission($permission): bool { return (bool) $this->permissions->where('slug', $permission->slug)->count(); } diff --git a/src/Concerns/HasRoles.php b/src/Concerns/HasRoles.php index 7ccb8b7..ab09f85 100644 --- a/src/Concerns/HasRoles.php +++ b/src/Concerns/HasRoles.php @@ -2,18 +2,19 @@ namespace Caffeinated\Shinobi\Concerns; -use Caffeinated\Shinobi\Models\Role; +use Caffeinated\Shinobi\Facades\Shinobi; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; trait HasRoles { /** * Users can have many roles. * - * @return \Illuminate\Database\Eloquent\Model + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function roles() + public function roles(): BelongsToMany { - return $this->belongsToMany(Role::class)->withTimestamps(); + return $this->belongsToMany(config('shinobi.models.role'))->withTimestamps(); } /** @@ -22,14 +23,20 @@ public function roles() * @param string $role * @return boolean */ - public function hasRole($role) + public function hasRole($role): bool { $slug = str_slug($role); return (bool) $this->roles->where('slug', $slug)->count(); } - public function assignRoles(...$roles) + /** + * Assign the specified roles to the model. + * + * @param mixed $roles,... + * @return self + */ + public function assignRoles(...$roles): self { $roles = array_flatten($roles); $roles = $this->getRoles($roles); @@ -43,7 +50,13 @@ public function assignRoles(...$roles) return $this; } - public function removeRoles(...$roles) + /** + * Remove the specified roles from the model. + * + * @param mixed $roles,... + * @return self + */ + public function removeRoles(...$roles): self { $roles = array_flatten($roles); $roles = $this->getRoles($roles); @@ -53,7 +66,13 @@ public function removeRoles(...$roles) return $this; } - public function syncRoles(...$roles) + /** + * Sync the specified roles to the model. + * + * @param mixed $roles,... + * @return self + */ + public function syncRoles(...$roles): self { $roles = array_flatten($roles); $roles = $this->getRoles($roles); @@ -63,8 +82,14 @@ public function syncRoles(...$roles) return $this; } + /** + * Get the specified roles. + * + * @param array $roles + * @return Role + */ protected function getRoles(array $roles) { - return Role::whereIn('slug', $roles)->get(); + return Shinobi::role()->whereIn('slug', $roles)->get(); } } \ No newline at end of file diff --git a/src/Concerns/HasRolesAndPermissions.php b/src/Concerns/HasRolesAndPermissions.php index c719300..5c7d81b 100644 --- a/src/Concerns/HasRolesAndPermissions.php +++ b/src/Concerns/HasRolesAndPermissions.php @@ -13,7 +13,7 @@ trait HasRolesAndPermissions * @param \Caffeinated\Shinobi\Models\Permission $permission * @return boolean */ - protected function hasPermissionThroughRole($permission) + protected function hasPermissionThroughRole($permission): bool { foreach ($permission->roles as $role) { if ($this->roles->contains($role)) { @@ -24,14 +24,14 @@ protected function hasPermissionThroughRole($permission) return false; } - protected function hasPermissionFlags() + protected function hasPermissionFlags(): bool { return (bool) (auth()->user()->roles->filter(function($role) { return ! is_null($role->special); })->count()); } - protected function hasPermissionThroughFlag() + protected function hasPermissionThroughFlag(): bool { return ! (auth()->user()->roles ->filter(function($role) { diff --git a/src/Contracts/Permission.php b/src/Contracts/Permission.php new file mode 100644 index 0000000..a0d07a7 --- /dev/null +++ b/src/Contracts/Permission.php @@ -0,0 +1,15 @@ +belongsToMany('\Caffeinated\Shinobi\Models\Role')->withTimestamps(); + return $this->belongsToMany(config('shinobi.models.role'))->withTimestamps(); } } diff --git a/src/Models/Role.php b/src/Models/Role.php index 2c53912..ca50ee7 100644 --- a/src/Models/Role.php +++ b/src/Models/Role.php @@ -4,8 +4,10 @@ use Illuminate\Database\Eloquent\Model; use Caffeinated\Shinobi\Concerns\HasPermissions; +use Caffeinated\Shinobi\Contracts\Role as RoleContract; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; -class Role extends Model +class Role extends Model implements RoleContract { use HasPermissions; @@ -28,7 +30,7 @@ class Role extends Model * * @return Model */ - public function users() + public function users(): BelongsToMany { return $this->belongsToMany(config('auth.model') ?: config('auth.providers.users.model'))->withTimestamps(); } diff --git a/src/Shinobi.php b/src/Shinobi.php index 988e2b0..4fdfddb 100644 --- a/src/Shinobi.php +++ b/src/Shinobi.php @@ -2,8 +2,6 @@ namespace Caffeinated\Shinobi; -use Caffeinated\Shinobi\Models\Role; -use Caffeinated\Shinobi\Models\Permission; use Caffeinated\Shinobi\Tactics\AssignRoleTo; use Caffeinated\Shinobi\Tactics\GivePermissionTo; use Caffeinated\Shinobi\Tactics\RevokePermissionFrom; @@ -13,21 +11,21 @@ class Shinobi /** * Fetch an instance of the Role model. * - * @return \Caffeinated\Shinobi\Models\Role + * @return Role */ public function role() { - return app()->make(Role::class); + return app()->make(config('shinobi.models.role')); } /** * Fetch an instance of the Permission model. * - * @return \Caffeinated\Shinobi\Models\Permission + * @return Permission */ public function permission() { - return app()->make(Permission::class); + return app()->make(config('shinobi.models.permission')); } /** @@ -36,7 +34,7 @@ public function permission() * @param string|array $roles * @return \Caffeinated\Shinobi\Tactic\AssignRoleTo */ - public function assign($roles) + public function assign($roles): AssignRoleTo { return new AssignRoleTo($roles); } @@ -47,7 +45,7 @@ public function assign($roles) * @param string|array $permissions * @return \Caffeinated\Shinobi\Tactic\GivePermissionTo */ - public function give($permissions) + public function give($permissions): GivePermissionTo { return new GivePermissionTo($permissions); } @@ -58,7 +56,7 @@ public function give($permissions) * @param string|array $permissions * @return \Caffeinated\Shinobi\Tactic\RevokePermissionFrom */ - public function revoke($permissions) + public function revoke($permissions): RevokePermissionFrom { return new RevokePermissionFrom($permissions); } diff --git a/src/ShinobiServiceProvider.php b/src/ShinobiServiceProvider.php index 5896898..f2f53cd 100644 --- a/src/ShinobiServiceProvider.php +++ b/src/ShinobiServiceProvider.php @@ -8,6 +8,7 @@ use Illuminate\Foundation\Application; use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider; +use Caffeinated\Shinobi\Facades\Shinobi; use Caffeinated\Shinobi\Models\Permission; class ShinobiServiceProvider extends ServiceProvider @@ -20,6 +21,7 @@ class ShinobiServiceProvider extends ServiceProvider public function boot() { $this->publishConfig(); + $this->publishMigrations(); $this->loadMigrations(); $this->registerGates(); @@ -52,7 +54,7 @@ public function register() protected function registerGates() { if (Schema::hasTable('permissions')) { - Permission::with('roles')->get()->map(function($permission) { + Shinobi::permission()->with('roles')->get()->map(function($permission) { Gate::define($permission->slug, function($user) use ($permission) { return $user->hasPermissionTo($permission); }); @@ -85,7 +87,19 @@ protected function publishConfig() { $this->publishes([ __DIR__.'/../config/shinobi.php' => config_path('shinobi.php'), - ]); + ], 'config'); + } + + /** + * Publish the migration files. + * + * @return void + */ + protected function publishMigrations() + { + $this->publishes([ + __DIR__.'/../database/migrations/' => database_path('migrations'), + ], 'migrations'); } /** @@ -95,6 +109,8 @@ protected function publishConfig() */ protected function loadMigrations() { - $this->loadMigrationsFrom(__DIR__.'/../migrations'); + if (config('shinobi.migrate', true)) { + $this->loadMigrationsFrom(__DIR__.'/../migrations'); + } } } diff --git a/src/Tactics/GivePermissionTo.php b/src/Tactics/GivePermissionTo.php index 2cb8fec..29c56b6 100644 --- a/src/Tactics/GivePermissionTo.php +++ b/src/Tactics/GivePermissionTo.php @@ -3,6 +3,7 @@ namespace Caffeinated\Shinobi\Tactics; use Illuminate\Database\Eloquent\Model; +use Caffeinated\Shinobi\Facades\Shinobi; class GivePermissionTo { @@ -21,12 +22,17 @@ public function __construct(...$permissions) $this->permissions = array_flatten($permissions); } + /** + * Give the permissions to the given user or role. + * + * @param Role|User $roleOrUser + */ public function to($roleOrUser) { if ($roleOrUser instanceof Model) { $instance = $roleOrUser; } else { - $instance = Role::where('slug', $roleOrUser)->firstOrFail(); + $instance = Shinobi::role()->where('slug', $roleOrUser)->firstOrFail(); } $instance->givePermissionTo($this->permissions); diff --git a/src/Tactics/RevokePermissionFrom.php b/src/Tactics/RevokePermissionFrom.php index d4b5cf0..4dfcc76 100644 --- a/src/Tactics/RevokePermissionFrom.php +++ b/src/Tactics/RevokePermissionFrom.php @@ -3,6 +3,7 @@ namespace Caffeinated\Shinobi\Tactics; use Illuminate\Database\Eloquent\Model; +use Caffeinated\Shinobi\Facades\Shinobi; class RevokePermissionsFrom { @@ -26,7 +27,7 @@ public function to($roleOrUser) if ($roleOrUser instanceof Model) { $instance = $roleOrUser; } else { - $instance = Role::where('slug', $roleOrUser)->firstOrFail(); + $instance = Shinobi::role()->where('slug', $roleOrUser)->firstOrFail(); } $instance->revokePermissionTo($this->permissions);