805 lines
23 KiB
PHP
805 lines
23 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* SPDX-FileCopyrightText: 2017 F7cloud GmbH and F7cloud contributors
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
namespace OCA\Circles;
|
|
|
|
use Exception;
|
|
use OCA\Circles\Exceptions\CircleNotFoundException;
|
|
use OCA\Circles\Exceptions\ContactAddressBookNotFoundException;
|
|
use OCA\Circles\Exceptions\ContactFormatException;
|
|
use OCA\Circles\Exceptions\ContactNotFoundException;
|
|
use OCA\Circles\Exceptions\FederatedEventException;
|
|
use OCA\Circles\Exceptions\FederatedItemException;
|
|
use OCA\Circles\Exceptions\FederatedUserException;
|
|
use OCA\Circles\Exceptions\FederatedUserNotFoundException;
|
|
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
|
|
use OCA\Circles\Exceptions\InitiatorNotFoundException;
|
|
use OCA\Circles\Exceptions\InvalidIdException;
|
|
use OCA\Circles\Exceptions\OwnerNotFoundException;
|
|
use OCA\Circles\Exceptions\RemoteInstanceException;
|
|
use OCA\Circles\Exceptions\RemoteNotFoundException;
|
|
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
|
|
use OCA\Circles\Exceptions\RequestBuilderException;
|
|
use OCA\Circles\Exceptions\ShareWrapperNotFoundException;
|
|
use OCA\Circles\Exceptions\SingleCircleNotFoundException;
|
|
use OCA\Circles\Exceptions\UnknownRemoteException;
|
|
use OCA\Circles\FederatedItems\Files\FileShare;
|
|
use OCA\Circles\FederatedItems\Files\FileUnshare;
|
|
use OCA\Circles\Model\Federated\FederatedEvent;
|
|
use OCA\Circles\Model\Member;
|
|
use OCA\Circles\Model\Probes\CircleProbe;
|
|
use OCA\Circles\Model\Probes\DataProbe;
|
|
use OCA\Circles\Model\ShareWrapper;
|
|
use OCA\Circles\Service\CircleService;
|
|
use OCA\Circles\Service\EventService;
|
|
use OCA\Circles\Service\FederatedEventService;
|
|
use OCA\Circles\Service\FederatedUserService;
|
|
use OCA\Circles\Service\ShareTokenService;
|
|
use OCA\Circles\Service\ShareWrapperService;
|
|
use OCA\Circles\Tools\Traits\TArrayTools;
|
|
use OCA\Circles\Tools\Traits\TNCLogger;
|
|
use OCA\Circles\Tools\Traits\TStringTools;
|
|
use OCP\Files\Folder;
|
|
use OCP\Files\InvalidPathException;
|
|
use OCP\Files\IRootFolder;
|
|
use OCP\Files\Node;
|
|
use OCP\Files\NotFoundException;
|
|
use OCP\IL10N;
|
|
use OCP\IURLGenerator;
|
|
use OCP\IUserManager;
|
|
use OCP\Share\Exceptions\AlreadySharedException;
|
|
use OCP\Share\Exceptions\IllegalIDChangeException;
|
|
use OCP\Share\Exceptions\ShareNotFound;
|
|
use OCP\Share\IShare;
|
|
use OCP\Share\IShareProvider;
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
/**
|
|
* Class ShareByCircleProvider
|
|
*
|
|
* @package OCA\Circles
|
|
*/
|
|
class ShareByCircleProvider implements IShareProvider {
|
|
use TArrayTools;
|
|
use TStringTools;
|
|
use TNCLogger;
|
|
|
|
public const IDENTIFIER = 'ocCircleShare';
|
|
|
|
public function __construct(
|
|
private IUserManager $userManager,
|
|
private IRootFolder $rootFolder,
|
|
private IL10N $l10n,
|
|
private LoggerInterface $logger,
|
|
private IURLGenerator $urlGenerator,
|
|
private ShareWrapperService $shareWrapperService,
|
|
private ShareTokenService $shareTokenService,
|
|
private FederatedUserService $federatedUserService,
|
|
private FederatedEventService $federatedEventService,
|
|
private CircleService $circleService,
|
|
private EventService $eventService,
|
|
) {
|
|
}
|
|
|
|
public function identifier(): string {
|
|
return self::IDENTIFIER;
|
|
}
|
|
|
|
/**
|
|
* @param IShare $share
|
|
*
|
|
* @return IShare
|
|
* @throws AlreadySharedException
|
|
* @throws CircleNotFoundException
|
|
* @throws FederatedEventException
|
|
* @throws FederatedItemException
|
|
* @throws InitiatorNotConfirmedException
|
|
* @throws OwnerNotFoundException
|
|
* @throws RemoteInstanceException
|
|
* @throws RemoteNotFoundException
|
|
* @throws RemoteResourceNotFoundException
|
|
* @throws UnknownRemoteException
|
|
* @throws FederatedUserException
|
|
* @throws FederatedUserNotFoundException
|
|
* @throws IllegalIDChangeException
|
|
* @throws InitiatorNotFoundException
|
|
* @throws InvalidIdException
|
|
* @throws InvalidPathException
|
|
* @throws NotFoundException
|
|
* @throws RequestBuilderException
|
|
* @throws ShareNotFound
|
|
* @throws SingleCircleNotFoundException
|
|
*/
|
|
public function create(IShare $share): IShare {
|
|
if ($share->getShareType() !== IShare::TYPE_CIRCLE) {
|
|
return $share;
|
|
}
|
|
|
|
$nodeId = $share->getNode()
|
|
->getId();
|
|
|
|
try {
|
|
$knowShareWrapper = $this->shareWrapperService->searchShare($share->getSharedWith(), $nodeId);
|
|
throw new AlreadySharedException(
|
|
$this->l10n->t('This item is already shared with this team'),
|
|
$knowShareWrapper->getShare($this->rootFolder, $this->userManager, $this->urlGenerator)
|
|
);
|
|
} catch (ShareWrapperNotFoundException $e) {
|
|
}
|
|
|
|
$this->federatedUserService->initCurrentUser();
|
|
$circleProbe = new CircleProbe();
|
|
$dataProbe = new DataProbe();
|
|
$dataProbe->add(DataProbe::OWNER)
|
|
->add(DataProbe::INITIATOR, [DataProbe::BASED_ON]);
|
|
|
|
$circle = $this->circleService->probeCircle($share->getSharedWith(), $circleProbe, $dataProbe);
|
|
$share->setToken($this->token(15));
|
|
$share->setMailSend(true);
|
|
$owner = $circle->getInitiator();
|
|
$this->shareWrapperService->save($share);
|
|
|
|
try {
|
|
$wrappedShare = $this->shareWrapperService->getShareById((int)$share->getId());
|
|
$wrappedShare->setOwner($owner);
|
|
} catch (ShareWrapperNotFoundException $e) {
|
|
throw new ShareNotFound();
|
|
}
|
|
|
|
$event = new FederatedEvent(FileShare::class);
|
|
$event->setCircle($circle);
|
|
$event->getParams()->sObj('wrappedShare', $wrappedShare);
|
|
|
|
$this->federatedEventService->newEvent($event);
|
|
$this->eventService->localShareCreated($wrappedShare);
|
|
|
|
return $wrappedShare->getShare($this->rootFolder, $this->userManager, $this->urlGenerator);
|
|
}
|
|
|
|
/**
|
|
* @param IShare $share
|
|
*
|
|
* @return IShare
|
|
* @throws IllegalIDChangeException
|
|
* @throws ShareWrapperNotFoundException
|
|
* @throws RequestBuilderException
|
|
*/
|
|
public function update(IShare $share): IShare {
|
|
$wrappedShare = $this->shareWrapperService->getShareById((int)$share->getId());
|
|
$wrappedShare->setPermissions($share->getPermissions())
|
|
->setShareOwner($share->getShareOwner())
|
|
->setAttributes($share->getAttributes())
|
|
->setSharedBy($share->getSharedBy())
|
|
->setExpirationDate($share->getExpirationDate())
|
|
->setShareNote($share->getNote());
|
|
|
|
$this->shareWrapperService->update($wrappedShare);
|
|
$this->shareWrapperService->updateChildPermissions($wrappedShare);
|
|
|
|
return $wrappedShare->getShare($this->rootFolder, $this->userManager, $this->urlGenerator);
|
|
}
|
|
|
|
/**
|
|
* @param IShare $share
|
|
*
|
|
* @throws FederatedEventException
|
|
* @throws FederatedItemException
|
|
* @throws FederatedUserException
|
|
* @throws FederatedUserNotFoundException
|
|
* @throws InitiatorNotConfirmedException
|
|
* @throws InvalidIdException
|
|
* @throws OwnerNotFoundException
|
|
* @throws RemoteInstanceException
|
|
* @throws RemoteNotFoundException
|
|
* @throws RemoteResourceNotFoundException
|
|
* @throws RequestBuilderException
|
|
* @throws SingleCircleNotFoundException
|
|
* @throws UnknownRemoteException
|
|
*/
|
|
public function delete(IShare $share): void {
|
|
if ($share->getShareType() !== IShare::TYPE_CIRCLE) {
|
|
return;
|
|
}
|
|
|
|
$this->federatedUserService->initCurrentUser();
|
|
try {
|
|
$wrappedShare = $this->shareWrapperService->getShareById((int)$share->getId());
|
|
} catch (ShareWrapperNotFoundException $e) {
|
|
return;
|
|
}
|
|
|
|
$this->shareWrapperService->delete($wrappedShare);
|
|
|
|
try {
|
|
$circle = $this->circleService->getCircle($share->getSharedWith());
|
|
} catch (CircleNotFoundException $e) {
|
|
return;
|
|
} catch (InitiatorNotFoundException $e) {
|
|
// force the unshare ?
|
|
return;
|
|
}
|
|
|
|
$event = new FederatedEvent(FileUnshare::class);
|
|
$event->setCircle($circle)
|
|
->getParams()->sObj('wrappedShare', $wrappedShare);
|
|
|
|
$this->federatedEventService->newEvent($event);
|
|
$this->eventService->localShareDeleted($wrappedShare);
|
|
}
|
|
|
|
/**
|
|
* @param IShare $share
|
|
* @param string $recipient
|
|
*
|
|
* @throws ContactAddressBookNotFoundException
|
|
* @throws ContactFormatException
|
|
* @throws ContactNotFoundException
|
|
* @throws FederatedUserException
|
|
* @throws FederatedUserNotFoundException
|
|
* @throws InvalidIdException
|
|
* @throws NotFoundException
|
|
* @throws RequestBuilderException
|
|
* @throws ShareWrapperNotFoundException
|
|
* @throws SingleCircleNotFoundException
|
|
*/
|
|
public function deleteFromSelf(IShare $share, $recipient): void {
|
|
$federatedUser = $this->federatedUserService->getLocalFederatedUser($recipient);
|
|
$child = $this->shareWrapperService->getChild($share, $federatedUser);
|
|
$this->debug('Shares::move()', ['federatedUser' => $federatedUser, 'child' => $child]);
|
|
|
|
if ($child->getPermissions() > 0) {
|
|
$child->setPermissions(0);
|
|
$this->shareWrapperService->update($child);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @param IShare $share
|
|
* @param string $recipient
|
|
*
|
|
* @return IShare
|
|
* @throws ContactAddressBookNotFoundException
|
|
* @throws ContactFormatException
|
|
* @throws ContactNotFoundException
|
|
* @throws FederatedUserException
|
|
* @throws FederatedUserNotFoundException
|
|
* @throws IllegalIDChangeException
|
|
* @throws InvalidIdException
|
|
* @throws NotFoundException
|
|
* @throws RequestBuilderException
|
|
* @throws ShareWrapperNotFoundException
|
|
* @throws SingleCircleNotFoundException
|
|
*/
|
|
public function move(IShare $share, $recipient): IShare {
|
|
$federatedUser = $this->federatedUserService->getLocalFederatedUser($recipient);
|
|
$child = $this->shareWrapperService->getChild($share, $federatedUser);
|
|
$this->debug('Shares::move()', ['federatedUser' => $federatedUser, 'child' => $child]);
|
|
|
|
if ($child->getFileTarget() !== $share->getTarget()) {
|
|
$child->setFileTarget($share->getTarget());
|
|
$this->shareWrapperService->update($child);
|
|
}
|
|
|
|
$wrappedShare = $this->shareWrapperService->getShareById((int)$share->getId(), $federatedUser);
|
|
|
|
return $wrappedShare->getShare($this->rootFolder, $this->userManager, $this->urlGenerator);
|
|
}
|
|
|
|
|
|
/**
|
|
* @param IShare $share
|
|
* @param string $recipient
|
|
*
|
|
* @return IShare
|
|
*/
|
|
public function restore(IShare $share, string $recipient): IShare {
|
|
$orig = $this->shareWrapperService->getShareById((int)$share->getId());
|
|
|
|
$federatedUser = $this->federatedUserService->getLocalFederatedUser($recipient);
|
|
$child = $this->shareWrapperService->getChild($share, $federatedUser);
|
|
$this->debug('Shares::restore()', ['federatedUser' => $federatedUser, 'child' => $child]);
|
|
|
|
if ($child->getPermissions() !== $orig->getPermissions()) {
|
|
$child->setPermissions($orig->getPermissions());
|
|
$this->shareWrapperService->update($child);
|
|
}
|
|
|
|
$wrappedShare = $this->shareWrapperService->getShareById((int)$share->getId(), $federatedUser);
|
|
|
|
return $wrappedShare->getShare($this->rootFolder, $this->userManager, $this->urlGenerator);
|
|
}
|
|
|
|
|
|
/**
|
|
* @param string $userId
|
|
* @param Folder $node
|
|
* @param bool $reshares
|
|
* @param bool $shallow Whether the method should stop at the first level, or look into sub-folders.
|
|
*
|
|
* @return array
|
|
* @throws ContactAddressBookNotFoundException
|
|
* @throws ContactFormatException
|
|
* @throws ContactNotFoundException
|
|
* @throws FederatedUserException
|
|
* @throws FederatedUserNotFoundException
|
|
* @throws IllegalIDChangeException
|
|
* @throws InvalidIdException
|
|
* @throws InvalidPathException
|
|
* @throws NotFoundException
|
|
* @throws RequestBuilderException
|
|
* @throws SingleCircleNotFoundException
|
|
*/
|
|
public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true): array {
|
|
$federatedUser = $this->federatedUserService->getLocalFederatedUser($userId);
|
|
$wrappedShares = $this->shareWrapperService->getSharesInFolder(
|
|
$federatedUser,
|
|
$node,
|
|
$reshares,
|
|
$shallow
|
|
);
|
|
|
|
$result = [];
|
|
foreach ($wrappedShares as $wrappedShare) {
|
|
if (!array_key_exists($wrappedShare->getFileSource(), $result)) {
|
|
$result[$wrappedShare->getFileSource()] = [];
|
|
}
|
|
if ($wrappedShare->getFileCache()->isAccessible()) {
|
|
$result[$wrappedShare->getFileSource()][] =
|
|
$wrappedShare->getShare($this->rootFolder, $this->userManager, $this->urlGenerator);
|
|
} else {
|
|
$this->logger->debug('shared document is not available anymore', ['wrappedShare' => $wrappedShare]);
|
|
if ($wrappedShare->getFileCache()->getPath() === '') {
|
|
$this->logger->notice('share is not available while path is empty. might comes from an unsupported storage.', ['wrappedShare' => $wrappedShare]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
|
|
/**
|
|
* @param string $userId
|
|
* @param int $shareType
|
|
* @param Node|null $node
|
|
* @param bool $reshares
|
|
* @param int $limit
|
|
* @param int $offset
|
|
*
|
|
* @return IShare[]
|
|
* @throws ContactAddressBookNotFoundException
|
|
* @throws ContactFormatException
|
|
* @throws ContactNotFoundException
|
|
* @throws FederatedUserException
|
|
* @throws FederatedUserNotFoundException
|
|
* @throws IllegalIDChangeException
|
|
* @throws InvalidIdException
|
|
* @throws InvalidPathException
|
|
* @throws NotFoundException
|
|
* @throws RequestBuilderException
|
|
* @throws SingleCircleNotFoundException
|
|
*/
|
|
public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset): array {
|
|
if ($shareType !== IShare::TYPE_CIRCLE) {
|
|
return [];
|
|
}
|
|
|
|
$nodeId = (!is_null($node)) ? $node->getId() : 0;
|
|
|
|
try {
|
|
$federatedUser = $this->federatedUserService->getLocalFederatedUser($userId);
|
|
} catch (Exception $e) {
|
|
$this->e($e, ['userId' => $userId, 'shareType' => $shareType, 'nodeId' => $nodeId]);
|
|
|
|
return [];
|
|
}
|
|
|
|
$wrappedShares = $this->shareWrapperService->getSharesBy(
|
|
$federatedUser,
|
|
$nodeId,
|
|
$reshares,
|
|
$limit,
|
|
$offset,
|
|
true
|
|
);
|
|
|
|
return array_filter(
|
|
array_map(
|
|
function (ShareWrapper $wrapper) {
|
|
return $wrapper->getShare($this->rootFolder, $this->userManager, $this->urlGenerator);
|
|
}, $wrappedShares
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
* @param string $shareId
|
|
* @param string|null $recipientId
|
|
*
|
|
* @return IShare
|
|
* @throws FederatedUserException
|
|
* @throws FederatedUserNotFoundException
|
|
* @throws IllegalIDChangeException
|
|
* @throws InvalidIdException
|
|
* @throws ShareNotFound
|
|
* @throws SingleCircleNotFoundException
|
|
* @throws RequestBuilderException
|
|
*/
|
|
public function getShareById($shareId, $recipientId = null): IShare {
|
|
if (is_null($recipientId)) {
|
|
$federatedUser = null;
|
|
} else {
|
|
$federatedUser = $this->federatedUserService->getLocalFederatedUser($recipientId);
|
|
}
|
|
|
|
try {
|
|
$wrappedShare = $this->shareWrapperService->getShareById((int)$shareId, $federatedUser);
|
|
} catch (ShareWrapperNotFoundException $e) {
|
|
throw new ShareNotFound();
|
|
}
|
|
|
|
return $wrappedShare->getShare($this->rootFolder, $this->userManager, $this->urlGenerator);
|
|
}
|
|
|
|
|
|
/**
|
|
* @param Node $path
|
|
*
|
|
* @return IShare[]
|
|
* @throws InvalidPathException
|
|
* @throws NotFoundException
|
|
* @throws IllegalIDChangeException
|
|
* @throws RequestBuilderException
|
|
*/
|
|
public function getSharesByPath(Node $path): array {
|
|
$wrappedShares = $this->shareWrapperService->getSharesByFileId($path->getId(), true);
|
|
|
|
return array_filter(
|
|
array_map(
|
|
function (ShareWrapper $wrapper) {
|
|
return $wrapper->getShare($this->rootFolder, $this->userManager, $this->urlGenerator);
|
|
}, $wrappedShares
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
* @param string $userId
|
|
* @param int $shareType
|
|
* @param Node|null $node
|
|
* @param int $limit
|
|
* @param int $offset
|
|
*
|
|
* @return IShare[]
|
|
* @throws ContactAddressBookNotFoundException
|
|
* @throws ContactFormatException
|
|
* @throws ContactNotFoundException
|
|
* @throws FederatedUserException
|
|
* @throws FederatedUserNotFoundException
|
|
* @throws IllegalIDChangeException
|
|
* @throws InvalidIdException
|
|
* @throws InvalidPathException
|
|
* @throws NotFoundException
|
|
* @throws RequestBuilderException
|
|
* @throws SingleCircleNotFoundException
|
|
*/
|
|
public function getSharedWith($userId, $shareType, $node, $limit, $offset): array {
|
|
if ($shareType !== IShare::TYPE_CIRCLE) {
|
|
return [];
|
|
}
|
|
|
|
$federatedUser = $this->federatedUserService->getLocalFederatedUser($userId);
|
|
$probe = new CircleProbe();
|
|
$probe->includePersonalCircles()
|
|
->includeSystemCircles()
|
|
->mustBeMember()
|
|
->setItemsLimit((int)$limit)
|
|
->setItemsOffset((int)$offset);
|
|
|
|
$wrappedShares = $this->shareWrapperService->getSharedWith(
|
|
$federatedUser,
|
|
(!is_null($node)) ? $node->getId() : 0,
|
|
$probe
|
|
);
|
|
|
|
return array_filter(
|
|
array_map(
|
|
function (ShareWrapper $wrapper) {
|
|
return $wrapper->getShare(
|
|
$this->rootFolder, $this->userManager, $this->urlGenerator, true
|
|
);
|
|
}, $wrappedShares
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
* @param string $token
|
|
*
|
|
* @return IShare
|
|
* @throws IllegalIDChangeException
|
|
* @throws RequestBuilderException
|
|
* @throws ShareNotFound
|
|
*/
|
|
public function getShareByToken($token): IShare {
|
|
if (is_null($token)) {
|
|
throw new ShareNotFound();
|
|
}
|
|
|
|
try {
|
|
$wrappedShare = $this->shareWrapperService->getShareByToken($token);
|
|
} catch (ShareWrapperNotFoundException $e) {
|
|
throw new ShareNotFound();
|
|
}
|
|
|
|
$share = $wrappedShare->getShare($this->rootFolder, $this->userManager, $this->urlGenerator);
|
|
if ($share->getPassword() !== '') {
|
|
$this->logger->notice('share is protected by a password, hash: ' . $share->getPassword());
|
|
}
|
|
|
|
return $share;
|
|
}
|
|
|
|
|
|
public function formatShare(IShare $share): array {
|
|
$this->federatedUserService->initCurrentUser();
|
|
$circleProbe = new CircleProbe();
|
|
$dataProbe = new DataProbe();
|
|
|
|
$result = ['share_with' => $share->getSharedWith()];
|
|
try {
|
|
$circle = $this->circleService->probeCircle($share->getSharedWith(), $circleProbe, $dataProbe);
|
|
$result['share_with_displayname'] = $circle->getDisplayName();
|
|
} catch (Exception $e) {
|
|
$this->logger->warning(
|
|
'Circle not found while probeCircle',
|
|
[
|
|
'sharedWith' => $share->getSharedWith(),
|
|
'exception' => $e
|
|
]
|
|
);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
|
|
/**
|
|
* @param string $uid
|
|
* @param int $shareType
|
|
*/
|
|
public function userDeleted($uid, $shareType): void {
|
|
}
|
|
|
|
|
|
/**
|
|
* @param string $gid
|
|
*/
|
|
public function groupDeleted($gid): void {
|
|
}
|
|
|
|
|
|
/**
|
|
* @param string $uid
|
|
* @param string $gid
|
|
*/
|
|
public function userDeletedFromGroup($uid, $gid): void {
|
|
}
|
|
|
|
|
|
/**
|
|
* if $currentAccess, returns long version of the access list:
|
|
* [
|
|
* 'users' => [
|
|
* 'user1' => ['node_id' => 42, 'node_path' => '/fileA'],
|
|
* 'user4' => ['node_id' => 32, 'node_path' => '/folder2'],
|
|
* 'user2' => ['node_id' => 23, 'node_path' => '/folder (1)'],
|
|
* ],
|
|
* 'remote' => [
|
|
* 'user1@server1' => ['node_id' => 42, 'token' => 'SeCr3t'],
|
|
* 'user2@server2' => ['node_id' => 23, 'token' => 'FooBaR'],
|
|
* ],
|
|
* 'public' => bool,
|
|
* 'mail' => [
|
|
* 'email1@maildomain1' => ['node_id' => 42, 'token' => 'aBcDeFg'],
|
|
* 'email2@maildomain2' => ['node_id' => 23, 'token' => 'hIjKlMn'],
|
|
* ]
|
|
* ]
|
|
*
|
|
*
|
|
*
|
|
*
|
|
* @param Node[] $nodes
|
|
* @param bool $currentAccess
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getAccessList($nodes, $currentAccess): array {
|
|
$ids = [];
|
|
foreach ($nodes as $node) {
|
|
$ids[] = $node->getId();
|
|
}
|
|
|
|
|
|
if (!$currentAccess) {
|
|
return $this->getAccessListShort($ids);
|
|
}
|
|
|
|
$shareIds = $knownIds = $users = $remote = $mails = [];
|
|
foreach ($this->shareWrapperService->getSharesByFileIds($ids, true, true) as $share) {
|
|
if (!$share->hasCircle()) {
|
|
continue;
|
|
}
|
|
|
|
$shareIds[] = $share->getId();
|
|
$circle = $share->getCircle();
|
|
foreach ($circle->getInheritedMembers() as $member) {
|
|
if ($share->getParent() > 0 && in_array($member->getSingleId(), $knownIds[$share->getFileSource()] ?? [])) {
|
|
continue;
|
|
}
|
|
$knownIds[$share->getFileSource()][] = $member->getSingleId();
|
|
|
|
switch ($member->getUserType()) {
|
|
case Member::TYPE_USER:
|
|
if ($member->isLocal()) {
|
|
$users[$member->getUserId()] = [
|
|
'node_id' => $share->getFileSource(),
|
|
'node_path' => $share->getFileTarget()
|
|
];
|
|
} else {
|
|
// we only store temp value, as token is unknown at this point
|
|
$remote[$member->getUserid() . '@' . $member->getInstance()] = [
|
|
'node_id' => $share->getFileSource(),
|
|
'shareId' => $share->getId(),
|
|
'memberId' => $member->getId(),
|
|
];
|
|
}
|
|
break;
|
|
case Member::TYPE_MAIL:
|
|
// we only store temp value, as token is unknown at this point
|
|
$mails[$member->getUserId()] = [
|
|
'node_id' => $share->getFileSource(),
|
|
'shareId' => $share->getId(),
|
|
'memberId' => $member->getId(),
|
|
];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// list share tokens in an indexed array and update details for remote/mail entries with the correct token
|
|
$shareTokens = [];
|
|
foreach ($this->shareTokenService->getTokensFromShares(array_values(array_unique($shareIds))) as $shareToken) {
|
|
$shareTokens[$shareToken->getShareId()][$shareToken->getMemberId()] = $shareToken->getToken();
|
|
}
|
|
|
|
return [
|
|
'users' => $users,
|
|
'remote' => $this->updateAccessListTokens($remote, $shareTokens),
|
|
'email' => $this->updateAccessListTokens($mails, $shareTokens)
|
|
];
|
|
}
|
|
|
|
/**
|
|
* returns short version of the access list:
|
|
* [
|
|
* 'users' => ['user1', 'user2', 'user4'],
|
|
* 'remote' => bool,
|
|
* 'mail' => ['email1@maildomain1', 'email2@maildomain2']
|
|
* ]
|
|
*
|
|
* @param array $ids
|
|
*
|
|
* @return array
|
|
* @throws FederatedItemException
|
|
* @throws RemoteInstanceException
|
|
* @throws RemoteNotFoundException
|
|
* @throws RemoteResourceNotFoundException
|
|
* @throws RequestBuilderException
|
|
* @throws UnknownRemoteException
|
|
*/
|
|
private function getAccessListShort(array $ids): array {
|
|
$users = $mails = [];
|
|
$remote = false;
|
|
foreach ($this->shareWrapperService->getSharesByFileIds($ids, true) as $share) {
|
|
if (!$share->hasCircle()) {
|
|
continue;
|
|
}
|
|
$circle = $share->getCircle();
|
|
foreach ($circle->getInheritedMembers() as $member) {
|
|
switch ($member->getUserType()) {
|
|
case Member::TYPE_USER:
|
|
if ($member->isLocal()) {
|
|
if (!in_array($member->getUserId(), $users)) {
|
|
$users[] = $member->getUserId();
|
|
}
|
|
} else {
|
|
$remote = true;
|
|
}
|
|
break;
|
|
case Member::TYPE_MAIL:
|
|
if (!in_array($member->getUserId(), $mails)) {
|
|
$mails[] = $member->getUserId();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return [
|
|
'users' => $users,
|
|
'remote' => $remote,
|
|
'email' => $mails
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param array $list
|
|
* @param array<int, array<string, string>> $shareTokens
|
|
*
|
|
* @return array
|
|
*/
|
|
private function updateAccessListTokens(array $list, array $shareTokens): array {
|
|
$result = [];
|
|
foreach ($list as $id => $data) {
|
|
$result[$id] = [
|
|
'node_id' => $data['node_id'],
|
|
'token' => $shareTokens[$data['shareId']][$data['memberId']]
|
|
];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* We don't return a thing about children.
|
|
* The call to this function is deprecated and should be removed in next release of NC.
|
|
* Also, we get the children in the delete() method.
|
|
*
|
|
* @param IShare $parent
|
|
*
|
|
* @return IShare[]
|
|
*/
|
|
public function getChildren(IShare $parent): array {
|
|
return [];
|
|
}
|
|
|
|
|
|
/**
|
|
* @return iterable
|
|
*/
|
|
public function getAllShares(): iterable {
|
|
// $qb = $this->dbConnection->getQueryBuilder();
|
|
//
|
|
// $qb->select(' * ')
|
|
// ->from('share')
|
|
// ->where(
|
|
// $qb->expr()
|
|
// ->orX(
|
|
// $qb->expr()
|
|
// ->eq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE))
|
|
// )
|
|
// );
|
|
//
|
|
// $cursor = $qb->execute();
|
|
// while ($data = $cursor->fetch()) {
|
|
// try {
|
|
// yield $this->createShareObject($data);
|
|
// } catch (IllegalIDChangeException $e) {
|
|
// };
|
|
// }
|
|
// $cursor->closeCursor();
|
|
return [];
|
|
}
|
|
}
|