createMock(PermissionService::class); $permissionService->expects($this->once()) ->method('userHas') ->with(9, PermissionService::PERMISSIONS_VIEW) ->willReturn(false); $policy = new PermissionAuthorizationPolicy($permissionService); $decision = $policy->authorize(PermissionAuthorizationPolicy::ABILITY_ADMIN_PERMISSIONS_VIEW, [ 'actor_user_id' => 9, ]); $this->assertForbiddenDecision($decision); } public function testAdminViewIncludesCreateCapability(): void { $permissionService = $this->permissionGatewayAllowing([ 9 => [PermissionService::PERMISSIONS_VIEW, PermissionService::PERMISSIONS_CREATE], ]); $policy = new PermissionAuthorizationPolicy($permissionService); $decision = $policy->authorize(PermissionAuthorizationPolicy::ABILITY_ADMIN_PERMISSIONS_VIEW, [ 'actor_user_id' => 9, ]); $this->assertTrue($decision->isAllowed()); $this->assertTrue((bool) ($decision->attribute('capabilities', [])['can_create_permission'] ?? false)); } public function testAdminCreateRequiresPermissionsCreatePermission(): void { $permissionService = $this->createMock(PermissionService::class); $permissionService->expects($this->once()) ->method('userHas') ->with(3, PermissionService::PERMISSIONS_CREATE) ->willReturn(false); $policy = new PermissionAuthorizationPolicy($permissionService); $decision = $policy->authorize(PermissionAuthorizationPolicy::ABILITY_ADMIN_PERMISSIONS_CREATE, [ 'actor_user_id' => 3, ]); $this->assertDeniedDecision($decision, 403, 'forbidden'); } public function testEditContextReturnsCapabilitiesAndSystemDeleteRestriction(): void { $permissionService = $this->permissionGatewayAllowing([ 5 => [ PermissionService::PERMISSIONS_VIEW, PermissionService::PERMISSIONS_UPDATE, PermissionService::PERMISSIONS_DELETE, ], ]); $policy = new PermissionAuthorizationPolicy($permissionService); $decision = $policy->authorize(PermissionAuthorizationPolicy::ABILITY_ADMIN_PERMISSIONS_EDIT_CONTEXT, [ 'actor_user_id' => 5, 'target_permission_id' => 21, 'target_is_system' => true, ]); $capabilities = $decision->attribute('capabilities', []); $this->assertTrue($decision->isAllowed()); $this->assertTrue((bool) ($capabilities['can_update_permission'] ?? false)); $this->assertFalse((bool) ($capabilities['can_delete_permission'] ?? true)); } public function testEditSubmitRequiresPermissionsUpdatePermission(): void { $permissionService = $this->permissionGatewayAllowing([ 5 => [PermissionService::PERMISSIONS_VIEW], ]); $policy = new PermissionAuthorizationPolicy($permissionService); $decision = $policy->authorize(PermissionAuthorizationPolicy::ABILITY_ADMIN_PERMISSIONS_EDIT_SUBMIT, [ 'actor_user_id' => 5, 'target_permission_id' => 21, 'target_is_system' => false, ]); $this->assertForbiddenDecision($decision); } public function testDeleteRequiresPermissionsDeletePermission(): void { $permissionService = $this->createMock(PermissionService::class); $permissionService->expects($this->once()) ->method('userHas') ->with(12, PermissionService::PERMISSIONS_DELETE) ->willReturn(false); $policy = new PermissionAuthorizationPolicy($permissionService); $decision = $policy->authorize(PermissionAuthorizationPolicy::ABILITY_ADMIN_PERMISSIONS_DELETE, [ 'actor_user_id' => 12, ]); $this->assertDeniedDecision($decision, 403, 'forbidden'); } }