aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorRoeland Jago Douma <rullzer@users.noreply.github.com>2019-11-18 20:11:20 +0100
committerGitHub <noreply@github.com>2019-11-18 20:11:20 +0100
commitccc0a5e0d586c8df25edb1a0f3cef20860d71e4f (patch)
tree96ffd796964b18c194b6696f653f1d0d2d3f70f5 /apps
parent5320f08cd2eab3926104a314fb76b2de222d1d7b (diff)
parente16321368f27f3b9534b3fb835fbe6c6fc85077e (diff)
downloadnextcloud-server-ccc0a5e0d586c8df25edb1a0f3cef20860d71e4f.tar.gz
nextcloud-server-ccc0a5e0d586c8df25edb1a0f3cef20860d71e4f.zip
Merge pull request #16828 from nextcloud/feature/noid/accept-incoming-shares
🔗☑️ Accept all incoming shares
Diffstat (limited to 'apps')
-rw-r--r--apps/federatedfilesharing/lib/Notifier.php2
-rw-r--r--apps/files_sharing/appinfo/app.php1
-rw-r--r--apps/files_sharing/appinfo/info.xml3
-rw-r--r--apps/files_sharing/appinfo/routes.php5
-rw-r--r--apps/files_sharing/composer/composer/autoload_classmap.php2
-rw-r--r--apps/files_sharing/composer/composer/autoload_static.php2
-rw-r--r--apps/files_sharing/lib/AppInfo/Application.php17
-rw-r--r--apps/files_sharing/lib/Controller/ShareAPIController.php36
-rw-r--r--apps/files_sharing/lib/External/Manager.php5
-rw-r--r--apps/files_sharing/lib/Migration/SetAcceptedStatus.php79
-rw-r--r--apps/files_sharing/lib/MountProvider.php16
-rw-r--r--apps/files_sharing/lib/Notification/Listener.php131
-rw-r--r--apps/files_sharing/lib/Notification/Notifier.php169
13 files changed, 456 insertions, 12 deletions
diff --git a/apps/federatedfilesharing/lib/Notifier.php b/apps/federatedfilesharing/lib/Notifier.php
index 02a46d65bba..1916390a1ad 100644
--- a/apps/federatedfilesharing/lib/Notifier.php
+++ b/apps/federatedfilesharing/lib/Notifier.php
@@ -86,7 +86,7 @@ class Notifier implements INotifier {
* @throws \InvalidArgumentException
*/
public function prepare(INotification $notification, string $languageCode): INotification {
- if ($notification->getApp() !== 'files_sharing') {
+ if ($notification->getApp() !== 'files_sharing' || $notification->getObjectType() !== 'remote_share') {
// Not my app => throw
throw new \InvalidArgumentException();
}
diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php
index c4f44095dcd..8d4b511c265 100644
--- a/apps/files_sharing/appinfo/app.php
+++ b/apps/files_sharing/appinfo/app.php
@@ -38,6 +38,7 @@ use OCA\Files_Sharing\AppInfo\Application;
$application = \OC::$server->query(Application::class);
$application->registerMountProviders();
+$application->register();
$eventDispatcher = \OC::$server->getEventDispatcher();
$eventDispatcher->addListener(
diff --git a/apps/files_sharing/appinfo/info.xml b/apps/files_sharing/appinfo/info.xml
index a90303828f5..111ed9c45c6 100644
--- a/apps/files_sharing/appinfo/info.xml
+++ b/apps/files_sharing/appinfo/info.xml
@@ -9,7 +9,7 @@
Turning the feature off removes shared files and folders on the server for all share recipients, and also on the sync clients and mobile apps. More information is available in the Nextcloud Documentation.
</description>
- <version>1.10.0</version>
+ <version>1.10.1</version>
<licence>agpl</licence>
<author>Michael Gapczynski</author>
<author>Bjoern Schiessle</author>
@@ -36,6 +36,7 @@ Turning the feature off removes shared files and folders on the server for all s
<post-migration>
<step>OCA\Files_Sharing\Migration\OwncloudGuestShareType</step>
<step>OCA\Files_Sharing\Migration\SetPasswordColumn</step>
+ <step>OCA\Files_Sharing\Migration\SetAcceptedStatus</step>
</post-migration>
</repair-steps>
diff --git a/apps/files_sharing/appinfo/routes.php b/apps/files_sharing/appinfo/routes.php
index ce7ba409199..ab5e829f86b 100644
--- a/apps/files_sharing/appinfo/routes.php
+++ b/apps/files_sharing/appinfo/routes.php
@@ -73,6 +73,11 @@ return [
'url' => '/api/v1/shares/{id}',
'verb' => 'DELETE',
],
+ [
+ 'name' => 'ShareAPI#acceptShare',
+ 'url' => '/api/v1/shares/pending/{id}',
+ 'verb' => 'POST',
+ ],
/*
* Deleted Shares
*/
diff --git a/apps/files_sharing/composer/composer/autoload_classmap.php b/apps/files_sharing/composer/composer/autoload_classmap.php
index 63c31f0a3c6..d73838c07df 100644
--- a/apps/files_sharing/composer/composer/autoload_classmap.php
+++ b/apps/files_sharing/composer/composer/autoload_classmap.php
@@ -49,8 +49,10 @@ return array(
'OCA\\Files_Sharing\\Middleware\\ShareInfoMiddleware' => $baseDir . '/../lib/Middleware/ShareInfoMiddleware.php',
'OCA\\Files_Sharing\\Middleware\\SharingCheckMiddleware' => $baseDir . '/../lib/Middleware/SharingCheckMiddleware.php',
'OCA\\Files_Sharing\\Migration\\OwncloudGuestShareType' => $baseDir . '/../lib/Migration/OwncloudGuestShareType.php',
+ 'OCA\\Files_Sharing\\Migration\\SetAcceptedStatus' => $baseDir . '/../lib/Migration/SetAcceptedStatus.php',
'OCA\\Files_Sharing\\Migration\\SetPasswordColumn' => $baseDir . '/../lib/Migration/SetPasswordColumn.php',
'OCA\\Files_Sharing\\MountProvider' => $baseDir . '/../lib/MountProvider.php',
+ 'OCA\\Files_Sharing\\Notification\\Listener' => $baseDir . '/../lib/Notification/Listener.php',
'OCA\\Files_Sharing\\Notification\\Notifier' => $baseDir . '/../lib/Notification/Notifier.php',
'OCA\\Files_Sharing\\Scanner' => $baseDir . '/../lib/Scanner.php',
'OCA\\Files_Sharing\\ShareBackend\\File' => $baseDir . '/../lib/ShareBackend/File.php',
diff --git a/apps/files_sharing/composer/composer/autoload_static.php b/apps/files_sharing/composer/composer/autoload_static.php
index 659903300c6..4cdf874b9ee 100644
--- a/apps/files_sharing/composer/composer/autoload_static.php
+++ b/apps/files_sharing/composer/composer/autoload_static.php
@@ -64,8 +64,10 @@ class ComposerStaticInitFiles_Sharing
'OCA\\Files_Sharing\\Middleware\\ShareInfoMiddleware' => __DIR__ . '/..' . '/../lib/Middleware/ShareInfoMiddleware.php',
'OCA\\Files_Sharing\\Middleware\\SharingCheckMiddleware' => __DIR__ . '/..' . '/../lib/Middleware/SharingCheckMiddleware.php',
'OCA\\Files_Sharing\\Migration\\OwncloudGuestShareType' => __DIR__ . '/..' . '/../lib/Migration/OwncloudGuestShareType.php',
+ 'OCA\\Files_Sharing\\Migration\\SetAcceptedStatus' => __DIR__ . '/..' . '/../lib/Migration/SetAcceptedStatus.php',
'OCA\\Files_Sharing\\Migration\\SetPasswordColumn' => __DIR__ . '/..' . '/../lib/Migration/SetPasswordColumn.php',
'OCA\\Files_Sharing\\MountProvider' => __DIR__ . '/..' . '/../lib/MountProvider.php',
+ 'OCA\\Files_Sharing\\Notification\\Listener' => __DIR__ . '/..' . '/../lib/Notification/Listener.php',
'OCA\\Files_Sharing\\Notification\\Notifier' => __DIR__ . '/..' . '/../lib/Notification/Notifier.php',
'OCA\\Files_Sharing\\Scanner' => __DIR__ . '/..' . '/../lib/Scanner.php',
'OCA\\Files_Sharing\\ShareBackend\\File' => __DIR__ . '/..' . '/../lib/ShareBackend/File.php',
diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php
index bba87ba991f..5f48088d719 100644
--- a/apps/files_sharing/lib/AppInfo/Application.php
+++ b/apps/files_sharing/lib/AppInfo/Application.php
@@ -32,6 +32,7 @@ namespace OCA\Files_Sharing\AppInfo;
use OCA\Files_Sharing\Middleware\OCSShareAPIMiddleware;
use OCA\Files_Sharing\Middleware\ShareInfoMiddleware;
use OCA\Files_Sharing\MountProvider;
+use OCA\Files_Sharing\Notification\Listener;
use OCA\Files_Sharing\Notification\Notifier;
use OCP\AppFramework\App;
use OC\AppFramework\Utility\SimpleContainer;
@@ -42,9 +43,11 @@ use OCP\AppFramework\Utility\IControllerMethodReflector;
use OCP\Defaults;
use OCP\Federation\ICloudIdManager;
use \OCP\IContainer;
+use OCP\IGroup;
use OCP\IServerContainer;
use OCA\Files_Sharing\Capabilities;
use OCA\Files_Sharing\External\Manager;
+use Symfony\Component\EventDispatcher\GenericEvent;
class Application extends App {
public function __construct(array $urlParams = array()) {
@@ -178,4 +181,18 @@ class Application extends App {
$mountProviderCollection->registerProvider($this->getContainer()->query('MountProvider'));
$mountProviderCollection->registerProvider($this->getContainer()->query('ExternalMountProvider'));
}
+
+ public function register(): void {
+ $dispatcher = $this->getContainer()->getServer()->getEventDispatcher();
+ $dispatcher->addListener('OCP\Share::postShare', function(GenericEvent $event) {
+ /** @var Listener $listener */
+ $listener = $this->getContainer()->query(Listener::class);
+ $listener->shareNotification($event);
+ });
+ $dispatcher->addListener(IGroup::class . '::postAddUser', function(GenericEvent $event) {
+ /** @var Listener $listener */
+ $listener = $this->getContainer()->query(Listener::class);
+ $listener->userAddedToGroup($event);
+ });
+ }
}
diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php
index 66b2383ea7d..90a76e2223d 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -947,6 +947,38 @@ class ShareAPIController extends OCSController {
}
/**
+ * @NoAdminRequired
+ *
+ * @param string $id
+ * @return DataResponse
+ * @throws OCSNotFoundException
+ * @throws OCSException
+ * @throws OCSBadRequestException
+ */
+ public function acceptShare(string $id): DataResponse {
+ try {
+ $share = $this->getShareById($id);
+ } catch (ShareNotFound $e) {
+ throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
+ }
+
+ if (!$this->canAccessShare($share)) {
+ throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
+ }
+
+ try {
+ $this->shareManager->acceptShare($share, $this->currentUser);
+ } catch (GenericShareException $e) {
+ $code = $e->getCode() === 0 ? 403 : $e->getCode();
+ throw new OCSException($e->getHint(), $code);
+ } catch (\Exception $e) {
+ throw new OCSBadRequestException($e->getMessage(), $e);
+ }
+
+ return new DataResponse();
+ }
+
+ /**
* Does the user have read permission on the share
*
* @param \OCP\Share\IShare $share the share to check
@@ -1078,8 +1110,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/External/Manager.php b/apps/files_sharing/lib/External/Manager.php
index 0cf7d899234..55f366fd65a 100644
--- a/apps/files_sharing/lib/External/Manager.php
+++ b/apps/files_sharing/lib/External/Manager.php
@@ -44,6 +44,7 @@ use OCP\IUserManager;
use OCP\Notification\IManager;
use OCP\OCS\IDiscoveryService;
use OCP\Share;
+use OCP\Share\IShare;
class Manager {
const STORAGE = '\OCA\Files_Sharing\External\Storage';
@@ -151,10 +152,10 @@ class Manager {
public function addShare($remote, $token, $password, $name, $owner, $shareType, $accepted=false, $user = null, $remoteId = -1, $parent = -1) {
$user = $user ? $user : $this->uid;
- $accepted = $accepted ? 1 : 0;
+ $accepted = $accepted ? IShare::STATUS_ACCEPTED : IShare::STATUS_PENDING;
$name = Filesystem::normalizePath('/' . $name);
- if (!$accepted) {
+ if ($accepted !== IShare::STATUS_ACCEPTED) {
// To avoid conflicts with the mount point generation later,
// we only use a temporary mount point name here. The real
// mount point name will be generated when accepting the share,
diff --git a/apps/files_sharing/lib/Migration/SetAcceptedStatus.php b/apps/files_sharing/lib/Migration/SetAcceptedStatus.php
new file mode 100644
index 00000000000..935372ca3fe
--- /dev/null
+++ b/apps/files_sharing/lib/Migration/SetAcceptedStatus.php
@@ -0,0 +1,79 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2019, Joas Schilling <coding@schilljs.com>
+ *
+ * @author Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Files_Sharing\Migration;
+
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+use OCP\Share\IShare;
+
+class SetAcceptedStatus implements IRepairStep {
+
+ /** @var IDBConnection */
+ private $connection;
+
+ /** @var IConfig */
+ private $config;
+
+
+ public function __construct(IDBConnection $connection, IConfig $config) {
+ $this->connection = $connection;
+ $this->config = $config;
+ }
+
+ /**
+ * Returns the step's name
+ *
+ * @return string
+ * @since 9.1.0
+ */
+ public function getName(): string {
+ return 'Set existing shares as accepted';
+ }
+
+ /**
+ * @param IOutput $output
+ */
+ public function run(IOutput $output): void {
+ if (!$this->shouldRun()) {
+ return;
+ }
+
+ $query = $this->connection->getQueryBuilder();
+ $query
+ ->update('share')
+ ->set('accepted', $query->createNamedParameter(IShare::STATUS_ACCEPTED))
+ ->where($query->expr()->in('share_type', $query->createNamedParameter([IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_USERGROUP], IQueryBuilder::PARAM_INT_ARRAY)));
+ $query->execute();
+ }
+
+ protected function shouldRun() {
+ $appVersion = $this->config->getAppValue('files_sharing', 'installed_version', '0.0.0');
+ return version_compare($appVersion, '1.10.1', '<');
+ }
+
+}
diff --git a/apps/files_sharing/lib/MountProvider.php b/apps/files_sharing/lib/MountProvider.php
index 47a787350d5..6dd1dc2f31f 100644
--- a/apps/files_sharing/lib/MountProvider.php
+++ b/apps/files_sharing/lib/MountProvider.php
@@ -35,6 +35,7 @@ use OCP\IConfig;
use OCP\ILogger;
use OCP\IUser;
use OCP\Share\IManager;
+use OCP\Share\IShare;
class MountProvider implements IMountProvider {
/**
@@ -94,6 +95,14 @@ class MountProvider implements IMountProvider {
try {
/** @var \OCP\Share\IShare $parentShare */
$parentShare = $share[0];
+
+ if ($parentShare->getStatus() !== IShare::STATUS_ACCEPTED &&
+ ($parentShare->getShareType() === IShare::TYPE_GROUP ||
+ $parentShare->getShareType() === IShare::TYPE_USERGROUP ||
+ $parentShare->getShareType() === IShare::TYPE_USER)) {
+ continue;
+ }
+
$owner = $parentShare->getShareOwner();
if (!isset($ownerViews[$owner])) {
$ownerViews[$owner] = new View('/' . $parentShare->getShareOwner() . '/files');
@@ -184,12 +193,16 @@ class MountProvider implements IMountProvider {
$superShare->setId($shares[0]->getId())
->setShareOwner($shares[0]->getShareOwner())
->setNodeId($shares[0]->getNodeId())
+ ->setShareType($shares[0]->getShareType())
->setTarget($shares[0]->getTarget());
// use most permissive permissions
$permissions = 0;
+ $status = IShare::STATUS_PENDING;
foreach ($shares as $share) {
$permissions |= $share->getPermissions();
+ $status = max($status, $share->getStatus());
+
if ($share->getTarget() !== $superShare->getTarget()) {
// adjust target, for database consistency
$share->setTarget($superShare->getTarget());
@@ -216,7 +229,8 @@ class MountProvider implements IMountProvider {
}
}
- $superShare->setPermissions($permissions);
+ $superShare->setPermissions($permissions)
+ ->setStatus($status);
$result[] = [$superShare, $shares];
}
diff --git a/apps/files_sharing/lib/Notification/Listener.php b/apps/files_sharing/lib/Notification/Listener.php
new file mode 100644
index 00000000000..9d23898e570
--- /dev/null
+++ b/apps/files_sharing/lib/Notification/Listener.php
@@ -0,0 +1,131 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2019, Joas Schilling <coding@schilljs.com>
+ *
+ * @author Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Files_Sharing\Notification;
+
+use OCP\IGroup;
+use OCP\IGroupManager;
+use OCP\IUser;
+use OCP\Notification\IManager as INotificationManager;
+use OCP\Notification\INotification;
+use OCP\Share\IManager as IShareManager;
+use OCP\Share\IShare;
+use Symfony\Component\EventDispatcher\GenericEvent;
+
+class Listener {
+
+ /** @var INotificationManager */
+ protected $notificationManager;
+ /** @var IShareManager */
+ protected $shareManager;
+ /** @var IGroupManager */
+ protected $groupManager;
+
+ public function __construct(
+ INotificationManager $notificationManager,
+ IShareManager $shareManager,
+ IGroupManager $groupManager
+ ) {
+ $this->notificationManager = $notificationManager;
+ $this->shareManager = $shareManager;
+ $this->groupManager = $groupManager;
+ }
+
+ /**
+ * @param GenericEvent $event
+ */
+ public function shareNotification(GenericEvent $event): void {
+ /** @var IShare $share */
+ $share = $event->getSubject();
+ $notification = $this->instantiateNotification($share);
+
+ if ($share->getShareType() === IShare::TYPE_USER) {
+ $notification->setSubject(Notifier::INCOMING_USER_SHARE)
+ ->setUser($share->getSharedWith());
+ $this->notificationManager->notify($notification);
+ } else if ($share->getShareType() === IShare::TYPE_GROUP) {
+ $notification->setSubject(Notifier::INCOMING_GROUP_SHARE);
+ $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);
+ }
+ }
+ }
+
+ /**
+ * @param GenericEvent $event
+ */
+ public function userAddedToGroup(GenericEvent $event): void {
+ /** @var IGroup $group */
+ $group = $event->getSubject();
+ /** @var IUser $user */
+ $user = $event->getArgument('user');
+
+ $offset = 0;
+ while (true) {
+ $shares = $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_GROUP, null, 50, $offset);
+ if (empty($shares)) {
+ break;
+ }
+
+ foreach ($shares as $share) {
+ if ($share->getSharedWith() !== $group->getGID()) {
+ continue;
+ }
+
+ if ($user->getUID() === $share->getShareOwner() ||
+ $user->getUID() === $share->getSharedBy()) {
+ continue;
+ }
+
+ $notification = $this->instantiateNotification($share);
+ $notification->setSubject(Notifier::INCOMING_GROUP_SHARE)
+ ->setUser($user->getUID());
+ $this->notificationManager->notify($notification);
+ }
+ $offset += 50;
+ }
+ }
+
+ /**
+ * @param IShare $share
+ * @return INotification
+ */
+ protected function instantiateNotification(IShare $share): INotification {
+ $notification = $this->notificationManager->createNotification();
+ $notification
+ ->setApp('files_sharing')
+ ->setObject('share', $share->getFullId())
+ ->setDateTime($share->getShareTime());
+
+ return $notification;
+ }
+}
diff --git a/apps/files_sharing/lib/Notification/Notifier.php b/apps/files_sharing/lib/Notification/Notifier.php
index a9028ec9cf5..52bb0eb8236 100644
--- a/apps/files_sharing/lib/Notification/Notifier.php
+++ b/apps/files_sharing/lib/Notification/Notifier.php
@@ -2,8 +2,10 @@
declare(strict_types=1);
/**
* @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
+ * @copyright Copyright (c) 2019, Joas Schilling <coding@schilljs.com>
*
* @author Roeland Jago Douma <roeland@famdouma.nl>
+ * @author Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
@@ -25,43 +27,83 @@ declare(strict_types=1);
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;
use OCP\Notification\INotifier;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
+use OCP\Share\IShare;
class Notifier implements INotifier {
+ public const INCOMING_USER_SHARE = 'incoming_user_share';
+ public const INCOMING_GROUP_SHARE = 'incoming_group_share';
/** @var IFactory */
protected $l10nFactory;
-
/** @var IManager */
private $shareManager;
-
/** @var IRootFolder */
private $rootFolder;
+ /** @var IGroupManager */
+ protected $groupManager;
+ /** @var IUserManager */
+ protected $userManager;
+ /** @var IURLGenerator */
+ protected $url;
+
public function __construct(IFactory $l10nFactory,
IManager $shareManager,
- IRootFolder $rootFolder) {
+ 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;
}
+ /**
+ * Identifier of the notifier, only use [a-z0-9_]
+ *
+ * @return string
+ * @since 17.0.0
+ */
public function getID(): string {
return 'files_sharing';
}
+ /**
+ * Human readable name describing the notifier
+ *
+ * @return string
+ * @since 17.0.0
+ */
public function getName(): string {
- return $this->l10nFactory->get('files_sharing')->t('Files sharing');
+ return $this->l10nFactory->get('files_sharing')->t('File sharing');
}
+ /**
+ * @param INotification $notification
+ * @param string $languageCode The code of the language that should be used to prepare the notification
+ * @return INotification
+ * @throws \InvalidArgumentException When the notification was not prepared by a notifier
+ * @throws AlreadyProcessedException When the notification is not needed anymore and should be deleted
+ * @since 9.0.0
+ */
public function prepare(INotification $notification, string $languageCode): INotification {
if ($notification->getApp() !== 'files_sharing' ||
- $notification->getSubject() !== 'expiresTomorrow') {
+ ($notification->getSubject() !== 'expiresTomorrow' &&
+ $notification->getObjectType() !== 'share')) {
throw new \InvalidArgumentException('Unhandled app or subject');
}
@@ -74,6 +116,15 @@ class Notifier implements INotifier {
throw new AlreadyProcessedException();
}
+ if ($notification->getSubject() === 'expiresTomorrow') {
+ $notification = $this->parseShareExpiration($share, $notification, $l);
+ } else {
+ $notification = $this->parseShareInvitation($share, $notification, $l);
+ }
+ return $notification;
+ }
+
+ protected function parseShareExpiration(IShare $share, INotification $notification, IL10N $l): INotification {
$node = $share->getNode();
$userFolder = $this->rootFolder->getUserFolder($notification->getUser());
$path = $userFolder->getRelativePath($node->getPath());
@@ -95,4 +146,112 @@ class Notifier implements INotifier {
return $notification;
}
+
+ protected function parseShareInvitation(IShare $share, INotification $notification, IL10N $l): INotification {
+
+ if ($share->getShareType() === IShare::TYPE_USER) {
+ 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();
+ }
+ }
+
+ switch ($notification->getSubject()) {
+ case self::INCOMING_USER_SHARE:
+ if ($share->getSharedWith() !== $notification->getUser()) {
+ throw new AlreadyProcessedException();
+ }
+
+ $sharer = $this->userManager->get($share->getSharedBy());
+ if (!$sharer instanceof IUser) {
+ throw new \InvalidArgumentException('Temporary failure');
+ }
+
+ $subject = $l->t('You received {share} as a share by {user}');
+ $subjectParameters = [
+ 'share' => [
+ 'type' => 'highlight',
+ 'id' => $notification->getObjectId(),
+ 'name' => $share->getNode()->getName(),
+ ],
+ 'user' => [
+ 'type' => 'user',
+ 'id' => $sharer->getUID(),
+ 'name' => $sharer->getDisplayName(),
+ ],
+ ];
+ break;
+
+ case self::INCOMING_GROUP_SHARE:
+ $user = $this->userManager->get($notification->getUser());
+ if (!$user instanceof IUser) {
+ throw new AlreadyProcessedException();
+ }
+
+ $group = $this->groupManager->get($share->getSharedWith());
+ if (!$group->inGroup($user)) {
+ throw new AlreadyProcessedException();
+ }
+
+ if ($share->getPermissions() === 0) {
+ // Already rejected
+ throw new AlreadyProcessedException();
+ }
+
+ $sharer = $this->userManager->get($share->getSharedBy());
+ if (!$sharer instanceof IUser) {
+ throw new \InvalidArgumentException('Temporary failure');
+ }
+
+ $subject = $l->t('You received {share} to group {group} as a share by {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' => $sharer->getUID(),
+ 'name' => $sharer->getDisplayName(),
+ ],
+ ];
+ 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;
+ }
}