From af661c5c260177983ecb1bb8cb190b18bbce2c30 Mon Sep 17 00:00:00 2001 From: Jonathan Treffler Date: Wed, 30 Oct 2024 01:51:48 +0100 Subject: [PATCH] ensure resource name is unique --- lib/Db/ResourceMapper.php | 23 +++++++++++-- lib/Errors/ResourceNameNotUnique.php | 9 +++++ lib/Errors/ResourceNotFound.php | 9 +++++ lib/Service/ResourceService.php | 50 +++++++++++++++++++--------- 4 files changed, 74 insertions(+), 17 deletions(-) create mode 100644 lib/Errors/ResourceNameNotUnique.php create mode 100644 lib/Errors/ResourceNotFound.php diff --git a/lib/Db/ResourceMapper.php b/lib/Db/ResourceMapper.php index a21be76..a74c2a7 100644 --- a/lib/Db/ResourceMapper.php +++ b/lib/Db/ResourceMapper.php @@ -17,7 +17,7 @@ class ResourceMapper extends QBMapper { public const RESOURCES_TABLE = "organizationfolders_resources"; public const FOLDER_RESOURCES_TABLE = "organizationfolders_folder_resources"; - private const updateableResourceProperties = ["parentResource", "active", "lastUpdatedTimestamp"]; + private const updateableResourceProperties = ["parentResource", "active", "name", "lastUpdatedTimestamp"]; private const updateableFolderResourceProperties = ["membersAclPermission", "managersAclPermission", "inheritedAclPermission"]; public function __construct(IDBConnection $db) { @@ -75,6 +75,25 @@ class ResourceMapper extends QBMapper { return $this->findEntities($qb); } + public function existsWithName(int $organizationFolderId, ?int $parentResourceId, string $name): bool { + /* @var $qb IQueryBuilder */ + $qb = $this->db->getQueryBuilder(); + + $qb->select($qb->createFunction('COUNT(1)')) + ->from(self::RESOURCES_TABLE) + ->where($qb->expr()->eq('organization_folder_id', $qb->createNamedParameter($organizationFolderId, IQueryBuilder::PARAM_INT))); + + if(is_null($parentResourceId)) { + $qb->andWhere($qb->expr()->isNull('parent_resource')); + } else { + $qb->andWhere($qb->expr()->eq('parent_resource', $qb->createNamedParameter($parentResourceId, IQueryBuilder::PARAM_INT))); + } + + $qb->andWhere($qb->expr()->eq('name', $qb->createNamedParameter($name, IQueryBuilder::PARAM_STR))); + + return $qb->executeQuery()->fetch()["COUNT(1)"] === 1; + } + /** * Creates a new entry in the db from an entity * @@ -87,7 +106,7 @@ class ResourceMapper extends QBMapper { */ public function insert(Entity $entity): Entity { $setProperties = array_keys($entity->getUpdatedFields()); - $setResourceProperties = array_intersect(["id", ...self::updateableResourceProperties], $setProperties); + $setResourceProperties = ["type", "organizationFolderId", ...array_intersect(["id", ...self::updateableResourceProperties], $setProperties)]; if($entity->getType() === "folder") { $typeSpecificTable = self::FOLDER_RESOURCES_TABLE; diff --git a/lib/Errors/ResourceNameNotUnique.php b/lib/Errors/ResourceNameNotUnique.php new file mode 100644 index 0000000..b5bcf25 --- /dev/null +++ b/lib/Errors/ResourceNameNotUnique.php @@ -0,0 +1,9 @@ + $id]); + } +} \ No newline at end of file diff --git a/lib/Service/ResourceService.php b/lib/Service/ResourceService.php index dce805d..10c15da 100644 --- a/lib/Service/ResourceService.php +++ b/lib/Service/ResourceService.php @@ -12,6 +12,7 @@ use OCA\OrganizationFolders\Db\FolderResource; use OCA\OrganizationFolders\Db\ResourceMapper; use OCA\OrganizationFolders\Errors\InvalidResourceType; use OCA\OrganizationFolders\Errors\ResourceNotFound; +use OCA\OrganizationFolders\Errors\ResourceNameNotUnique; class ResourceService { public function __construct( @@ -19,6 +20,10 @@ class ResourceService { ) { } + public function findAll(int $groupfolderId, int $parentResourceId = null) { + return $this->mapper->findAll($groupfolderId, $parentResourceId); + } + private function handleException(Exception $e, int $id): void { if ($e instanceof DoesNotExistException || $e instanceof MultipleObjectsReturnedException) { @@ -40,6 +45,7 @@ class ResourceService { public function create( string $type, int $organizationFolderId, + string $name, ?int $parentResource = null, bool $active = true, @@ -53,30 +59,36 @@ class ResourceService { throw new InvalidResourceType($type); } - $resource->setGroupFolderId($groupFolderId); - $resource->setParentResource($parentResource); - $resource->setActive($active); - $resource->setLastUpdatedTimestamp(time()); + if(!$this->mapper->existsWithName($organizationFolderId, $parentResource, $name)) { + $resource->setGroupFolderId($organizationFolderId); + $resource->setName($name); + $resource->setParentResource($parentResource); + $resource->setActive($active); + $resource->setLastUpdatedTimestamp(time()); - if($type === "folder") { - if(isset($membersAclPermission, $managersAclPermission, $inheritedAclPermission)) { - $resource->setMembersAclPermission($membersAclPermission); - $resource->setManagersAclPermission($managersAclPermission); - $resource->setInheritedAclPermission($inheritedAclPermission); - } else { - throw new \InvalidArgumentException("Folder specific parameters must be included, when creating a resource of type folder"); + if($type === "folder") { + if(isset($membersAclPermission, $managersAclPermission, $inheritedAclPermission)) { + $resource->setMembersAclPermission($membersAclPermission); + $resource->setManagersAclPermission($managersAclPermission); + $resource->setInheritedAclPermission($inheritedAclPermission); + } else { + throw new \InvalidArgumentException("Folder specific parameters must be included, when creating a resource of type folder"); + } } + + $resource = $this->mapper->insert($resource); + + return $resource; + } else { + throw new ResourceNameNotUnique(); } - - $resource = $this->mapper->insert($resource); - - return $resource; } /* Use named arguments to call this function */ public function update( int $id, + ?string $name = null, ?int $parentResource = null, ?bool $active = null, @@ -90,6 +102,14 @@ class ResourceService { $resource->setParentResource($parentResource); } + if(isset($name)) { + if($this->mapper->existsWithName($resource->getGroupFolderId(), $resource->getParentResource(), $name)) { + throw new ResourceNameNotUnique(); + } else { + $resource->setName($name); + } + } + if(isset($active)) { $resource->setActive($active); }