Feat: implement role-based priority restrictions and permission manager
- Added `priority`-based access logic to restrict role and user management actions. - Introduced `Permission Manager` UI and routes for permission access control. - Updated `RoleService` and `AppRoleService` to include `visible` scope for priority filtering. - Enhanced seeding to assign priorities to default roles and ensure proper hierarchy. - Updated sidebar, routes, and data structure to handle new permission enums and resource segmentation. - Improved UI components to dynamically restrict visibility and actions based on role priority.
This commit is contained in:
parent
d024308c2e
commit
dcb5bd2790
@ -15,15 +15,19 @@ public function __construct(
|
|||||||
public int $id,
|
public int $id,
|
||||||
public string $name,
|
public string $name,
|
||||||
public ?ConnectedAppPermissonEnum $type,
|
public ?ConnectedAppPermissonEnum $type,
|
||||||
|
public string $resource = 'general',
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public static function fromModel(Permission $permission): self
|
public static function fromModel(Permission $permission): self
|
||||||
{
|
{
|
||||||
|
$parts = explode(':', $permission->name);
|
||||||
|
$resource = count($parts) > 1 ? $parts[0] : 'general';
|
||||||
|
|
||||||
return new self(
|
return new self(
|
||||||
id: $permission->id,
|
id: $permission->id,
|
||||||
name: $permission->name,
|
name: $permission->name,
|
||||||
type: AppPermission::type($permission->name),
|
type: AppPermission::type($permission->name),
|
||||||
|
resource: $resource,
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,15 +5,18 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Spatie\Activitylog\Models\Concerns\LogsActivity;
|
use Spatie\Activitylog\Models\Concerns\LogsActivity;
|
||||||
use Spatie\Activitylog\Support\LogOptions;
|
use Spatie\Activitylog\Support\LogOptions;
|
||||||
use Spatie\Permission\Models\Role as SpatieRole;
|
use Spatie\Permission\Models\{Permission, Role as SpatieRole};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int $priority
|
* @property int $priority
|
||||||
* @property AppRole $pivot
|
* @property AppRole $pivot
|
||||||
* @property ConnectedApp $apps
|
* @property ConnectedApp $apps
|
||||||
|
*
|
||||||
|
* @method static Builder<Role> visible()
|
||||||
*/
|
*/
|
||||||
#[Fillable(['priority'])]
|
#[Fillable(['priority'])]
|
||||||
class Role extends SpatieRole
|
class Role extends SpatieRole
|
||||||
@ -39,4 +42,28 @@ public function getActivitylogOptions(): LogOptions
|
|||||||
->logOnlyDirty()
|
->logOnlyDirty()
|
||||||
->useLogName('role_management');
|
->useLogName('role_management');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the Spatie permissions relationship to provide precise type-hinting for Larastan.
|
||||||
|
*
|
||||||
|
* @return BelongsToMany<Permission, Role>
|
||||||
|
*/
|
||||||
|
public function permissions(): BelongsToMany
|
||||||
|
{
|
||||||
|
return parent::permissions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope a query to only include roles with priority strictly greater than the logged in user's priority (lower privilege).
|
||||||
|
*/
|
||||||
|
public function scopeVisible(Builder $query): Builder
|
||||||
|
{
|
||||||
|
if (! auth()->check()) {
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
|
|
||||||
|
return $query->where('priority', '>', $userPriority);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -142,11 +142,19 @@ public function getAppsForRole(int $roleId): DataCollection
|
|||||||
#[NoDiscard]
|
#[NoDiscard]
|
||||||
public function searchAppsForSelect(string $search = ''): Collection
|
public function searchAppsForSelect(string $search = ''): Collection
|
||||||
{
|
{
|
||||||
return ConnectedApp::query()
|
$query = ConnectedApp::query()
|
||||||
->select(['id', 'name'])
|
->select(['id', 'name']);
|
||||||
->when($search, function ($query, $search): void {
|
|
||||||
$query->where('name', 'like', '%'.$search.'%');
|
if (auth()->check()) {
|
||||||
})
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
|
$query->whereHas('roles', function ($q) use ($userPriority): void {
|
||||||
|
$q->where('priority', '>', $userPriority);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query->when($search, function ($q, $search): void {
|
||||||
|
$q->where('name', 'like', '%'.$search.'%');
|
||||||
|
})
|
||||||
->limit(50) // Limit the results so the dropdown doesn't lag
|
->limit(50) // Limit the results so the dropdown doesn't lag
|
||||||
->orderBy('name')
|
->orderBy('name')
|
||||||
->get(['id', 'name']);
|
->get(['id', 'name']);
|
||||||
@ -160,7 +168,16 @@ public function searchAppsForSelect(string $search = ''): Collection
|
|||||||
#[NoDiscard]
|
#[NoDiscard]
|
||||||
public function getAllAppIds(): array
|
public function getAllAppIds(): array
|
||||||
{
|
{
|
||||||
return ConnectedApp::pluck('id')->toArray();
|
$query = ConnectedApp::query();
|
||||||
|
|
||||||
|
if (auth()->check()) {
|
||||||
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
|
$query->whereHas('roles', function ($q) use ($userPriority): void {
|
||||||
|
$q->where('priority', '>', $userPriority);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query->pluck('id')->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -241,11 +258,19 @@ public function getUsersForRole(int $roleId): DataCollection
|
|||||||
#[NoDiscard]
|
#[NoDiscard]
|
||||||
public function searchUsersForSelect(string $search = ''): DataCollection
|
public function searchUsersForSelect(string $search = ''): DataCollection
|
||||||
{
|
{
|
||||||
$users = User::query()
|
$query = User::query()
|
||||||
->select(['id', 'name'])
|
->select(['id', 'name']);
|
||||||
->when($search, function ($query, $search): void {
|
|
||||||
$query->where('name', 'like', '%'.$search.'%');
|
if (auth()->check()) {
|
||||||
})
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
|
$query->whereDoesntHave('roles', function ($q) use ($userPriority): void {
|
||||||
|
$q->where('priority', '<=', $userPriority);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$users = $query->when($search, function ($q, $search): void {
|
||||||
|
$q->where('name', 'like', '%'.$search.'%');
|
||||||
|
})
|
||||||
->limit(50)
|
->limit(50)
|
||||||
->orderBy('name')
|
->orderBy('name')
|
||||||
->get();
|
->get();
|
||||||
|
|||||||
@ -56,6 +56,7 @@ public function delete(int $id): void
|
|||||||
public function getAll(): PaginatedDataCollection
|
public function getAll(): PaginatedDataCollection
|
||||||
{
|
{
|
||||||
$roles = Role::query()
|
$roles = Role::query()
|
||||||
|
->visible()
|
||||||
->with(['apps:id,name', 'users:id,name'])
|
->with(['apps:id,name', 'users:id,name'])
|
||||||
->orderBy('id')
|
->orderBy('id')
|
||||||
->paginate();
|
->paginate();
|
||||||
@ -66,6 +67,7 @@ public function getAll(): PaginatedDataCollection
|
|||||||
public function searchRolesForSelect(string $search = ''): Collection
|
public function searchRolesForSelect(string $search = ''): Collection
|
||||||
{
|
{
|
||||||
return Role::query()
|
return Role::query()
|
||||||
|
->visible()
|
||||||
->when('' !== $search, fn ($query) => $query->where('name', 'like', "%{$search}%"))
|
->when('' !== $search, fn ($query) => $query->where('name', 'like', "%{$search}%"))
|
||||||
->select('id', 'name')
|
->select('id', 'name')
|
||||||
->get();
|
->get();
|
||||||
@ -73,7 +75,7 @@ public function searchRolesForSelect(string $search = ''): Collection
|
|||||||
|
|
||||||
public function getAllRoleIds(): array
|
public function getAllRoleIds(): array
|
||||||
{
|
{
|
||||||
return Role::query()->pluck('id')->toArray();
|
return Role::query()->visible()->pluck('id')->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,6 +94,7 @@ public function getPermissionsGroupedByRole(array $roleIds): ?DataCollection
|
|||||||
}
|
}
|
||||||
|
|
||||||
$roles = Role::query()
|
$roles = Role::query()
|
||||||
|
->visible()
|
||||||
->with('permissions:id,name')
|
->with('permissions:id,name')
|
||||||
->whereIn('id', $roleIds)
|
->whereIn('id', $roleIds)
|
||||||
->get(['id', 'name', 'priority']);
|
->get(['id', 'name', 'priority']);
|
||||||
|
|||||||
@ -25,7 +25,7 @@ public function getAll(): PaginatedDataCollection
|
|||||||
{
|
{
|
||||||
$users = User::query()
|
$users = User::query()
|
||||||
->with([
|
->with([
|
||||||
'roles:id,name',
|
'roles:id,name,priority',
|
||||||
'roles.apps:id,name',
|
'roles.apps:id,name',
|
||||||
'roles.permissions:id,name',
|
'roles.permissions:id,name',
|
||||||
'restrictedPermissions',
|
'restrictedPermissions',
|
||||||
@ -64,7 +64,19 @@ public function assignRoles(int $userId, array $roleIds): void
|
|||||||
|
|
||||||
DB::transaction(function () use ($userId, $roleIds): void {
|
DB::transaction(function () use ($userId, $roleIds): void {
|
||||||
$user = User::query()->findOrFail($userId);
|
$user = User::query()->findOrFail($userId);
|
||||||
$user->syncRoles($roleIds);
|
|
||||||
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
|
|
||||||
|
// Get user's existing roles that have priority <= $userPriority (which are forbidden to the logged in user)
|
||||||
|
$forbiddenRoleIds = $user->roles()
|
||||||
|
->where('priority', '<=', $userPriority)
|
||||||
|
->pluck('id')
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
// Merge them with the newly assigned roles so they are preserved
|
||||||
|
$mergedRoleIds = array_values(array_unique(array_merge($forbiddenRoleIds, $roleIds)));
|
||||||
|
|
||||||
|
$user->syncRoles($mergedRoleIds);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +123,16 @@ public function delete(int $id): void
|
|||||||
}
|
}
|
||||||
|
|
||||||
DB::transaction(function () use ($id): void {
|
DB::transaction(function () use ($id): void {
|
||||||
User::query()->findOrFail($id)->delete();
|
$user = User::query()->findOrFail($id);
|
||||||
|
|
||||||
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
|
$targetUserMinPriority = $user->roles()->min('priority') ?? 999999;
|
||||||
|
|
||||||
|
if ($targetUserMinPriority <= $userPriority) {
|
||||||
|
abort(403, 'Unauthorized to delete this user due to role priority hierarchy.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->delete();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,8 +15,10 @@ class DefaultRoleWithPermissionSeeder extends Seeder
|
|||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
$role = Role::findOrCreate(DefaultUserRole::Admin->value);
|
$role = Role::findOrCreate(DefaultUserRole::Admin->value);
|
||||||
|
$role->update(['priority' => 0]);
|
||||||
$role->givePermissionTo(Permission::all());
|
$role->givePermissionTo(Permission::all());
|
||||||
$role = Role::findOrCreate(DefaultUserRole::User->value);
|
$role = Role::findOrCreate(DefaultUserRole::User->value);
|
||||||
|
$role->update(['priority' => 100]);
|
||||||
$this->syncUserPermissions($role);
|
$this->syncUserPermissions($role);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ public function run(): void
|
|||||||
$allEnums = $enumExtractor->extract();
|
$allEnums = $enumExtractor->extract();
|
||||||
foreach ($allEnums as $enumCases) {
|
foreach ($allEnums as $enumCases) {
|
||||||
foreach ($enumCases as $case) {
|
foreach ($enumCases as $case) {
|
||||||
Permission::create(['name' => $case->value]);
|
Permission::findOrCreate($case->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use App\Data\Ui\Sidebar\NavItemData;
|
use App\Data\Ui\Sidebar\NavItemData;
|
||||||
use App\Data\Ui\Sidebar\NavSubItemData;
|
use App\Data\Ui\Sidebar\NavSubItemData;
|
||||||
use App\Enums\Permissions\{AppPermissionEnum, ConnectionProviderPermissionEnum, ProfilePermissionEnum, RoleAndAppsPermissionEnum, SecurityPermissionEnum, UserPermissionEnum};
|
use App\Enums\Permissions\{AppPermissionEnum, ConnectionProviderPermissionEnum, ProfilePermissionEnum, RoleAndAppsPermissionEnum, SecurityPermissionEnum, UserPermissionEnum, PermissionPermissionEnum};
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Spatie\LaravelData\DataCollection;
|
use Spatie\LaravelData\DataCollection;
|
||||||
|
|
||||||
@ -65,6 +65,12 @@ public function navItems(): DataCollection
|
|||||||
active_pattern: 'access-manager.roles-and-apps.*',
|
active_pattern: 'access-manager.roles-and-apps.*',
|
||||||
permission: RoleAndAppsPermissionEnum::Access
|
permission: RoleAndAppsPermissionEnum::Access
|
||||||
),
|
),
|
||||||
|
new NavSubItemData(
|
||||||
|
label: 'Permission Manager',
|
||||||
|
route: 'access-manager.permissions.index',
|
||||||
|
active_pattern: 'access-manager.permissions.*',
|
||||||
|
permission: PermissionPermissionEnum::Access
|
||||||
|
),
|
||||||
new NavSubItemData(
|
new NavSubItemData(
|
||||||
label: 'Users',
|
label: 'Users',
|
||||||
route: 'access-manager.users.index',
|
route: 'access-manager.users.index',
|
||||||
|
|||||||
@ -83,7 +83,15 @@ public function openCreateModal(): void
|
|||||||
|
|
||||||
public function save(): void
|
public function save(): void
|
||||||
{
|
{
|
||||||
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
|
|
||||||
$this->form->validate();
|
$this->form->validate();
|
||||||
|
|
||||||
|
if ((int) $this->form->priority <= $userPriority) {
|
||||||
|
$this->addError('form.priority', 'The priority must be greater than your own highest role priority (' . $userPriority . ').');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$this->attempt(
|
$this->attempt(
|
||||||
action: function (): void {
|
action: function (): void {
|
||||||
$role = $this->roleService->create(new CreateRoleData(
|
$role = $this->roleService->create(new CreateRoleData(
|
||||||
|
|||||||
@ -64,9 +64,14 @@ public function boot(AppRoleService $appRoleService, RoleService $roleService):
|
|||||||
|
|
||||||
public function mount(int $id): void
|
public function mount(int $id): void
|
||||||
{
|
{
|
||||||
|
$role = Role::query()->findOrFail($id);
|
||||||
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
|
if ($role->priority <= $userPriority) {
|
||||||
|
abort(403, 'Unauthorized access to this role.');
|
||||||
|
}
|
||||||
|
|
||||||
$this->attempt(
|
$this->attempt(
|
||||||
action: function () use ($id): void {
|
action: function () use ($role): void {
|
||||||
$role = Role::query()->findOrFail($id);
|
|
||||||
$this->roleId = $role->id;
|
$this->roleId = $role->id;
|
||||||
$this->roleName = $role->name;
|
$this->roleName = $role->name;
|
||||||
$this->rolePriority = $role->priority;
|
$this->rolePriority = $role->priority;
|
||||||
@ -277,8 +282,12 @@ public function openEditPriorityModal(): void
|
|||||||
|
|
||||||
public function savePriority(): void
|
public function savePriority(): void
|
||||||
{
|
{
|
||||||
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
|
|
||||||
$this->validate([
|
$this->validate([
|
||||||
'newPriority' => 'required|integer|min:0',
|
'newPriority' => 'required|integer|min:' . ($userPriority + 1),
|
||||||
|
], [
|
||||||
|
'newPriority.min' => 'The priority must be greater than your own highest role priority (' . $userPriority . ').',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->attempt(
|
$this->attempt(
|
||||||
|
|||||||
@ -68,10 +68,18 @@ public function openAssignRolesModal(int $userId): void
|
|||||||
{
|
{
|
||||||
$this->attempt(
|
$this->attempt(
|
||||||
action: function () use ($userId) {
|
action: function () use ($userId) {
|
||||||
|
$user = User::findOrFail($userId);
|
||||||
|
|
||||||
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
|
$targetUserMinPriority = $user->roles()->min('priority') ?? 999999;
|
||||||
|
if ($targetUserMinPriority <= $userPriority) {
|
||||||
|
abort(403, 'Unauthorized to manage this user.');
|
||||||
|
}
|
||||||
|
|
||||||
$this->currentUserId = $userId;
|
$this->currentUserId = $userId;
|
||||||
$this->form->reset();
|
$this->form->reset();
|
||||||
$this->searchRoles();
|
$this->searchRoles();
|
||||||
$this->form->roleIds = User::findOrFail($userId)->roles()->pluck('id')->toArray();
|
$this->form->roleIds = $user->roles()->pluck('id')->toArray();
|
||||||
$this->hydratePermissionInForm();
|
$this->hydratePermissionInForm();
|
||||||
$this->showAssignRolesModal = true;
|
$this->showAssignRolesModal = true;
|
||||||
},
|
},
|
||||||
@ -213,8 +221,13 @@ public function saveRoles(): void
|
|||||||
|
|
||||||
@scope('cell_roles', $row)
|
@scope('cell_roles', $row)
|
||||||
<div class="flex flex-wrap gap-1">
|
<div class="flex flex-wrap gap-1">
|
||||||
|
@php
|
||||||
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
|
@endphp
|
||||||
@foreach($row->roles as $role)
|
@foreach($row->roles as $role)
|
||||||
<x-mary-badge class="badge-soft badge-neutral" :value="ucfirst($role->name)"/>
|
@if($role->priority > $userPriority)
|
||||||
|
<x-mary-badge class="badge-soft badge-neutral" :value="ucfirst($role->name)"/>
|
||||||
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
@endscope
|
@endscope
|
||||||
@ -223,9 +236,10 @@ public function saveRoles(): void
|
|||||||
<div class="flex flex-wrap gap-1">
|
<div class="flex flex-wrap gap-1">
|
||||||
@php
|
@php
|
||||||
$displayedPermissions = [];
|
$displayedPermissions = [];
|
||||||
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
@endphp
|
@endphp
|
||||||
@foreach($row->roles as $role)
|
@foreach($row->roles as $role)
|
||||||
@if($role->permissions)
|
@if($role->priority > $userPriority && $role->permissions)
|
||||||
@foreach($role->permissions as $permission)
|
@foreach($role->permissions as $permission)
|
||||||
@if(!in_array($permission->id, $displayedPermissions))
|
@if(!in_array($permission->id, $displayedPermissions))
|
||||||
@php
|
@php
|
||||||
@ -247,8 +261,11 @@ public function saveRoles(): void
|
|||||||
|
|
||||||
@scope('cell_apps', $row)
|
@scope('cell_apps', $row)
|
||||||
<div class="flex flex-wrap gap-1">
|
<div class="flex flex-wrap gap-1">
|
||||||
|
@php
|
||||||
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
|
@endphp
|
||||||
@foreach($row->roles as $role)
|
@foreach($row->roles as $role)
|
||||||
@if($role->apps)
|
@if($role->priority > $userPriority && $role->apps)
|
||||||
@foreach ($role->apps as $app)
|
@foreach ($role->apps as $app)
|
||||||
<x-mary-badge class="badge-soft badge-secondary" :value="$app->appName"/>
|
<x-mary-badge class="badge-soft badge-secondary" :value="$app->appName"/>
|
||||||
@endforeach
|
@endforeach
|
||||||
@ -258,23 +275,30 @@ public function saveRoles(): void
|
|||||||
@endscope
|
@endscope
|
||||||
|
|
||||||
@scope('actions', $row)
|
@scope('actions', $row)
|
||||||
<div class="flex gap-1">
|
@php
|
||||||
<x-mary-button
|
$userPriority = auth()->user()?->roles()->min('priority') ?? 999999;
|
||||||
icon="lucide.shield-plus"
|
$rowMinPriority = collect($row->roles)->min('priority') ?? 999999;
|
||||||
wire:click="openAssignRolesModal({{ $row->id }})"
|
$isManageable = $rowMinPriority > $userPriority;
|
||||||
tooltip="Manage roles"
|
@endphp
|
||||||
class="btn-sm btn-circle btn-soft"
|
@if($isManageable)
|
||||||
spinner="openAssignRolesModal({{ $row->id }})"
|
<div class="flex gap-1">
|
||||||
/>
|
<x-mary-button
|
||||||
<x-mary-button
|
icon="lucide.shield-plus"
|
||||||
icon="lucide.trash"
|
wire:click="openAssignRolesModal({{ $row->id }})"
|
||||||
wire:click="requireConfirmation('delete', {{ $row->id }});"
|
tooltip="Manage roles"
|
||||||
spinner="requireConfirmation('delete', {{ $row->id }});"
|
class="btn-sm btn-circle btn-soft"
|
||||||
variant="danger"
|
spinner="openAssignRolesModal({{ $row->id }})"
|
||||||
:tooltip="__('Delete user')"
|
/>
|
||||||
class="btn-sm btn-circle btn-error btn-soft"
|
<x-mary-button
|
||||||
/>
|
icon="lucide.trash"
|
||||||
</div>
|
wire:click="requireConfirmation('delete', {{ $row->id }});"
|
||||||
|
spinner="requireConfirmation('delete', {{ $row->id }});"
|
||||||
|
variant="danger"
|
||||||
|
:tooltip="__('Delete user')"
|
||||||
|
class="btn-sm btn-circle btn-error btn-soft"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
@endscope
|
@endscope
|
||||||
</x-mary-table>
|
</x-mary-table>
|
||||||
</x-shared.card>
|
</x-shared.card>
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use App\Enums\DefaultUserRole;
|
use App\Enums\DefaultUserRole;
|
||||||
use App\Enums\Permissions\{AppPermissionEnum, ConnectionProviderPermissionEnum, RoleAndAppsPermissionEnum, UserPermissionEnum};
|
use App\Enums\Permissions\{AppPermissionEnum, ConnectionProviderPermissionEnum, PermissionPermissionEnum, RoleAndAppsPermissionEnum, UserPermissionEnum};
|
||||||
use App\Http\Controllers\ResolveDashboardRouteController;
|
use App\Http\Controllers\ResolveDashboardRouteController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Spatie\Permission\Middleware\{PermissionMiddleware, RoleMiddleware};
|
use Spatie\Permission\Middleware\{PermissionMiddleware, RoleMiddleware};
|
||||||
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
Route::group(['middleware' => ['auth', 'verified']], function (): void {
|
Route::group(['middleware' => ['auth', 'verified']], function (): void {
|
||||||
Route::get('dashboard', ResolveDashboardRouteController::class)->name('dashboard');
|
Route::get('dashboard', ResolveDashboardRouteController::class)->name('dashboard');
|
||||||
|
|
||||||
Route::prefix('dashboard')->name('dashboard.')->group(function (): void {
|
Route::prefix('dashboard')->name('dashboard.')->group(function (): void {
|
||||||
Route::livewire('/user', 'pages::dashboards.user')
|
Route::livewire('/user', 'pages::dashboards.user')
|
||||||
->middleware(RoleMiddleware::using(DefaultUserRole::User))
|
->middleware(RoleMiddleware::using(DefaultUserRole::User))
|
||||||
@ -34,6 +35,12 @@
|
|||||||
->group(function (): void {
|
->group(function (): void {
|
||||||
Route::livewire('users', 'pages::access-manager.users.index')->name('index');
|
Route::livewire('users', 'pages::access-manager.users.index')->name('index');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::prefix('permissions')->name('permissions.')
|
||||||
|
->middleware(PermissionMiddleware::using(PermissionPermissionEnum::Access))
|
||||||
|
->group(function (): void {
|
||||||
|
Route::livewire('/', 'pages::access-manager.permissions.index')->name('index');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::prefix('apps')->name('apps.')->group(function (): void {
|
Route::prefix('apps')->name('apps.')->group(function (): void {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user