summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/files_sharing/lib/Controller/ShareAPIController.php16
-rw-r--r--apps/files_sharing/lib/Notification/Listener.php5
-rw-r--r--apps/files_sharing/lib/Notification/Notifier.php94
-rw-r--r--lib/private/Share20/DefaultShareProvider.php125
-rw-r--r--lib/private/Share20/Manager.php24
-rw-r--r--lib/public/Share/IManager.php12
-rw-r--r--lib/public/Share/IShareProvider.php10
7 files changed, 230 insertions, 56 deletions
diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php
index acb95a0a3d3..9c5f6abee68 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -962,19 +962,17 @@ class ShareAPIController extends OCSController {
throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
}
- if (!$this->canAccessShare($share, false)) {
+ if (!$this->canAccessShare($share)) {
throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
}
- if ($share->getShareType() !== Share::SHARE_TYPE_USER ||
- $share->getSharedWith() !== $this->currentUser) {
- throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
+ if ($share->getShareType() !== IShare::TYPE_USER &&
+ $share->getShareType() !== IShare::TYPE_GROUP) {
+ throw new OCSNotFoundException($this->l->t('Share type does not support accepting'));
}
- $share->setStatus(IShare::STATUS_ACCEPTED);
-
try {
- $this->shareManager->updateShare($share);
+ $this->shareManager->acceptShare($share, $this->currentUser);
} catch (GenericShareException $e) {
$code = $e->getCode() === 0 ? 403 : $e->getCode();
throw new OCSException($e->getHint(), $code);
@@ -1117,8 +1115,8 @@ class ShareAPIController extends OCSController {
* @suppress PhanUndeclaredClassMethod
*/
protected function canDeleteShareFromSelf(\OCP\Share\IShare $share): bool {
- if ($share->getShareType() !== Share::SHARE_TYPE_GROUP &&
- $share->getShareType() !== Share::SHARE_TYPE_ROOM
+ if ($share->getShareType() !== IShare::TYPE_GROUP &&
+ $share->getShareType() !== IShare::TYPE_ROOM
) {
return false;
}
diff --git a/apps/files_sharing/lib/Notification/Listener.php b/apps/files_sharing/lib/Notification/Listener.php
index b2e00613e70..fd4daca28e7 100644
--- a/apps/files_sharing/lib/Notification/Listener.php
+++ b/apps/files_sharing/lib/Notification/Listener.php
@@ -63,6 +63,11 @@ class Listener {
$group = $this->groupManager->get($share->getSharedWith());
foreach ($group->getUsers() as $user) {
+ if ($user->getUID() === $share->getShareOwner() ||
+ $user->getUID() === $share->getSharedBy()) {
+ continue;
+ }
+
$notification->setUser($user->getUID());
$this->notificationManager->notify($notification);
}
diff --git a/apps/files_sharing/lib/Notification/Notifier.php b/apps/files_sharing/lib/Notification/Notifier.php
index 6ae009895d3..03d7038e6fe 100644
--- a/apps/files_sharing/lib/Notification/Notifier.php
+++ b/apps/files_sharing/lib/Notification/Notifier.php
@@ -28,7 +28,10 @@ namespace OCA\Files_Sharing\Notification;
use OCP\Files\IRootFolder;
use OCP\IL10N;
+use OCP\IGroupManager;
use OCP\IURLGenerator;
+use OCP\IUser;
+use OCP\IUserManager;
use OCP\L10N\IFactory;
use OCP\Notification\AlreadyProcessedException;
use OCP\Notification\INotification;
@@ -45,6 +48,10 @@ class Notifier implements INotifier {
private $shareManager;
/** @var IRootFolder */
private $rootFolder;
+ /** @var IGroupManager */
+ protected $groupManager;
+ /** @var IUserManager */
+ protected $userManager;
/** @var IURLGenerator */
protected $url;
@@ -52,10 +59,14 @@ class Notifier implements INotifier {
public function __construct(IFactory $l10nFactory,
IManager $shareManager,
IRootFolder $rootFolder,
+ IGroupManager $groupManager,
+ IUserManager $userManager,
IURLGenerator $url) {
$this->l10nFactory = $l10nFactory;
$this->shareManager = $shareManager;
$this->rootFolder = $rootFolder;
+ $this->groupManager = $groupManager;
+ $this->userManager = $userManager;
$this->url = $url;
}
@@ -135,11 +146,12 @@ class Notifier implements INotifier {
}
protected function parseShareInvitation(IShare $share, INotification $notification, IL10N $l): INotification {
+
if ($share->getShareType() === IShare::TYPE_USER) {
- if ($share->getSharedWith() !== $notification->getUser()) {
+ if ($share->getStatus() !== IShare::STATUS_PENDING) {
throw new AlreadyProcessedException();
}
-
+ } else if ($share->getShareType() === IShare::TYPE_GROUP) {
if ($share->getStatus() !== IShare::STATUS_PENDING) {
throw new AlreadyProcessedException();
}
@@ -147,6 +159,10 @@ class Notifier implements INotifier {
switch ($notification->getSubject()) {
case 'incoming_user_share':
+ if ($share->getSharedWith() !== $notification->getUser()) {
+ throw new AlreadyProcessedException();
+ }
+
$subject = $l->t('You received {share} as a share from {user}');
$subjectParameters = [
'share' => [
@@ -160,34 +176,70 @@ class Notifier implements INotifier {
'name' => $share->getShareOwner(),
],
];
+ break;
- $placeholders = $replacements = [];
- foreach ($subjectParameters as $placeholder => $parameter) {
- $placeholders[] = '{' . $placeholder . '}';
- $replacements[] = $parameter['name'];
+ case 'incoming_group_share':
+ $user = $this->userManager->get($notification->getUser());
+ if (!$user instanceof IUser) {
+ throw new AlreadyProcessedException();
}
- $notification->setParsedSubject(str_replace($placeholders, $replacements, $subject))
- ->setRichSubject($subject, $subjectParameters)
- ->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/share.svg')));
-
- $acceptAction = $notification->createAction();
- $acceptAction->setParsedLabel($l->t('Accept'))
- ->setLink($this->url->linkToOCSRouteAbsolute('files_sharing.ShareAPI.acceptShare', ['id' => $share->getId()]), 'POST')
- ->setPrimary(true);
- $notification->addParsedAction($acceptAction);
+ $group = $this->groupManager->get($share->getSharedWith());
+ if (!$group->inGroup($user)) {
+ throw new AlreadyProcessedException();
+ }
- $rejectAction = $notification->createAction();
- $rejectAction->setParsedLabel($l->t('Reject'))
- ->setLink($this->url->linkToOCSRouteAbsolute('files_sharing.ShareAPI.deleteShare', ['id' => $share->getId()]), 'DELETE')
- ->setPrimary(false);
- $notification->addParsedAction($rejectAction);
+ if ($share->getPermissions() === 0) {
+ // Already rejected
+ throw new AlreadyProcessedException();
+ }
- return $notification;
+ $subject = $l->t('You received {share} to group {group} as a share from {user}');
+ $subjectParameters = [
+ 'share' => [
+ 'type' => 'highlight',
+ 'id' => $notification->getObjectId(),
+ 'name' => $share->getNode()->getName(),
+ ],
+ 'group' => [
+ 'type' => 'user-group',
+ 'id' => $group->getGID(),
+ 'name' => $group->getDisplayName(),
+ ],
+ 'user' => [
+ 'type' => 'user',
+ 'id' => $share->getShareOwner(),
+ 'name' => $share->getShareOwner(),
+ ],
+ ];
break;
default:
throw new \InvalidArgumentException('Invalid subject');
}
+
+ $placeholders = $replacements = [];
+ foreach ($subjectParameters as $placeholder => $parameter) {
+ $placeholders[] = '{' . $placeholder . '}';
+ $replacements[] = $parameter['name'];
+ }
+
+ $notification->setParsedSubject(str_replace($placeholders, $replacements, $subject))
+ ->setRichSubject($subject, $subjectParameters)
+ ->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/share.svg')));
+
+ $acceptAction = $notification->createAction();
+ $acceptAction->setParsedLabel($l->t('Accept'))
+ ->setLink($this->url->linkToOCSRouteAbsolute('files_sharing.ShareAPI.acceptShare', ['id' => $share->getId()]), 'POST')
+ ->setPrimary(true);
+ $notification->addParsedAction($acceptAction);
+
+ $rejectAction = $notification->createAction();
+ $rejectAction->setParsedLabel($l->t('Reject'))
+ ->setLink($this->url->linkToOCSRouteAbsolute('files_sharing.ShareAPI.deleteShare', ['id' => $share->getId()]), 'DELETE')
+ ->setPrimary(false);
+ $notification->addParsedAction($rejectAction);
+
+ return $notification;
}
}
diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php
index 66d28869dbd..ffcaf4f1065 100644
--- a/lib/private/Share20/DefaultShareProvider.php
+++ b/lib/private/Share20/DefaultShareProvider.php
@@ -321,6 +321,71 @@ class DefaultShareProvider implements IShareProvider {
}
/**
+ * Accept a share.
+ *
+ * @param IShare $share
+ * @param string $recipient
+ * @return IShare The share object
+ * @since 9.0.0
+ */
+ public function acceptShare(IShare $share, string $recipient): IShare {
+ if ($share->getShareType() === IShare::TYPE_GROUP) {
+ $group = $this->groupManager->get($share->getSharedWith());
+ $user = $this->userManager->get($recipient);
+
+ if (is_null($group)) {
+ throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
+ }
+
+ if (!$group->inGroup($user)) {
+ throw new ProviderException('Recipient not in receiving group');
+ }
+
+ // Try to fetch user specific share
+ $qb = $this->dbConn->getQueryBuilder();
+ $stmt = $qb->select('*')
+ ->from('share')
+ ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
+ ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
+ ->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
+ ->andWhere($qb->expr()->orX(
+ $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
+ $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
+ ))
+ ->execute();
+
+ $data = $stmt->fetch();
+
+ /*
+ * Check if there already is a user specific group share.
+ * If there is update it (if required).
+ */
+ if ($data === false) {
+ $id = $this->createUserSpecificGroupShare($share, $recipient);
+ } else {
+ $id = $data['id'];
+ }
+
+ } else if ($share->getShareType() === IShare::TYPE_USER) {
+ if ($share->getSharedWith() !== $recipient) {
+ throw new ProviderException('Recipient does not match');
+ }
+
+ $id = $share->getId();
+ } else {
+ throw new ProviderException('Invalid shareType');
+ }
+
+ $qb = $this->dbConn->getQueryBuilder();
+ $qb->update('share')
+ ->set('accepted', $qb->createNamedParameter(IShare::STATUS_ACCEPTED))
+ ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
+ ->execute();
+
+ return $share;
+ }
+
+ /**
* Get all children of this share
* FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
*
@@ -384,13 +449,13 @@ class DefaultShareProvider implements IShareProvider {
* Unshare a share from the recipient. If this is a group share
* this means we need a special entry in the share db.
*
- * @param \OCP\Share\IShare $share
+ * @param IShare $share
* @param string $recipient UserId of recipient
* @throws BackendError
* @throws ProviderException
*/
- public function deleteFromSelf(\OCP\Share\IShare $share, $recipient) {
- if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
+ public function deleteFromSelf(IShare $share, $recipient) {
+ if ($share->getShareType() === IShare::TYPE_GROUP) {
$group = $this->groupManager->get($share->getSharedWith());
$user = $this->userManager->get($recipient);
@@ -423,37 +488,23 @@ class DefaultShareProvider implements IShareProvider {
* If there is update it (if required).
*/
if ($data === false) {
- $qb = $this->dbConn->getQueryBuilder();
-
- $type = $share->getNodeType();
-
- //Insert new share
- $qb->insert('share')
- ->values([
- 'share_type' => $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP),
- 'share_with' => $qb->createNamedParameter($recipient),
- 'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
- 'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
- 'parent' => $qb->createNamedParameter($share->getId()),
- 'item_type' => $qb->createNamedParameter($type),
- 'item_source' => $qb->createNamedParameter($share->getNodeId()),
- 'file_source' => $qb->createNamedParameter($share->getNodeId()),
- 'file_target' => $qb->createNamedParameter($share->getTarget()),
- 'permissions' => $qb->createNamedParameter(0),
- 'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
- ])->execute();
-
- } else if ($data['permissions'] !== 0) {
+ $id = $this->createUserSpecificGroupShare($share, $recipient);
+ $permissions = $share->getPermissions();
+ } else {
+ $permissions = $data['permissions'];
+ $id = $data['id'];
+ }
+ if ($permissions !== 0) {
// Update existing usergroup share
$qb = $this->dbConn->getQueryBuilder();
$qb->update('share')
->set('permissions', $qb->createNamedParameter(0))
- ->where($qb->expr()->eq('id', $qb->createNamedParameter($data['id'])))
+ ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
->execute();
}
- } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
+ } else if ($share->getShareType() === IShare::TYPE_USER) {
if ($share->getSharedWith() !== $recipient) {
throw new ProviderException('Recipient does not match');
@@ -466,6 +517,28 @@ class DefaultShareProvider implements IShareProvider {
}
}
+ protected function createUserSpecificGroupShare(IShare $share, string $recipient): int {
+ $type = $share->getNodeType();
+
+ $qb = $this->dbConn->getQueryBuilder();
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP),
+ 'share_with' => $qb->createNamedParameter($recipient),
+ 'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
+ 'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
+ 'parent' => $qb->createNamedParameter($share->getId()),
+ 'item_type' => $qb->createNamedParameter($type),
+ 'item_source' => $qb->createNamedParameter($share->getNodeId()),
+ 'file_source' => $qb->createNamedParameter($share->getNodeId()),
+ 'file_target' => $qb->createNamedParameter($share->getTarget()),
+ 'permissions' => $qb->createNamedParameter($share->getPermissions()),
+ 'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
+ ])->execute();
+
+ return $qb->getLastInsertId();
+ }
+
/**
* @inheritdoc
*
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index 728dd60e759..ba370e7724a 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -929,6 +929,30 @@ class Manager implements IManager {
}
/**
+ * Accept a share.
+ *
+ * @param IShare $share
+ * @param string $recipientId
+ * @return IShare The share object
+ * @throws \InvalidArgumentException
+ * @since 9.0.0
+ */
+ public function acceptShare(IShare $share, string $recipientId): IShare {
+ [$providerId, ] = $this->splitFullId($share->getFullId());
+ $provider = $this->factory->getProvider($providerId);
+
+ if (!method_exists($provider, 'acceptShare')) {
+ // TODO FIX ME
+ throw new \InvalidArgumentException('not supported');
+ }
+ $provider->acceptShare($share, $recipientId);
+ $event = new GenericEvent($share);
+ $this->eventDispatcher->dispatch('OCP\Share::postAcceptShare', $event);
+
+ return $share;
+ }
+
+ /**
* Updates the password of the given share if it is not the same as the
* password of the original share.
*
diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php
index 8bb7291d6ba..3127c74be5e 100644
--- a/lib/public/Share/IManager.php
+++ b/lib/public/Share/IManager.php
@@ -54,6 +54,7 @@ interface IManager {
* Update a share.
* The target of the share can't be changed this way: use moveShare
* The share can't be removed this way (permission 0): use deleteShare
+ * The state can't be changed this way: use acceptShare
*
* @param IShare $share
* @return IShare The share object
@@ -63,6 +64,17 @@ interface IManager {
public function updateShare(IShare $share);
/**
+ * Accept a share.
+ *
+ * @param IShare $share
+ * @param string $recipientId
+ * @return IShare The share object
+ * @throws \InvalidArgumentException
+ * @since 18.0.0
+ */
+ public function acceptShare(IShare $share, string $recipientId): IShare;
+
+ /**
* Delete a share
*
* @param IShare $share
diff --git a/lib/public/Share/IShareProvider.php b/lib/public/Share/IShareProvider.php
index c8815928269..49ab4bef3e6 100644
--- a/lib/public/Share/IShareProvider.php
+++ b/lib/public/Share/IShareProvider.php
@@ -64,6 +64,16 @@ interface IShareProvider {
public function update(\OCP\Share\IShare $share);
/**
+ * Accept a share.
+ *
+ * @param IShare $share
+ * @param string $recipient
+ * @return IShare The share object
+ * @since 17.0.0
+ */
+// public function acceptShare(IShare $share, string $recipient): IShare;
+
+ /**
* Delete a share
*
* @param \OCP\Share\IShare $share