IBF hasRoles

This commit is contained in:
a6a2f5842 2025-06-19 14:45:06 +02:00
parent d9bdc10f78
commit dd2ac01cdb
3 changed files with 54 additions and 51 deletions

View File

@ -2,10 +2,13 @@
namespace Blax\Roles\Models; namespace Blax\Roles\Models;
use Blax\Roles\Traits\HasPermissions;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class Role extends Model class Role extends Model
{ {
use HasPermissions;
protected $fillable = [ protected $fillable = [
'parent_id', 'parent_id',
'name', 'name',
@ -25,11 +28,6 @@ class Role extends Model
return $this->hasMany(RoleMember::class, 'role_id', 'id'); return $this->hasMany(RoleMember::class, 'role_id', 'id');
} }
public function permissions()
{
return $this->hasMany(Permission::class, 'role_id', 'id');
}
public function parent() public function parent()
{ {
return $this->hasOne(Role::class, 'id', 'parent_id'); return $this->hasOne(Role::class, 'id', 'parent_id');

View File

@ -6,47 +6,46 @@ use Illuminate\Support\Collection;
trait HasPermissions trait HasPermissions
{ {
public function can(string $permission): bool
{
return $this->hasPermission($permission);
}
public function hasPermission(string $permission): bool public function hasPermission(string $permission): bool
{ {
return $this->permissions() $allpermissions = $this->allPermissions();
->where('name', $permission)
->orWhere('slug', '*') if ($allpermissions->contains('slug', '*')) {
->exists(); return true; // If any permission is '*', all permissions are granted
}
return $allpermissions->contains(function ($perm) use ($permission) {
return $perm->slug === $permission || $perm->name === $permission;
});
}
public function rolePermissions()
{
return $this->hasManyThrough(
config('roles.models.permission'),
config('roles.models.role_member'),
'member_id',
'id',
'id',
'role_id'
);
} }
public function permissions() public function permissions()
{ {
$permissionClass = config('roles.models.permission'); return $this->morphToMany(
$permissionTable = config('roles.table_names.permissions'); config('roles.models.permission'),
$permissionMemberTable = config('roles.table_names.permission_member');
// direct assignment
$direct = $this->morphToMany(
$permissionClass,
'member', 'member',
$permissionMemberTable config('roles.table_names.permission_member', 'permission_member')
); );
if (! method_exists($this, 'roles')) {
return $direct;
} }
// inherited via roles public function addPermission($permission)
$permissionRoleTable = config('roles.table_names.permission_role');
$roleMemberTable = config('roles.table_names.role_member');
$memberType = $this->getMorphClass();
$viaRoles = $permissionClass::query()
->select("$permissionTable.*")
->join($permissionRoleTable, "$permissionTable.id", '=', "$permissionRoleTable.permission_id")
->join($roleMemberTable, "$permissionRoleTable.role_id", '=', "$roleMemberTable.role_id")
->where("$roleMemberTable.member_id", $this->getKey())
->where("$roleMemberTable.member_type", $memberType);
return $direct->union($viaRoles);
}
public function addPermission($permission): bool
{ {
$permission_class = config('roles.models.permission'); $permission_class = config('roles.models.permission');
@ -54,14 +53,16 @@ trait HasPermissions
$permission = $permission_class::find($permission); $permission = $permission_class::find($permission);
} elseif (is_string($permission)) { } elseif (is_string($permission)) {
$permission = $permission_class::where('slug', $permission)->firstOrCreate(); $permission = $permission_class::where('slug', $permission)->firstOrCreate();
} elseif ($permission instanceof $permission_class) { }
if ($permission instanceof $permission_class) {
// Already a Permission instance // Already a Permission instance
} else { } else {
throw new \InvalidArgumentException('Permission must be a string, numeric ID, or an instance of Permission.'); throw new \InvalidArgumentException('Permission must be a string, numeric ID, or an instance of Permission.');
} }
if ($permission) { if ($permission) {
return $this->permissions()->attach($permission); return $this->permissions()->syncWithoutDetaching($permission);
} }
return false; return false;
@ -75,7 +76,9 @@ trait HasPermissions
$permission = $permission_class::find($permission); $permission = $permission_class::find($permission);
} elseif (is_string($permission)) { } elseif (is_string($permission)) {
$permission = $permission_class::where('slug', $permission)->first(); $permission = $permission_class::where('slug', $permission)->first();
} elseif ($permission instanceof $permission_class) { }
if ($permission instanceof $permission_class) {
// Already a Permission instance // Already a Permission instance
} else { } else {
throw new \InvalidArgumentException('Permission must be a string, numeric ID, or an instance of Permission.'); throw new \InvalidArgumentException('Permission must be a string, numeric ID, or an instance of Permission.');
@ -93,7 +96,7 @@ trait HasPermissions
* *
* @return Collection * @return Collection
*/ */
public function allPermissions(): Collection public function allPermissions()
{ {
// Directly assigned permissions // Directly assigned permissions
$direct = $this->permissions()->get(); $direct = $this->permissions()->get();

View File

@ -58,7 +58,9 @@ trait HasRoles
$role = config('roles.models.role', \Blax\Roles\Models\Role::class)::where('slug', $role)->first(); $role = config('roles.models.role', \Blax\Roles\Models\Role::class)::where('slug', $role)->first();
} elseif (is_numeric($role)) { } elseif (is_numeric($role)) {
$role = config('roles.models.role', \Blax\Roles\Models\Role::class)::find($role); $role = config('roles.models.role', \Blax\Roles\Models\Role::class)::find($role);
} elseif ($role instanceof Role) { }
if ($role instanceof Role) {
$this->roles()->attach($role); $this->roles()->attach($role);
} else { } else {
throw new \InvalidArgumentException('Role must be a string, numeric ID, or an instance of Role.'); throw new \InvalidArgumentException('Role must be a string, numeric ID, or an instance of Role.');