0
0
Fork 0
mirror of https://github.com/verdigado/organization_folders.git synced 2024-11-21 20:28:11 +01:00

added resource members

This commit is contained in:
Jonathan Treffler 2024-10-31 17:29:15 +01:00
parent 851fa0a1cc
commit 92c431e856
14 changed files with 311 additions and 20 deletions

View file

@ -23,5 +23,7 @@
<command>OCA\OrganizationFolders\Command\OrganizationFolder\CreateOrganizationFolder</command> <command>OCA\OrganizationFolders\Command\OrganizationFolder\CreateOrganizationFolder</command>
<command>OCA\OrganizationFolders\Command\Resource\CreateResource</command> <command>OCA\OrganizationFolders\Command\Resource\CreateResource</command>
<command>OCA\OrganizationFolders\Command\Resource\ListResources</command> <command>OCA\OrganizationFolders\Command\Resource\ListResources</command>
<command>OCA\OrganizationFolders\Command\ResourceMember\CreateResourceMember</command>
<command>OCA\OrganizationFolders\Command\ResourceMember\ListResourceMembers</command>
</commands> </commands>
</info> </info>

View file

@ -8,6 +8,7 @@ use OCP\IDateTimeFormatter;
use OCA\OrganizationFolders\Model\OrganizationFolder; use OCA\OrganizationFolders\Model\OrganizationFolder;
use OCA\OrganizationFolders\Service\OrganizationFolderService; use OCA\OrganizationFolders\Service\OrganizationFolderService;
use OCA\OrganizationFolders\Service\ResourceService; use OCA\OrganizationFolders\Service\ResourceService;
use OCA\OrganizationFolders\Service\ResourceMemberService;
use OCA\OrganizationFolders\Interface\TableSerializable; use OCA\OrganizationFolders\Interface\TableSerializable;
abstract class BaseCommand extends Base { abstract class BaseCommand extends Base {
@ -16,19 +17,20 @@ abstract class BaseCommand extends Base {
private readonly IDateTimeFormatter $dateTimeFormatter, private readonly IDateTimeFormatter $dateTimeFormatter,
protected readonly OrganizationFolderService $organizationFolderService, protected readonly OrganizationFolderService $organizationFolderService,
protected ResourceService $resourceService, protected ResourceService $resourceService,
protected ResourceMemberService $resourceMemberService,
) { ) {
parent::__construct(); parent::__construct();
} }
protected function formatTableSerializable(TableSerializable $serializable): array { protected function formatTableSerializable(TableSerializable $serializable, ?array $params = null): array {
return $serializable->tableSerialize(); return $serializable->tableSerialize($params);
} }
protected function formatOrganizationFolders(array $organizationFolders) { protected function formatTableSerializables(array $serializables, ?array $params = null): array {
return array_map($this->formatTableSerializable(...), $organizationFolders); $result = [];
foreach($serializables as $serializable) {
$result[] = $serializable->tableSerialize($params);
} }
return $result;
protected function formatResources(array $resources): array {
return array_map($this->formatTableSerializable(...), $resources);
} }
} }

View file

