682 lines
17 KiB
PHP
682 lines
17 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
/**
|
|
* SPDX-FileCopyrightText: 2021 F7cloud GmbH and F7cloud contributors
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
|
|
namespace OCA\Circles\Model;
|
|
|
|
use DateTime;
|
|
use JsonSerializable;
|
|
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;
|
|
use OCA\Circles\Tools\Exceptions\InvalidItemException;
|
|
use OCA\Circles\Tools\IDeserializable;
|
|
use OCA\Circles\Tools\Traits\TArrayTools;
|
|
use OCA\Circles\Tools\Traits\TDeserialize;
|
|
use OCP\Files\IMimeTypeLoader;
|
|
use OCP\Files\IRootFolder;
|
|
use OCP\IURLGenerator;
|
|
use OCP\IUserManager;
|
|
use OCP\L10N\IFactory;
|
|
use OCP\Server;
|
|
use OCP\Share\Exceptions\IllegalIDChangeException;
|
|
use OCP\Share\IAttributes;
|
|
use OCP\Share\IShare;
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
/**
|
|
* Class ShareWrapper
|
|
*
|
|
* @package OCA\Circles\Model
|
|
*/
|
|
class ShareWrapper extends ManagedModel implements IDeserializable, IQueryRow, JsonSerializable {
|
|
use TArrayTools;
|
|
use TDeserialize;
|
|
|
|
private string $id = '';
|
|
private int $permissions = 0;
|
|
private string $itemType = '';
|
|
private int $itemSource = 0;
|
|
private string $itemTarget = '';
|
|
private int $fileSource = 0;
|
|
private string $fileTarget = '';
|
|
private string $token = '';
|
|
private int $status = 0;
|
|
private string $providerId = '';
|
|
private DateTime $shareTime;
|
|
private string $note = '';
|
|
private string $sharedWith = '';
|
|
private string $sharedBy = '';
|
|
private ?DateTime $expirationDate = null;
|
|
private string $shareOwner = '';
|
|
private int $shareType = 0;
|
|
private int $parent = 0;
|
|
private ?Circle $circle = null;
|
|
private int $childId = 0;
|
|
private string $childFileTarget = '';
|
|
private int $childPermissions = 0;
|
|
private ?FileCacheWrapper $fileCache = null;
|
|
private ?Member $initiator = null;
|
|
private ?Member $owner = null;
|
|
private ?ShareToken $shareToken = null;
|
|
private ?IAttributes $attributes = null;
|
|
private bool $hideDownload = false;
|
|
private bool $mailSend = true;
|
|
|
|
public function __construct() {
|
|
$this->shareTime = new DateTime();
|
|
}
|
|
|
|
public function setId(string $id): self {
|
|
$this->id = $id;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getId(): string {
|
|
return $this->id;
|
|
}
|
|
|
|
public function setPermissions(int $permissions): self {
|
|
$this->permissions = $permissions;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getPermissions(): int {
|
|
return $this->permissions;
|
|
}
|
|
|
|
public function setItemType(string $itemType): self {
|
|
$this->itemType = $itemType;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getItemType(): string {
|
|
return $this->itemType;
|
|
}
|
|
|
|
public function setItemSource(int $itemSource): self {
|
|
$this->itemSource = $itemSource;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getItemSource(): int {
|
|
return $this->itemSource;
|
|
}
|
|
|
|
public function setItemTarget(string $itemTarget): self {
|
|
$this->itemTarget = $itemTarget;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getItemTarget(): string {
|
|
return $this->itemTarget;
|
|
}
|
|
|
|
public function setFileSource(int $fileSource): self {
|
|
$this->fileSource = $fileSource;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getFileSource(): int {
|
|
return $this->fileSource;
|
|
}
|
|
|
|
public function setFileTarget(string $fileTarget): self {
|
|
$this->fileTarget = $fileTarget;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getFileTarget(): string {
|
|
return $this->fileTarget;
|
|
}
|
|
|
|
public function setToken(string $token): self {
|
|
$this->token = $token;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getToken(): string {
|
|
return $this->token;
|
|
}
|
|
|
|
public function setStatus(int $status): self {
|
|
$this->status = $status;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getStatus(): int {
|
|
return $this->status;
|
|
}
|
|
|
|
public function setProviderId(string $providerId): self {
|
|
$this->providerId = $providerId;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getProviderId(): string {
|
|
return $this->providerId;
|
|
}
|
|
|
|
public function setShareTime(DateTime $shareTime): self {
|
|
$this->shareTime = $shareTime;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getShareTime(): DateTime {
|
|
return $this->shareTime;
|
|
}
|
|
|
|
public function setShareNote(string $note): self {
|
|
$this->note = $note;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getShareNote(): string {
|
|
return $this->note;
|
|
}
|
|
|
|
public function setSharedWith(string $sharedWith): self {
|
|
$this->sharedWith = $sharedWith;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getSharedWith(): string {
|
|
return $this->sharedWith;
|
|
}
|
|
|
|
public function setSharedBy(string $sharedBy): self {
|
|
$this->sharedBy = $sharedBy;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getExpirationDate(): ?DateTime {
|
|
return $this->expirationDate;
|
|
}
|
|
|
|
public function setExpirationDate(?DateTime $date):self {
|
|
$this->expirationDate = $date;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getSharedBy(): string {
|
|
return $this->sharedBy;
|
|
}
|
|
|
|
public function setShareOwner(string $shareOwner): self {
|
|
$this->shareOwner = $shareOwner;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getShareOwner(): string {
|
|
return $this->shareOwner;
|
|
}
|
|
|
|
public function setShareType(int $shareType): self {
|
|
$this->shareType = $shareType;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getShareType(): int {
|
|
return $this->shareType;
|
|
}
|
|
|
|
public function setParent(int $parent): self {
|
|
$this->parent = $parent;
|
|
return $this;
|
|
}
|
|
|
|
public function getParent(): int {
|
|
return $this->parent;
|
|
}
|
|
|
|
public function setCircle(Circle $circle): self {
|
|
$this->circle = $circle;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getCircle(): Circle {
|
|
return $this->circle;
|
|
}
|
|
|
|
public function hasCircle(): bool {
|
|
return (!is_null($this->circle));
|
|
}
|
|
|
|
public function setChildId(int $childId): self {
|
|
$this->childId = $childId;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getChildId(): int {
|
|
return $this->childId;
|
|
}
|
|
|
|
public function setChildFileTarget(string $childFileTarget): self {
|
|
$this->childFileTarget = $childFileTarget;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getChildFileTarget(): string {
|
|
return $this->childFileTarget;
|
|
}
|
|
|
|
public function setChildPermissions(int $childPermissions): self {
|
|
$this->childPermissions = $childPermissions;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getChildPermissions(): int {
|
|
return $this->childPermissions;
|
|
}
|
|
|
|
public function setFileCache(FileCacheWrapper $fileCache): self {
|
|
$this->fileCache = $fileCache;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getFileCache(): FileCacheWrapper {
|
|
return $this->fileCache;
|
|
}
|
|
|
|
public function hasFileCache(): bool {
|
|
return (!is_null($this->fileCache));
|
|
}
|
|
|
|
public function setInitiator(Member $initiator): self {
|
|
$this->initiator = $initiator;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getInitiator(): Member {
|
|
return $this->initiator;
|
|
}
|
|
|
|
public function hasInitiator(): bool {
|
|
return (!is_null($this->initiator));
|
|
}
|
|
|
|
public function setOwner(Member $owner): self {
|
|
$this->owner = $owner;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getOwner(): Member {
|
|
return $this->owner;
|
|
}
|
|
|
|
public function hasOwner(): bool {
|
|
return (!is_null($this->owner));
|
|
}
|
|
|
|
public function setShareToken(ShareToken $shareToken): self {
|
|
$this->shareToken = $shareToken;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getShareToken(): ShareToken {
|
|
return $this->shareToken;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
public function setMailSend(bool $mailSend): self {
|
|
$this->mailSend = $mailSend;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getMailSend(): bool {
|
|
return $this->mailSend;
|
|
}
|
|
|
|
|
|
/**
|
|
* @throws IllegalIDChangeException
|
|
*/
|
|
public function getShare(
|
|
IRootFolder $rootFolder,
|
|
IUserManager $userManager,
|
|
IURLGenerator $urlGenerator,
|
|
bool $nullOnMissingFileCache = false,
|
|
): ?IShare {
|
|
$share = new Share($rootFolder, $userManager);
|
|
$share->setId($this->getId());
|
|
$share->setPermissions($this->getPermissions());
|
|
$share->setNodeType($this->getItemType());
|
|
$share->setNodeId($this->getFileSource());
|
|
$share->setTarget($this->getFileTarget());
|
|
$share->setProviderId($this->getProviderId());
|
|
$share->setStatus($this->getStatus());
|
|
$share->setToken($this->getToken());
|
|
if ($this->getExpirationDate() !== null) {
|
|
$share->setExpirationDate($this->getExpirationDate());
|
|
}
|
|
$share->setHideDownload($this->getHideDownload());
|
|
$share->setAttributes($this->getAttributes());
|
|
$share->setNote($this->getShareNote());
|
|
$share->setMailSend($this->getMailSend());
|
|
if ($this->hasShareToken()) {
|
|
$password = $this->getShareToken()->getPassword();
|
|
if ($password !== '') {
|
|
$share->setPassword($password);
|
|
}
|
|
}
|
|
|
|
$share->setShareTime($this->getShareTime())
|
|
->setSharedWith($this->getSharedWith())
|
|
->setSharedBy($this->getSharedBy())
|
|
->setShareOwner($this->getShareOwner())
|
|
->setShareType($this->getShareType());
|
|
|
|
if ($this->getChildId() > 0) {
|
|
$share->setTarget($this->getChildFileTarget());
|
|
if ($this->getChildPermissions() < $this->getPermissions()) {
|
|
$share->setPermissions($this->getChildPermissions());
|
|
}
|
|
}
|
|
|
|
$this->setShareDisplay($share, $urlGenerator);
|
|
|
|
if ($this->hasFileCache()) {
|
|
if (!$this->getFileCache()->isAccessible()) {
|
|
return null;
|
|
}
|
|
$share->setNodeCacheEntry(
|
|
Cache::cacheEntryFromData($this->getFileCache()->toCache(), Server::get(IMimeTypeLoader::class))
|
|
);
|
|
} elseif ($nullOnMissingFileCache) {
|
|
return null;
|
|
}
|
|
|
|
return $share;
|
|
}
|
|
|
|
private function setShareDisplay(IShare $share, IURLGenerator $urlGenerator): void {
|
|
if (!$this->hasCircle()) {
|
|
return;
|
|
}
|
|
|
|
$circle = $this->getCircle();
|
|
if ($circle->isConfig(Circle::CFG_PERSONAL)
|
|
&& $this->hasInitiator()
|
|
&& $circle->getOwner()->getSingleId() !== $this->getInitiator()->getSingleId()) {
|
|
$share->setSharedWithDisplayName(' ');
|
|
|
|
return;
|
|
}
|
|
|
|
$display = $circle->getDisplayName();
|
|
if ($circle->getSource() === Member::TYPE_CIRCLE) {
|
|
$l10n = Server::get(IFactory::class)->get('circles');
|
|
$display = $l10n->t('%s (Team owned by %s)', [$display, $circle->getOwner()->getDisplayName()]);
|
|
} else {
|
|
$display .= ' (' . Circle::$DEF_SOURCE[$circle->getSource()] . ')';
|
|
}
|
|
|
|
$share->setSharedWithDisplayName($display);
|
|
|
|
$icon = $urlGenerator->getAbsoluteURL(
|
|
$urlGenerator->imagePath(Application::APP_ID, 'circles.svg')
|
|
);
|
|
$share->setSharedWithAvatar($icon);
|
|
}
|
|
|
|
|
|
/**
|
|
* @param array $data
|
|
*
|
|
* @throws InvalidItemException
|
|
*/
|
|
public function import(array $data): IDeserializable {
|
|
if ($this->getInt('id', $data) === 0) {
|
|
throw new InvalidItemException();
|
|
}
|
|
|
|
$shareTime = new DateTime();
|
|
$shareTime->setTimestamp($this->getInt('shareTime', $data));
|
|
|
|
$this->setId($this->get('id', $data))
|
|
->setShareType($this->getInt('shareType', $data))
|
|
->setParent($data['parent'] ?? 0)
|
|
->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))
|
|
->setFileSource($this->getInt('fileSource', $data))
|
|
->setFileTarget($this->get('fileTarget', $data))
|
|
->setSharedWith($this->get('sharedWith', $data))
|
|
->setSharedBy($this->get('sharedBy', $data))
|
|
->setShareOwner($this->get('shareOwner', $data))
|
|
->setToken($this->get('token', $data))
|
|
->setShareTime($shareTime)
|
|
->setShareNote($this->get('note', $data));
|
|
|
|
$this->importAttributesFromDatabase($this->get('attributes', $data));
|
|
|
|
try {
|
|
$expirationDate = $this->getInt('expiration', $data);
|
|
if ($expirationDate > 0) {
|
|
$this->setExpirationDate((new DateTime())->setTimestamp($expirationDate));
|
|
}
|
|
} catch (\Exception $e) {
|
|
}
|
|
|
|
$this->setChildId($this->getInt('childId', $data))
|
|
->setChildFileTarget($this->get('childFileTarget', $data))
|
|
->setChildPermissions($this->getInt('childPermissions', $data))
|
|
->setProviderId(ShareByCircleProvider::IDENTIFIER)
|
|
->setStatus(Ishare::STATUS_ACCEPTED);
|
|
|
|
try {
|
|
$circle = new Circle();
|
|
$this->setCircle($circle->import($this->getArray('circle', $data)));
|
|
} catch (InvalidItemException $e) {
|
|
}
|
|
|
|
try {
|
|
$fileCache = new FileCacheWrapper();
|
|
$this->setFileCache($fileCache->import($this->getArray('fileCache', $data)));
|
|
} catch (InvalidItemException $e) {
|
|
}
|
|
|
|
try {
|
|
$owner = new Member();
|
|
$this->setOwner($owner->import($this->getArray('owner', $data)));
|
|
} catch (InvalidItemException $e) {
|
|
}
|
|
|
|
try {
|
|
$member = new Member();
|
|
$this->setInitiator($member->import($this->getArray('viewer', $data)));
|
|
} catch (InvalidItemException $e) {
|
|
}
|
|
|
|
try {
|
|
$shareToken = new ShareToken();
|
|
$this->setShareToken($shareToken->import($this->getArray('shareToken', $data)));
|
|
} catch (InvalidItemException $e) {
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function importFromDatabase(array $data, string $prefix = ''): IQueryRow {
|
|
$shareTime = new DateTime();
|
|
$shareTime->setTimestamp($this->getInt($prefix . 'stime', $data));
|
|
|
|
$this->setId($this->get($prefix . 'id', $data))
|
|
->setShareType($this->getInt($prefix . 'share_type', $data))
|
|
->setPermissions($this->getInt($prefix . 'permissions', $data))
|
|
->setItemType($this->get($prefix . 'item_type', $data))
|
|
->setItemSource($this->getInt($prefix . 'item_source', $data))
|
|
->setItemTarget($this->get($prefix . 'item_target', $data))
|
|
->setFileSource($this->getInt($prefix . 'file_source', $data))
|
|
->setFileTarget($this->get($prefix . 'file_target', $data))
|
|
->setSharedWith($this->get($prefix . 'share_with', $data))
|
|
->setSharedBy($this->get($prefix . 'uid_initiator', $data))
|
|
->setShareOwner($this->get($prefix . 'uid_owner', $data))
|
|
->setToken($this->get($prefix . 'token', $data))
|
|
->setShareTime($shareTime)
|
|
->setShareNote($this->get($prefix . 'note', $data));
|
|
|
|
try {
|
|
$expirationDate = $this->get($prefix . 'expiration', $data);
|
|
if ($expirationDate !== '') {
|
|
$this->setExpirationDate(new DateTime($expirationDate));
|
|
}
|
|
} catch (\Exception $e) {
|
|
Server::get(LoggerInterface::class)->warning('could not parse expiration date', ['exception' => $e]);
|
|
}
|
|
|
|
$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, '')) !== '') {
|
|
// $share->setPassword($this->get('password', $data, ''));
|
|
// }
|
|
|
|
$this->setChildId($this->getInt($prefix . 'child_id', $data))
|
|
->setChildFileTarget($this->get($prefix . 'child_file_target', $data))
|
|
->setChildPermissions($this->getInt($prefix . 'child_permissions', $data))
|
|
->setProviderId(ShareByCircleProvider::IDENTIFIER)
|
|
->setStatus(Ishare::STATUS_ACCEPTED);
|
|
|
|
$this->getManager()->manageImportFromDatabase($this, $data, $prefix);
|
|
|
|
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() !== null) ? json_encode($this->getAttributes()->toArray()) : null,
|
|
'hideDownload' => $this->getHideDownload(),
|
|
'itemType' => $this->getItemType(),
|
|
'itemSource' => $this->getItemSource(),
|
|
'itemTarget' => $this->getItemTarget(),
|
|
'fileSource' => $this->getFileSource(),
|
|
'fileTarget' => $this->getFileTarget(),
|
|
'expiration' => $this->getExpirationDate()?->getTimestamp(),
|
|
'status' => $this->getStatus(),
|
|
'shareTime' => $this->getShareTime()->getTimestamp(),
|
|
'note' => $this->getShareNote(),
|
|
'sharedWith' => $this->getSharedWith(),
|
|
'sharedBy' => $this->getSharedBy(),
|
|
'shareOwner' => $this->getShareOwner(),
|
|
'token' => $this->getToken(),
|
|
'childId' => $this->getChildId(),
|
|
'childFileTarget' => $this->getChildFileTarget(),
|
|
'childPermissions' => $this->getChildPermissions()
|
|
];
|
|
|
|
if ($this->hasOwner()) {
|
|
$arr['owner'] = $this->getOwner();
|
|
}
|
|
|
|
if ($this->hasCircle()) {
|
|
$arr['circle'] = $this->getCircle();
|
|
}
|
|
|
|
if ($this->hasInitiator()) {
|
|
$arr['viewer'] = $this->getInitiator();
|
|
}
|
|
|
|
if ($this->hasFileCache()) {
|
|
$arr['fileCache'] = $this->getFileCache();
|
|
}
|
|
|
|
if ($this->hasShareToken()) {
|
|
$arr['shareToken'] = $this->getShareToken();
|
|
}
|
|
|
|
return $arr;
|
|
}
|
|
}
|