2026-06-17 17:21:16 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Livewire;
|
|
|
|
|
|
|
|
|
|
use Livewire\Component;
|
|
|
|
|
use Livewire\Attributes\Layout;
|
|
|
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
|
use Illuminate\Support\Str;
|
2026-06-17 18:51:59 +02:00
|
|
|
use App\Models\User;
|
2026-06-17 17:21:16 +02:00
|
|
|
use Spatie\Permission\Models\Role;
|
|
|
|
|
use Spatie\Permission\Models\Permission;
|
|
|
|
|
use Spatie\Permission\PermissionRegistrar;
|
|
|
|
|
|
|
|
|
|
#[Layout('layouts.app')]
|
|
|
|
|
class RoleView extends Component
|
|
|
|
|
{
|
|
|
|
|
public Role $role;
|
|
|
|
|
public string $tab = 'ficha'; // ficha | permisos
|
2026-06-17 18:51:59 +02:00
|
|
|
public $newUserId = '';
|
2026-06-17 17:21:16 +02:00
|
|
|
|
|
|
|
|
private const PROTECTED_ROLES = ['Admin'];
|
|
|
|
|
private const CORE_PERMISSION = 'manage all';
|
|
|
|
|
|
|
|
|
|
public function mount(Role $role): void
|
|
|
|
|
{
|
2026-06-17 19:15:58 +02:00
|
|
|
abort_unless(Auth::user()?->can('manage roles'), 403);
|
2026-06-17 17:21:16 +02:00
|
|
|
$this->role = $role;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function setTab(string $tab): void
|
|
|
|
|
{
|
|
|
|
|
$this->tab = in_array($tab, ['ficha', 'permisos'], true) ? $tab : 'ficha';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function togglePermission(string $permissionName): void
|
|
|
|
|
{
|
|
|
|
|
// Admin must always keep the core permission
|
|
|
|
|
if ($this->role->name === 'Admin'
|
|
|
|
|
&& $permissionName === self::CORE_PERMISSION
|
|
|
|
|
&& $this->role->hasPermissionTo($permissionName)) {
|
|
|
|
|
$this->dispatch('notify', "El rol Admin no puede perder '" . self::CORE_PERMISSION . "'.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($this->role->hasPermissionTo($permissionName)) {
|
|
|
|
|
$this->role->revokePermissionTo($permissionName);
|
|
|
|
|
} else {
|
|
|
|
|
$this->role->givePermissionTo($permissionName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app(PermissionRegistrar::class)->forgetCachedPermissions();
|
|
|
|
|
$this->role->load('permissions');
|
|
|
|
|
$this->dispatch('notify', 'Permisos actualizados');
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-17 18:51:59 +02:00
|
|
|
public function addUser(): void
|
|
|
|
|
{
|
|
|
|
|
$this->validate(['newUserId' => 'required|exists:users,id'], [], ['newUserId' => 'usuario']);
|
|
|
|
|
|
|
|
|
|
User::findOrFail($this->newUserId)->assignRole($this->role->name);
|
|
|
|
|
$this->newUserId = '';
|
|
|
|
|
app(PermissionRegistrar::class)->forgetCachedPermissions();
|
|
|
|
|
$this->dispatch('notify', 'Usuario añadido al rol');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function removeUser(int $userId): void
|
|
|
|
|
{
|
|
|
|
|
User::findOrFail($userId)->removeRole($this->role->name);
|
|
|
|
|
app(PermissionRegistrar::class)->forgetCachedPermissions();
|
|
|
|
|
$this->dispatch('notify', 'Usuario quitado del rol');
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-17 17:44:58 +02:00
|
|
|
public function setGroup(string $group, bool $enabled): void
|
|
|
|
|
{
|
|
|
|
|
$names = Permission::where('group', $group)->pluck('name');
|
|
|
|
|
|
|
|
|
|
foreach ($names as $name) {
|
|
|
|
|
// Admin must always keep the core permission
|
|
|
|
|
if (! $enabled && $this->role->name === 'Admin' && $name === self::CORE_PERMISSION) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
$enabled ? $this->role->givePermissionTo($name) : $this->role->revokePermissionTo($name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app(PermissionRegistrar::class)->forgetCachedPermissions();
|
|
|
|
|
$this->role->load('permissions');
|
|
|
|
|
$this->dispatch('notify', $enabled ? 'Permisos del grupo activados' : 'Permisos del grupo desactivados');
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-17 17:21:16 +02:00
|
|
|
public function delete()
|
|
|
|
|
{
|
|
|
|
|
if (in_array($this->role->name, self::PROTECTED_ROLES, true)) {
|
|
|
|
|
$this->dispatch('notify', "El rol '{$this->role->name}' está protegido y no se puede borrar.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
$this->role->delete();
|
|
|
|
|
app(PermissionRegistrar::class)->forgetCachedPermissions();
|
|
|
|
|
session()->flash('message', 'Rol eliminado.');
|
|
|
|
|
|
|
|
|
|
return $this->redirect(route('admin.roles'), navigate: true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Section title for a permission name (groups by the resource / last word). */
|
|
|
|
|
private function sectionFor(string $name): string
|
|
|
|
|
{
|
|
|
|
|
if ($name === self::CORE_PERMISSION) {
|
|
|
|
|
return 'General';
|
|
|
|
|
}
|
|
|
|
|
$resource = Str::afterLast($name, ' ');
|
|
|
|
|
return Str::headline($resource ?: 'General');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function render()
|
|
|
|
|
{
|
|
|
|
|
$users = $this->role->users()
|
|
|
|
|
->orderBy('first_name')
|
|
|
|
|
->orderBy('name')
|
|
|
|
|
->get();
|
|
|
|
|
|
2026-06-17 17:32:16 +02:00
|
|
|
$order = [
|
|
|
|
|
'Proyectos', 'Fases y progreso', 'Capas y elementos', 'Inspecciones',
|
|
|
|
|
'Incidencias', 'Empresas', 'Usuarios', 'Roles', 'Informes', 'Archivos', 'General',
|
|
|
|
|
];
|
|
|
|
|
|
2026-06-17 17:21:16 +02:00
|
|
|
$grouped = Permission::orderBy('name')->get()
|
2026-06-17 17:32:16 +02:00
|
|
|
->groupBy(fn ($perm) => $perm->group ?: $this->sectionFor($perm->name))
|
|
|
|
|
->sortBy(function ($perms, $section) use ($order) {
|
|
|
|
|
$i = array_search($section, $order, true);
|
|
|
|
|
return $i === false ? 999 : $i;
|
|
|
|
|
});
|
2026-06-17 17:21:16 +02:00
|
|
|
|
2026-06-17 18:51:59 +02:00
|
|
|
$availableUsers = User::whereDoesntHave('roles', fn ($q) => $q->where('roles.id', $this->role->id))
|
|
|
|
|
->orderBy('first_name')->orderBy('name')->get();
|
|
|
|
|
|
2026-06-17 17:21:16 +02:00
|
|
|
return view('livewire.roles.role-view', [
|
2026-06-17 18:51:59 +02:00
|
|
|
'users' => $users,
|
|
|
|
|
'availableUsers' => $availableUsers,
|
|
|
|
|
'grouped' => $grouped,
|
|
|
|
|
'rolePerms' => $this->role->permissions->pluck('name')->toArray(),
|
|
|
|
|
'isProtected' => in_array($this->role->name, self::PROTECTED_ROLES, true),
|
2026-06-17 17:21:16 +02:00
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
}
|