diff --git a/lib/Db/OrganizationFolderMember.php b/lib/Db/OrganizationFolderMember.php new file mode 100644 index 0000000..24c12d0 --- /dev/null +++ b/lib/Db/OrganizationFolderMember.php @@ -0,0 +1,81 @@ +addType('organizationFolderId','integer'); + $this->addType('permissionLevel','integer'); + $this->addType('principalType','integer'); + $this->addType('createdTimestamp','integer'); + $this->addType('lastUpdatedTimestamp','integer'); + } + + public function getPrincipal(): Principal { + return new Principal(PrincipalType::from($this->principalType), $this->principalId); + } + + public function setPrincipal(Principal $principal) { + $principalType = $principal->getType(); + if($principalType === PrincipalType::GROUP || $principalType === PrincipalType::ROLE) { + $this->setPrincipalType($principalType->value); + } else { + throw new \Exception("individual users are not allowed as organization folder members"); + } + + $this->setPrincipalId($principal->getId()); + } + + public function setPermissionLevel(int $permissionLevel) { + if($permissionLevel >= 1 && $permissionLevel <= 3) { + if ($permissionLevel === $this->permissionLevel) { + // no change + return; + } + + $this->markFieldUpdated("permissionLevel"); + $this->permissionLevel = $permissionLevel; + } else { + throw new \Exception("invalid organization folder member permission level"); + } + } + + public function jsonSerialize(): array { + return [ + 'id' => $this->id, + 'organizationFolderId' => $this->organizationFolderId, + 'permissionLevel' => $this->permissionLevel, + 'principal' => $this->getPrincipal(), + 'createdTimestamp' => $this->createdTimestamp, + 'lastUpdatedTimestamp' => $this->lastUpdatedTimestamp, + ]; + } + + public function tableSerialize(?array $params = null): array { + return [ + 'Id' => $this->id, + 'Organization Folder Id' => $this->organizationFolderId, + 'Permission Level' => OrganizationFolderMemberPermissionLevel::from($this->permissionLevel)->name, + 'Principal Type' => PrincipalType::from($this->principalType)->name, + 'Principal Id' => $this->principalId, + 'Created' => $this->createdTimestamp, + 'LastUpdated' => $this->lastUpdatedTimestamp, + ]; + } +} diff --git a/lib/Db/OrganizationFolderMemberMapper.php b/lib/Db/OrganizationFolderMemberMapper.php new file mode 100644 index 0000000..11f3a86 --- /dev/null +++ b/lib/Db/OrganizationFolderMemberMapper.php @@ -0,0 +1,72 @@ +db->getQueryBuilder(); + + $qb->select('*') + ->from(self::ORGANIZATIONFOLDER_MEMBERS_TABLE) + ->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT))); + + return $this->findEntity($qb); + } + + /** + * @param int $organizationFolderId + * @param array{permissionLevel: int, principalType: int} $filters + * @return array + * @psalm-return OrganizationFolderMember[] + */ + public function findAll(int $organizationFolderId, array $filters = []): array { + /* @var $qb IQueryBuilder */ + $qb = $this->db->getQueryBuilder(); + + $qb->select('*') + ->from(self::ORGANIZATIONFOLDER_MEMBERS_TABLE) + ->where($qb->expr()->eq('organization_folder_id', $qb->createNamedParameter($organizationFolderId, IQueryBuilder::PARAM_INT))); + + if(isset($filters["permissionLevel"])) { + $qb->andWhere($qb->expr()->eq('permission_level', $qb->createNamedParameter($filters["permissionLevel"], IQueryBuilder::PARAM_INT))); + } + + if(isset($filters["principalType"])) { + $qb->andWhere($qb->expr()->eq('principal_type', $qb->createNamedParameter($filters["principalType"], IQueryBuilder::PARAM_INT))); + } + + return $this->findEntities($qb); + } + + public function exists(int $organizationFolderId, int $principalType, string $principalId): bool { + /* @var $qb IQueryBuilder */ + $qb = $this->db->getQueryBuilder(); + + $qb->select($qb->createFunction('COUNT(1)')) + ->from(self::ORGANIZATIONFOLDER_MEMBERS_TABLE) + ->where($qb->expr()->eq('organization_folder_id', $qb->createNamedParameter($organizationFolderId, IQueryBuilder::PARAM_INT))) + ->andWhere($qb->expr()->eq('principal_type', $qb->createNamedParameter($principalType, IQueryBuilder::PARAM_INT))) + ->andWhere($qb->expr()->eq('principal_id', $qb->createNamedParameter($principalId))); + + return $qb->executeQuery()->fetch()["COUNT(1)"] === 1; + } +} \ No newline at end of file diff --git a/lib/Enum/OrganizationFolderMemberPermissionLevel.php b/lib/Enum/OrganizationFolderMemberPermissionLevel.php new file mode 100644 index 0000000..67ca95a --- /dev/null +++ b/lib/Enum/OrganizationFolderMemberPermissionLevel.php @@ -0,0 +1,11 @@ + $id]); + } +} \ No newline at end of file diff --git a/lib/Service/OrganizationFolderMemberService.php b/lib/Service/OrganizationFolderMemberService.php new file mode 100644 index 0000000..1401bc1 --- /dev/null +++ b/lib/Service/OrganizationFolderMemberService.php @@ -0,0 +1,129 @@ + $filters['permissionLevel']?->value ?: null, + "principalType" => $filters['principalType']?->value ?: null, + ]; + + return $this->mapper->findAll($organizationFolderId, $mapperFilters); + } + + /** + * @throws OrganizationFolderMemberNotFound + */ + + private function handleException(Exception $e): void { + if ($e instanceof DoesNotExistException || + $e instanceof MultipleObjectsReturnedException) { + throw new OrganizationFolderMemberNotFound($e->getMessage()); + } else { + throw $e; + } + } + + /** + * @param int $id + * @psalm-param int $id + * @throws OrganizationFolderMemberNotFound + */ + public function find(int $id): OrganizationFolderMember { + try { + return $this->mapper->find($id); + } catch (Exception $e) { + $this->handleException($e); + } + } + + public function create( + int $organizationFolderId, + OrganizationFolderMemberPermissionLevel $permissionLevel, + Principal $principal, + ): OrganizationFolderMember { + $organizationFolder = $this->organizationFolderService->find($organizationFolderId); + + $member = new OrganizationFolderMember(); + + $member->setOrganizationFolderId($organizationFolder->getId()); + $member->setPermissionLevel($permissionLevel->value); + $member->setPrincipal($principal); + + $creationTime = time(); + $member->setCreatedTimestamp($creationTime); + $member->setLastUpdatedTimestamp($creationTime); + + $member = $this->mapper->insert($member); + + $this->organizationFolderService->applyPermissions($organizationFolder->getId()); + + return $member; + } + + public function update(int $id, ?OrganizationFolderMemberPermissionLevel $permissionLevel = null, ?Principal $principal = null): OrganizationFolderMember { + try { + $member = $this->mapper->find($id); + + if(isset($permissionLevel)) { + $member->setPermissionLevel($permissionLevel->value); + } + + if(isset($principal)) { + $member->setPrincipal($principal); + } + + if(count($member->getUpdatedFields()) > 0) { + $member->setLastUpdatedTimestamp(time()); + + $member = $this->mapper->update($member); + } + + $this->organizationFolderService->applyPermissions($member->getOrganizationFolderId()); + + return $member; + } catch (Exception $e) { + $this->handleException($e); + } + } + + public function delete(int $id): OrganizationFolderMember { + try { + $member = $this->mapper->find($id); + + $this->mapper->delete($member); + + $this->organizationFolderService->applyPermissions($member->getOrganizationFolderId()); + + return $member; + } catch (Exception $e) { + $this->handleException($e); + } + } +} \ No newline at end of file