createMock(PermissionService::class); $permissionService->expects($this->once()) ->method('userHas') ->with(7, PermissionService::ROLES_VIEW) ->willReturn(false); $policy = new RoleAuthorizationPolicy($permissionService); $decision = $policy->authorize(RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_VIEW, [ 'actor_user_id' => 7, ]); $this->assertForbiddenDecision($decision); } public function testAdminViewIncludesCreateCapability(): void { $permissionService = $this->permissionGatewayAllowing([ 7 => [PermissionService::ROLES_VIEW, PermissionService::ROLES_CREATE], ]); $policy = new RoleAuthorizationPolicy($permissionService); $decision = $policy->authorize(RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_VIEW, [ 'actor_user_id' => 7, ]); $this->assertTrue($decision->isAllowed()); $this->assertTrue((bool) ($decision->attribute('capabilities', [])['can_create_role'] ?? false)); } public function testAdminCreateRequiresRolesCreatePermission(): void { $permissionService = $this->createMock(PermissionService::class); $permissionService->expects($this->once()) ->method('userHas') ->with(11, PermissionService::ROLES_CREATE) ->willReturn(false); $policy = new RoleAuthorizationPolicy($permissionService); $decision = $policy->authorize(RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_CREATE, [ 'actor_user_id' => 11, ]); $this->assertDeniedDecision($decision, 403, 'forbidden'); } public function testEditContextRequiresTargetRoleId(): void { $permissionService = $this->createMock(PermissionService::class); $permissionService->expects($this->never())->method('userHas'); $policy = new RoleAuthorizationPolicy($permissionService); $decision = $policy->authorize(RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_EDIT_CONTEXT, [ 'actor_user_id' => 5, 'target_role_id' => 0, ]); $this->assertDeniedDecision($decision, 403, 'forbidden'); } public function testEditContextReturnsCapabilities(): void { $permissionService = $this->permissionGatewayAllowing([ 5 => [PermissionService::ROLES_VIEW, PermissionService::ROLES_UPDATE], ]); $policy = new RoleAuthorizationPolicy($permissionService); $decision = $policy->authorize(RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_EDIT_CONTEXT, [ 'actor_user_id' => 5, 'target_role_id' => 22, ]); $capabilities = $decision->attribute('capabilities', []); $this->assertTrue($decision->isAllowed()); $this->assertTrue((bool) ($capabilities['can_edit_role'] ?? false)); $this->assertFalse((bool) ($capabilities['can_delete_role'] ?? true)); } public function testEditSubmitRequiresRolesUpdatePermission(): void { $permissionService = $this->permissionGatewayAllowing([ 5 => [PermissionService::ROLES_VIEW], ]); $policy = new RoleAuthorizationPolicy($permissionService); $decision = $policy->authorize(RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_EDIT_SUBMIT, [ 'actor_user_id' => 5, 'target_role_id' => 22, ]); $this->assertForbiddenDecision($decision); } public function testDeleteRequiresRolesDeletePermission(): void { $permissionService = $this->createMock(PermissionService::class); $permissionService->expects($this->once()) ->method('userHas') ->with(6, PermissionService::ROLES_DELETE) ->willReturn(false); $policy = new RoleAuthorizationPolicy($permissionService); $decision = $policy->authorize(RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_DELETE, [ 'actor_user_id' => 6, ]); $this->assertDeniedDecision($decision, 403, 'forbidden'); } }