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

View File

@ -6,47 +6,46 @@ use Illuminate\Support\Collection;
trait HasPermissions
{
public function can(string $permission): bool
{
return $this->hasPermission($permission);
}
public function hasPermission(string $permission): bool
{
return $this->permissions()
->where('name', $permission)
->orWhere('slug', '*')
->exists();
$allpermissions = $this->allPermissions();
if ($allpermissions->contains('slug', '*')) {
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()
{
$permissionClass = config('roles.models.permission');
$permissionTable = config('roles.table_names.permissions');
$permissionMemberTable = config('roles.table_names.permission_member');
// direct assignment
$direct = $this->morphToMany(
$permissionClass,
return $this->morphToMany(
config('roles.models.permission'),
'member',
$permissionMemberTable
config('roles.table_names.permission_member', 'permission_member')
);
if (! method_exists($this, 'roles')) {
return $direct;
}
// inherited via roles
$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
public function addPermission($permission)
{
$permission_class = config('roles.models.permission');
@ -54,14 +53,16 @@ trait HasPermissions
$permission = $permission_class::find($permission);
} elseif (is_string($permission)) {
$permission = $permission_class::where('slug', $permission)->firstOrCreate();
} elseif ($permission instanceof $permission_class) {
}
if ($permission instanceof $permission_class) {
// Already a Permission instance
} else {
throw new \InvalidArgumentException('Permission must be a string, numeric ID, or an instance of Permission.');
}
if ($permission) {
return $this->permissions()->attach($permission);
return $this->permissions()->syncWithoutDetaching($permission);
}
return false;
@ -75,7 +76,9 @@ trait HasPermissions
$permission = $permission_class::find($permission);
} elseif (is_string($permission)) {
$permission = $permission_class::where('slug', $permission)->first();
} elseif ($permission instanceof $permission_class) {
}
if ($permission instanceof $permission_class) {
// Already a Permission instance
} else {
throw new \InvalidArgumentException('Permission must be a string, numeric ID, or an instance of Permission.');
@ -93,7 +96,7 @@ trait HasPermissions
*
* @return Collection
*/
public function allPermissions(): Collection
public function allPermissions()
{
// Directly assigned permissions
$direct = $this->permissions()->get();

View File

@ -47,9 +47,9 @@ trait HasRoles
/**
* Assigns the role to the memberable
*
*
* @param int|string|Role $role
*
*
* @return $this
*/
public function assignRole(string|Role $role)
@ -58,7 +58,9 @@ trait HasRoles
$role = config('roles.models.role', \Blax\Roles\Models\Role::class)::where('slug', $role)->first();
} elseif (is_numeric($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);
} else {
throw new \InvalidArgumentException('Role must be a string, numeric ID, or an instance of Role.');
@ -69,9 +71,9 @@ trait HasRoles
/**
* Removes the role from the memberable
*
*
* @param int|string|Role $role
*
*
* @return $this
*/
public function removeRole(string|Role $role)
@ -91,9 +93,9 @@ trait HasRoles
/**
* Syncs the roles for the memberable
*
*
* @param array $roles
*
*
* @return $this
*/
public function syncRoles(array $roles)
@ -126,9 +128,9 @@ trait HasRoles
/**
* Checks if the memberable has any of the given roles
*
*
* @param array $roles
*
*
* @return bool
*/
public function hasAnyRole(array $roles): bool
@ -143,9 +145,9 @@ trait HasRoles
/**
* Checks if the memberable has all of the given roles
*
*
* @param array $roles
*
*
* @return bool
*/
public function hasAllRoles(array $roles): bool