create(); $role = Role::firstOrCreate(['name' => RoleName::Administrator->value]); $user->roles()->attach($role); return $user; } function ensureManagementRoles(): void { foreach (RoleName::cases() as $role) { Role::firstOrCreate(['name' => $role->value]); } } it('restringe a gestão de utilizadores a administradores', function () { $this->actingAs(User::factory()->create()) ->get('/administracao/utilizadores') ->assertForbidden(); ensureManagementRoles(); $this->actingAs(userManagementAdministrator()) ->get('/administracao/utilizadores') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->component('admin/users/index') ->has('roles', count(RoleName::cases()))); }); it('cria uma conta verificada com perfis e associação Snipe-IT', function () { ensureManagementRoles(); $administrator = userManagementAdministrator(); $this->actingAs($administrator) ->post('/administracao/utilizadores', [ 'name' => 'Operadora de Inventário', 'email' => 'operadora@escola.pt', 'department' => 'Serviços de Informática', 'snipe_user_id' => 172, 'password' => 'temporaria-segura-2026', 'active' => true, 'roles' => [RoleName::Requester->value, RoleName::InventoryOperator->value], ]) ->assertRedirect() ->assertSessionHas('success'); $user = User::query()->where('email', 'operadora@escola.pt')->firstOrFail(); expect($user->email_verified_at)->not->toBeNull() ->and($user->snipe_user_id)->toBe(172) ->and($user->roles()->pluck('name')->sort()->values()->all())->toBe([ RoleName::InventoryOperator->value, RoleName::Requester->value, ]); $this->assertDatabaseHas('audit_logs', [ 'actor_id' => $administrator->id, 'event' => 'user.created', 'auditable_id' => $user->id, ]); }); it('atualiza dados perfis estado e palavra-passe com auditoria', function () { ensureManagementRoles(); $administrator = userManagementAdministrator(); $user = User::factory()->create(); $user->roles()->attach(Role::query()->where('name', RoleName::Requester->value)->firstOrFail()); $this->actingAs($administrator) ->put("/administracao/utilizadores/{$user->id}", [ 'name' => 'Utilizador Atualizado', 'email' => $user->email, 'department' => 'Direção', 'snipe_user_id' => 88, 'password' => 'nova-palavra-passe-2026', 'active' => false, 'roles' => [RoleName::Auditor->value], ]) ->assertRedirect() ->assertSessionHas('success'); $user->refresh(); expect($user->name)->toBe('Utilizador Atualizado') ->and($user->active)->toBeFalse() ->and($user->hasRole(RoleName::Auditor))->toBeTrue() ->and(Hash::check('nova-palavra-passe-2026', $user->password))->toBeTrue(); $this->assertDatabaseHas('audit_logs', ['event' => 'user.updated', 'auditable_id' => $user->id]); }); it('impede o administrador de remover o próprio acesso', function () { ensureManagementRoles(); $administrator = userManagementAdministrator(); $this->actingAs($administrator) ->from('/administracao/utilizadores') ->put("/administracao/utilizadores/{$administrator->id}", [ 'name' => $administrator->name, 'email' => $administrator->email, 'department' => $administrator->department, 'snipe_user_id' => null, 'password' => null, 'active' => false, 'roles' => [RoleName::Requester->value], ]) ->assertRedirect('/administracao/utilizadores') ->assertSessionHasErrors('roles'); expect($administrator->fresh()->active)->toBeTrue() ->and($administrator->hasRole(RoleName::Administrator))->toBeTrue(); });