parseIncludesString($include); $result = []; if ($this->shouldInclude(self::MODEL_INCLUDE, $includes)) { $result = $resource->jsonSerialize(); } if ($this->shouldInclude(self::MEMBERS_INCLUDE, $includes)) { $result["members"] = $this->memberService->findAll($resource->getId()); } if($this->shouldInclude(self::SUBRESOURCES_INCLUDE, $includes)) { $result["subResources"] = $this->getSubResources($resource->getId()); } return $result; } #[NoAdminRequired] public function show(int $resourceId, ?string $include): JSONResponse { return $this->handleNotFound(function () use ($resourceId, $include) { $resource = $this->service->find($resourceId); $this->denyAccessUnlessGranted(['READ'], $resource); return $this->getApiObjectFromEntity($resource, $include); }); } #[NoAdminRequired] public function create( int $organizationFolderId, string $type, string $name, ?int $parentResourceId = null, bool $active = true, bool $inheritManagers = true, // for type folder ?int $membersAclPermission = null, ?int $managersAclPermission = null, ?int $inheritedAclPermission = null, ?string $include, ): JSONResponse { return $this->handleErrors(function () use ($organizationFolderId, $type, $name, $parentResourceId, $active, $inheritManagers, $membersAclPermission, $managersAclPermission, $inheritedAclPermission, $include) { $organizationFolder = $this->organizationFolderService->find($organizationFolderId); if(!is_null($parentResourceId)) { $parentResource = $this->service->find($parentResourceId); $this->denyAccessUnlessGranted(['CREATE_SUBRESOURCE'], $parentResource); } else { $this->denyAccessUnlessGranted(['CREATE_RESOURCE'], $organizationFolder); } $resource = $this->service->create( organizationFolderId: $organizationFolder->getId(), type: $type, name: $name, parentResourceId: $parentResourceId, active: $active, inheritManagers: $inheritManagers, membersAclPermission: $membersAclPermission, managersAclPermission: $managersAclPermission, inheritedAclPermission: $inheritedAclPermission, ); return $this->getApiObjectFromEntity($resource, $include); }); } #[NoAdminRequired] public function update( int $resourceId, ?string $name = null, ?bool $active = null, ?bool $inheritManagers = null, // for type folder ?int $membersAclPermission = null, ?int $managersAclPermission = null, ?int $inheritedAclPermission = null, ?string $include, ): JSONResponse { return $this->handleErrors(function () use ($resourceId, $name, $active, $inheritManagers, $membersAclPermission, $managersAclPermission, $inheritedAclPermission, $include) { $resource = $this->service->find($resourceId); $this->denyAccessUnlessGranted(['UPDATE'], $resource); $resource = $this->service->update( id: $resourceId, name: $name, active: $active, inheritManagers: $inheritManagers, membersAclPermission: $membersAclPermission, managersAclPermission: $managersAclPermission, inheritedAclPermission: $inheritedAclPermission, ); return $this->getApiObjectFromEntity($resource, $include); }); } #[NoAdminRequired] public function subResources(int $resourceId): JSONResponse { return $this->handleNotFound(function () use ($resourceId) { return $this->getSubResources($resourceId); }); } protected function getSubResources(int $resourceId): array { $resource = $this->service->find($resourceId); $organizationFolder = $this->organizationFolderService->find($resource->getOrganizationFolderId()); $subresources = $this->service->getSubResources($resource); $result = []; if($this->authorizationService->isGranted(['MANAGE_ALL_RESOURCES'], $organizationFolder)) { /* fastpath: access to all subresources */ $result = $subresources; } else { foreach($subresources as $subresource) { // Future optimization potential 1: the following will potentially check the permissions of each of these subresources all the way up the resource tree. // As sibling resources these subresources share the same resources above them in the tree. // So if access to the parent resource is granted, all subresources with inheritManagers can be granted immediately. // For all other subresources only a check if user has direct (non-inherited) manager rights is neccessary. // Future optimization potential 2: READ permission check checks MANAGE_ALL_RESOURCES again, at this point we know this to be false, because of the fastpath. // Could be replaced with something like a READ_DIRECT (name TBD) permission check, which does not check this again. if($this->authorizationService->isGranted(['READ'], $resource)) { $result[] = $subresource; } else if($this->authorizationService->isGranted(['READ_LIMITED'], $resource)) { $result[] = $subresource->limitedJsonSerialize(); } } } return $result; } }