@ -21,7 +21,7 @@ class ListOrganizationFolders extends BaseCommand {
try { try {
$organizationFolderGroupfolders = $this->organizationFolderService->getAll(); $organizationFolderGroupfolders = $this->organizationFolderService->getAll();
$this->writeTableInOutputFormat($input, $output, $this->formatOrganizationFolders($organizationFolderGroupfolders)); $this->writeTableInOutputFormat($input, $output, $this->formatTableSerializables($organizationFolderGroupfolders));
return 0; return 0;
} catch (Exception $e) { } catch (Exception $e) {
$output->writeln("<error>Exception \"{$e->getMessage()}\" at {$e->getFile()} line {$e->getLine()}</error>"); $output->writeln("<error>Exception \"{$e->getMessage()}\" at {$e->getFile()} line {$e->getLine()}</error>");

View file

@ -27,7 +27,7 @@ class ListResources extends BaseCommand {
$resources = $this->resourceService->findAll($organizationFolderId, $parentResourceId); $resources = $this->resourceService->findAll($organizationFolderId, $parentResourceId);
$this->writeTableInOutputFormat($input, $output, $this->formatResources($resources)); $this->writeTableInOutputFormat($input, $output, $this->formatTableSerializables($resources));
return 0; return 0;
} catch (Exception $e) { } catch (Exception $e) {
$output->writeln("<error>Exception \"{$e->getMessage()}\" at {$e->getFile()} line {$e->getLine()}</error>"); $output->writeln("<error>Exception \"{$e->getMessage()}\" at {$e->getFile()} line {$e->getLine()}</error>");

View file

@ -0,0 +1,48 @@
<?php
namespace OCA\OrganizationFolders\Command\ResourceMember;
use OCP\DB\Exception;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use OCA\OrganizationFolders\Command\BaseCommand;
use OCA\OrganizationFolders\Enum\MemberType;
use OCA\OrganizationFolders\Enum\MemberPermissionLevel;
class CreateResourceMember extends BaseCommand {
protected function configure(): void {
$this
->setName('organization-folders:create-resource-member')
->setDescription('Create a new member of resource')
->addOption('resource-id', null, InputOption::VALUE_REQUIRED, 'Id of resource to create member of')
->addOption('permission-level', null, InputOption::VALUE_REQUIRED, 'Permissions level of member (valid values: MEMBER, MANAGER)')
->addOption('type', null, InputOption::VALUE_REQUIRED, 'Type of principal (valid values: USER, GROUP, ROLE)')
->addOption('principal', null, InputOption::VALUE_OPTIONAL, 'For type user: "[user_id]", for group: "[group_name]", for role: "[organization_provider_id]:[role_id]"');
parent::configure();
}
protected function execute(InputInterface $input, OutputInterface $output): int {
$resourceId = $input->getOption('resource-id');
$permissionLevel = MemberPermissionLevel::fromNameOrValue($input->getOption('permission-level'));
$type = MemberType::fromNameOrValue($input->getOption('type'));
$principal = $input->getOption('principal');
try {
$resource = $this->resourceMemberService->create(
resourceId: $resourceId,
permissionLevel: $permissionLevel,
type: $type,
principal: $principal,
);
$this->writeTableInOutputFormat($input, $output, [$this->formatTableSerializable($resource)]);
return 0;
} catch (Exception $e) {
$output->writeln("<error>Exception \"{$e->getMessage()}\" at {$e->getFile()} line {$e->getLine()}</error>");
return 1;
}
}
}

View file

@ -0,0 +1,35 @@
<?php
namespace OCA\OrganizationFolders\Command\ResourceMember;
use OCP\DB\Exception;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use OCA\OrganizationFolders\Command\BaseCommand;
class ListResourceMembers extends BaseCommand {
protected function configure(): void {
$this
->setName('organization-folders:list-resource-members')
->addArgument('resource-id', InputArgument::REQUIRED, 'Id of Resource')
->setDescription('List all members of resource.');
parent::configure();
}
protected function execute(InputInterface $input, OutputInterface $output): int {
try {
$resourceId = $input->getArgument('resource-id');
$members = $this->resourceMemberService->findAll($resourceId);
$this->writeTableInOutputFormat($input, $output, $this->formatTableSerializables($members));
return 0;
} catch (Exception $e) {
$output->writeln("<error>Exception \"{$e->getMessage()}\" at {$e->getFile()} line {$e->getLine()}</error>");
return 1;
}
}
}

View file

@ -48,7 +48,7 @@ class FolderResource extends Resource {
]; ];
} }
public function tableSerialize(): array { public function tableSerialize(?array $params = null): array {
return [ return [
'Id' => $this->id, 'Id' => $this->id,
'Name' => $this->name, 'Name' => $this->name,

50
lib/Db/ResourceMember.php Normal file
View file

@ -0,0 +1,50 @@
<?php
namespace OCA\OrganizationFolders\Db;
use JsonSerializable;
use OCA\OrganizationFolders\Interface\TableSerializable;
use OCP\AppFramework\Db\Entity;
use OCA\OrganizationFolders\Enum\MemberPermissionLevel;
use OCA\OrganizationFolders\Enum\MemberType;
class ResourceMember extends Entity implements JsonSerializable, TableSerializable {
protected $resourceId;
protected $permissionLevel;
protected $type;
protected $principal;
protected $createdTimestamp;
protected $lastUpdatedTimestamp;
public function __construct() {
$this->addType('resourceId','integer');
$this->addType('permissionLevel','integer');
$this->addType('type','integer');
$this->addType('createdTimestamp','integer');
$this->addType('lastUpdatedTimestamp','integer');
}
public function jsonSerialize(): array {
return [
'resourceId' => $this->resourceId,
'permissionLevel' => $this->permissionLevel,
'type' => $this->type,
'principal' => $this->principal,
'createdTimestamp' => $this->createdTimestamp,
'lastUpdatedTimestamp' => $this->lastUpdatedTimestamp,
];
}
public function tableSerialize(?array $params = null): array {
return [
'Resource Id' => $this->resourceId,
'Permission Level' => MemberPermissionLevel::from($this->permissionLevel)->name,
'Type' => MemberType::from($this->type)->name,
'Principal' => $this->principal,
'Created' => $this->createdTimestamp,
'LastUpdated' => $this->lastUpdatedTimestamp,
];
}
}

View file

@ -0,0 +1,49 @@
<?php
namespace OCA\OrganizationFolders\Db;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\QBMapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
class ResourceMemberMapper extends QBMapper {
public const RESOURCE_MEMBERS_TABLE = "organizationfolders_resource_members";
public function __construct(IDBConnection $db) {
parent::__construct($db, self::RESOURCE_MEMBERS_TABLE, ResourceMember::class);
}
/**
* @param int $id
* @return Entity|ResourceMember
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws DoesNotExistException
*/
public function find(int $id): ResourceMember {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from(self::RESOURCE_MEMBERS_TABLE)
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
return $this->findEntity($qb);
}
/**
* @param int $resourceId
* @return array
*/
public function findAll(int $resourceId): array {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from(self::RESOURCE_MEMBERS_TABLE)
->where($qb->expr()->eq('resource_id', $qb->createNamedParameter($resourceId, IQueryBuilder::PARAM_INT)));
return $this->findEntities($qb);
}
}

View file

@ -3,12 +3,20 @@
namespace OCA\OrganizationFolders\Enum; namespace OCA\OrganizationFolders\Enum;
trait FromNameEnum { trait FromNameEnum {
public static function fromName(string $name): string { public static function fromName(string $name) {
foreach(self::cases() as $status) { foreach(self::cases() as $status) {
if($name === $status->name){ if($name === $status->name){
return $status->value; return $status;
} }
} }
throw new \ValueError("$name is not a valid value for enum " . self::class ); throw new \ValueError("$name is not a valid value for enum " . self::class );
} }
public static function fromNameOrValue(int|string $scalar) {
if(gettype($scalar) == "integer") {
return self::tryFrom($scalar);
} else {
return self::fromName($scalar);
}
}
} }

View file

@ -7,5 +7,5 @@ interface TableSerializable {
* Serializes the object to a dict array to be rendered into a occ command output table * Serializes the object to a dict array to be rendered into a occ command output table
* @return array * @return array
*/ */
function tableSerialize(); function tableSerialize(?array $params = null);
} }

View file

@ -33,7 +33,7 @@ class OrganizationFolder implements JsonSerializable, TableSerializable {
]; ];
} }
public function tableSerialize(): array { public function tableSerialize(?array $params = null): array {
return [ return [
'Id' => $this->id, 'Id' => $this->id,
'Name' => $this->name, 'Name' => $this->name,

View file

@ -0,0 +1,97 @@
<?php
namespace OCA\OrganizationFolders\Service;
use Exception;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCA\OrganizationFolders\Errors\ResourceMemberNotFound;
use OCA\OrganizationFolders\Db\ResourceMember;
use OCA\OrganizationFolders\Db\ResourceMemberMapper;
use OCA\OrganizationFolders\Enum\MemberPermissionLevel;
use OCA\OrganizationFolders\Enum\MemberType;
class ResourceMemberService {
public function __construct(
private ResourceMemberMapper $mapper
) {
}
public function findAll(int $resourceId): array {
return $this->mapper->findAll($resourceId);
}
private function handleException(Exception $e): void {
if ($e instanceof DoesNotExistException ||
$e instanceof MultipleObjectsReturnedException) {
throw new ResourceMemberNotFound($e->getMessage());
} else {
throw $e;
}
}
public function find(int $id): ResourceMember {
try {
return $this->mapper->find($id);
} catch (Exception $e) {
$this->handleException($e);
}
}
public function create(
int $resourceId,
MemberPermissionLevel $permissionLevel,
MemberType $type,
string $principal
): ResourceMember {
$member = new ResourceMember();
$member->setResourceId($resourceId);
$member->setPermissionLevel($permissionLevel->value);
$member->setType($type->value);
$member->setPrincipal($principal);
$member->setCreatedTimestamp(time());
$member->setLastUpdatedTimestamp(time());
return $this->mapper->insert($member);
}
public function update(int $id, ?MemberPermissionLevel $permissionLevel = null, ?MemberType $type = null, ?string $principal = null): ResourceMember {
try {
$member = $this->mapper->find($id);
if(isset($permissionLevel)) {
$member->setPermissionLevel($permissionLevel->value);
}
if(isset($type)) {
$member->setType($type->value);
}
if(isset($principal)) {
$member->setPrincipal($principal);
}
if(count($member->getUpdatedFields()) > 0) {
$member->setLastUpdatedTimestamp(time());
}
return $this->mapper->update($member);
} catch (Exception $e) {
$this->handleException($e);
}
}
public function delete(int $id): ResourceMember {
try {
$member = $this->mapper->find($id);
$this->mapper->delete($member);
return $member;
} catch (Exception $e) {
$this->handleException($e);
}
}
}

View file

@ -20,8 +20,8 @@ class ResourceService {
) { ) {
} }
public function findAll(int $groupfolderId, int $parentResourceId = null) { public function findAll(int $organizationFolderId, int $parentResourceId = null) {
return $this->mapper->findAll($groupfolderId, $parentResourceId); return $this->mapper->findAll($organizationFolderId, $parentResourceId);
} }
private function handleException(Exception $e, int $id): void { private function handleException(Exception $e, int $id): void {
@ -60,7 +60,7 @@ class ResourceService {
} }
if(!$this->mapper->existsWithName($organizationFolderId, $parentResource, $name)) { if(!$this->mapper->existsWithName($organizationFolderId, $parentResource, $name)) {
$resource->setGroupFolderId($organizationFolderId); $resource->setOrganizationFolderId($organizationFolderId);
$resource->setName($name); $resource->setName($name);
$resource->setParentResource($parentResource); $resource->setParentResource($parentResource);
$resource->setActive($active); $resource->setActive($active);