diff --git a/lib/Db/CoreRequestBuilder.php b/lib/Db/CoreRequestBuilder.php index 41a5cea71..2cc2ea9ab 100644 --- a/lib/Db/CoreRequestBuilder.php +++ b/lib/Db/CoreRequestBuilder.php @@ -169,6 +169,7 @@ class CoreRequestBuilder { 'file_source', 'file_target', 'permissions', + 'attributes', 'stime', 'accepted', 'expiration', diff --git a/lib/Db/ShareWrapperRequest.php b/lib/Db/ShareWrapperRequest.php index ee4bcd44d..18286ad5f 100644 --- a/lib/Db/ShareWrapperRequest.php +++ b/lib/Db/ShareWrapperRequest.php @@ -31,16 +31,18 @@ namespace OCA\Circles\Db; +use JsonException; use OCA\Circles\Exceptions\RequestBuilderException; use OCA\Circles\Exceptions\ShareWrapperNotFoundException; use OCA\Circles\Model\FederatedUser; use OCA\Circles\Model\Membership; use OCA\Circles\Model\Probes\CircleProbe; use OCA\Circles\Model\ShareWrapper; +use OCP\Files\Folder; use OCP\Files\NotFoundException; use OCP\Share\Exceptions\IllegalIDChangeException; +use OCP\Share\IAttributes; use OCP\Share\IShare; -use OCP\Files\Folder; /** * Class ShareWrapperRequest @@ -62,18 +64,18 @@ public function save(IShare $share, int $parentId = 0): int { $qb = $this->getShareInsertSql(); $qb->setValue('share_type', $qb->createNamedParameter($share->getShareType())) - ->setValue('item_type', $qb->createNamedParameter($share->getNodeType())) - ->setValue('item_source', $qb->createNamedParameter($share->getNodeId())) - ->setValue('file_source', $qb->createNamedParameter($share->getNodeId())) - ->setValue('file_target', $qb->createNamedParameter($share->getTarget())) - ->setValue('share_with', $qb->createNamedParameter($share->getSharedWith())) - ->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner())) - ->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy())) - ->setValue('accepted', $qb->createNamedParameter(IShare::STATUS_ACCEPTED)) - ->setValue('password', $qb->createNamedParameter($password)) - ->setValue('permissions', $qb->createNamedParameter($share->getPermissions())) - ->setValue('token', $qb->createNamedParameter($share->getToken())) - ->setValue('stime', $qb->createFunction('UNIX_TIMESTAMP()')); + ->setValue('item_type', $qb->createNamedParameter($share->getNodeType())) + ->setValue('item_source', $qb->createNamedParameter($share->getNodeId())) + ->setValue('file_source', $qb->createNamedParameter($share->getNodeId())) + ->setValue('file_target', $qb->createNamedParameter($share->getTarget())) + ->setValue('share_with', $qb->createNamedParameter($share->getSharedWith())) + ->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner())) + ->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy())) + ->setValue('accepted', $qb->createNamedParameter(IShare::STATUS_ACCEPTED)) + ->setValue('password', $qb->createNamedParameter($password)) + ->setValue('permissions', $qb->createNamedParameter($share->getPermissions())) + ->setValue('token', $qb->createNamedParameter($share->getToken())) + ->setValue('stime', $qb->createFunction('UNIX_TIMESTAMP()')); if ($parentId > 0) { $qb->setValue('parent', $qb->createNamedParameter($parentId)); @@ -95,12 +97,15 @@ public function save(IShare $share, int $parentId = 0): int { */ public function update(ShareWrapper $shareWrapper): void { $qb = $this->getShareUpdateSql(); + $shareAttributes = $this->formatShareAttributes($shareWrapper->getAttributes()); + $qb->set('file_target', $qb->createNamedParameter($shareWrapper->getFileTarget())) - ->set('share_with', $qb->createNamedParameter($shareWrapper->getSharedWith())) - ->set('uid_owner', $qb->createNamedParameter($shareWrapper->getShareOwner())) - ->set('uid_initiator', $qb->createNamedParameter($shareWrapper->getSharedBy())) - ->set('accepted', $qb->createNamedParameter(IShare::STATUS_ACCEPTED)) - ->set('permissions', $qb->createNamedParameter($shareWrapper->getPermissions())); + ->set('share_with', $qb->createNamedParameter($shareWrapper->getSharedWith())) + ->set('uid_owner', $qb->createNamedParameter($shareWrapper->getShareOwner())) + ->set('uid_initiator', $qb->createNamedParameter($shareWrapper->getSharedBy())) + ->set('accepted', $qb->createNamedParameter(IShare::STATUS_ACCEPTED)) + ->set('permissions', $qb->createNamedParameter($shareWrapper->getPermissions())) + ->set('attributes', $qb->createNamedParameter($shareAttributes)); $qb->limitToId((int)$shareWrapper->getId()); @@ -486,4 +491,30 @@ private function deleteSharesAndChild(array $ids): void { $qb->execute(); } + + + /** + * Format IAttributes to database format (JSON string) + * based on OC\Share20\DefaultShareProvider::formatShareAttributes(); + */ + private function formatShareAttributes(?IAttributes $attributes): ?string { + if (empty($attributes?->toArray())) { + return null; + } + + $compressedAttributes = []; + foreach ($attributes->toArray() as $attribute) { + $compressedAttributes[] = [ + $attribute['scope'], + $attribute['key'], + $attribute['enabled'] + ]; + } + + try { + return json_encode($compressedAttributes, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR); + } catch (JsonException $e) { + return null; + } + } } diff --git a/lib/Model/ShareWrapper.php b/lib/Model/ShareWrapper.php index 6b3a3262a..4909582bc 100644 --- a/lib/Model/ShareWrapper.php +++ b/lib/Model/ShareWrapper.php @@ -36,6 +36,7 @@ use OC; use OC\Files\Cache\Cache; use OC\Share20\Share; +use OC\Share20\ShareAttributes; use OCA\Circles\AppInfo\Application; use OCA\Circles\ShareByCircleProvider; use OCA\Circles\Tools\Db\IQueryRow; @@ -48,6 +49,7 @@ use OCP\IUserManager; use OCP\L10N\IFactory; use OCP\Share\Exceptions\IllegalIDChangeException; +use OCP\Share\IAttributes; use OCP\Share\IShare; /** @@ -82,6 +84,8 @@ class ShareWrapper extends ManagedModel implements IDeserializable, IQueryRow, J private ?Member $initiator = null; private ?Member $owner = null; private ?ShareToken $shareToken = null; + private ?IAttributes $attributes = null; + private bool $hideDownload = false; public function __construct() { $this->shareTime = new DateTime(); @@ -337,6 +341,27 @@ public function hasShareToken(): bool { return !is_null($this->shareToken); } + public function getAttributes(): ?IAttributes { + return $this->attributes; + } + + public function setAttributes(?IAttributes $attributes): self { + $this->attributes = $attributes; + + return $this; + } + + public function getHideDownload(): bool { + return $this->hideDownload; + } + + public function setHideDownload(bool $hideDownload): self { + $this->hideDownload = $hideDownload; + + return $this; + } + + /** * @throws IllegalIDChangeException */ @@ -354,7 +379,8 @@ public function getShare( $share->setTarget($this->getFileTarget()); $share->setProviderId($this->getProviderId()); $share->setStatus($this->getStatus()); - + $share->setHideDownload($this->getHideDownload()); + $share->setAttributes($this->getAttributes()); if ($this->hasShareToken()) { $password = $this->getShareToken()->getPassword(); if ($password !== '') { @@ -456,6 +482,7 @@ public function import(array $data): IDeserializable { $this->setId($this->get('id', $data)) ->setShareType($this->getInt('shareType', $data)) ->setPermissions($this->getInt('permissions', $data)) + ->setHideDownload($this->getBool('hideDownload', $data)) ->setItemType($this->get('itemType', $data)) ->setItemSource($this->getInt('itemSource', $data)) ->setItemTarget($this->get('itemTarget', $data)) @@ -524,6 +551,8 @@ public function importFromDatabase(array $data, string $prefix = ''): IQueryRow ->setToken($this->get($prefix . 'token', $data)) ->setShareTime($shareTime); + $this->importAttributesFromDatabase($this->get('attributes', $data)); + // if (($password = $this->get('personal_password', $data, '')) !== '') { // $share->setPassword($this->get('personal_password', $data, '')); // } else if (($password = $this->get('password', $data, '')) !== '') { @@ -541,12 +570,39 @@ public function importFromDatabase(array $data, string $prefix = ''): IQueryRow return $this; } + + /** + * Load from database format (JSON string) to IAttributes + * based on \OC\Share20\DefaultShareProvider + */ + private function importAttributesFromDatabase(string $data): void { + if ($data === '') { + return; + } + + $attributes = new ShareAttributes(); + $compressedAttributes = json_decode($data, true); + if (!is_array($compressedAttributes)) { + return; + } + + foreach ($compressedAttributes as $compressedAttribute) { + $attributes->setAttribute(...$compressedAttribute); + } + + $this->setHideDownload(!($attributes->getAttribute('permissions', 'download') ?? true)); + $this->setAttributes($attributes); + } + + public function jsonSerialize(): array { $arr = [ 'id' => $this->getId(), 'shareType' => $this->getShareType(), 'providerId' => $this->getProviderId(), 'permissions' => $this->getPermissions(), + 'attributes' => $this->getAttributes(), + 'hideDownload' => $this->getHideDownload(), 'itemType' => $this->getItemType(), 'itemSource' => $this->getItemSource(), 'itemTarget' => $this->getItemTarget(), diff --git a/lib/Service/CircleService.php b/lib/Service/CircleService.php index b4e023e88..475ed968d 100644 --- a/lib/Service/CircleService.php +++ b/lib/Service/CircleService.php @@ -801,7 +801,7 @@ public function probeCircle( * @param CircleProbe $circleProbe * @param DataProbe|null $dataProbe * - * @return array + * @return Circle[] * @throws InitiatorNotFoundException * @throws RequestBuilderException */ diff --git a/lib/ShareByCircleProvider.php b/lib/ShareByCircleProvider.php index 48b564233..31c379b3d 100644 --- a/lib/ShareByCircleProvider.php +++ b/lib/ShareByCircleProvider.php @@ -225,8 +225,9 @@ public function create(IShare $share): IShare { public function update(IShare $share): IShare { $wrappedShare = $this->shareWrapperService->getShareById((int)$share->getId()); $wrappedShare->setPermissions($share->getPermissions()) - ->setShareOwner($share->getShareOwner()) - ->setSharedBy($share->getSharedBy()); + ->setShareOwner($share->getShareOwner()) + ->setAttributes($share->getAttributes()) + ->setSharedBy($share->getSharedBy()); $this->shareWrapperService->update($wrappedShare); diff --git a/psalm.xml b/psalm.xml index 81ca9131b..9ab703435 100644 --- a/psalm.xml +++ b/psalm.xml @@ -26,6 +26,7 @@ + diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml index 522091959..086779a64 100644 --- a/tests/psalm-baseline.xml +++ b/tests/psalm-baseline.xml @@ -430,8 +430,9 @@ - + Cache::cacheEntryFromData($this->getFileCache()->toCache(), OC::$server->getMimeTypeLoader()) + $this->setAttributes($attributes) Circle