Skip to content

Commit f575504

Browse files
committed
notification of share through email moved to background job
It is better to move the notification of share using email to background job. This prevents timeout or long time wait to notify the user(s). Signed-off-by: Sujith H <[email protected]>
1 parent 00abb1d commit f575504

File tree

5 files changed

+506
-6
lines changed

5 files changed

+506
-6
lines changed

appinfo/info.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
<personal>OCA\Notifications\Panels\Personal\NotificationsPanel</personal>
3030
</settings>
3131

32+
<background-jobs>
33+
<job>OCA\Notifications\Background\MailNotificationSender</job>
34+
</background-jobs>
35+
3236
<dependencies>
3337
<owncloud min-version="10.0.9" max-version="10.1" />
3438
</dependencies>

lib/App.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
namespace OCA\Notifications;
2323

2424

25+
use OCP\BackgroundJob\IJobList;
2526
use OCP\Notification\IApp;
2627
use OCP\Notification\INotification;
2728
use OCA\Notifications\Mailer\NotificationMailerAdapter;
@@ -33,9 +34,13 @@ class App implements IApp {
3334
/** @var NotificationMailerAdapter */
3435
protected $mailerAdapter;
3536

36-
public function __construct(Handler $handler, NotificationMailerAdapter $mailerAdapter) {
37+
/** @var IJobList */
38+
protected $jobList;
39+
40+
public function __construct(Handler $handler, NotificationMailerAdapter $mailerAdapter, IJobList $jobList) {
3741
$this->handler = $handler;
3842
$this->mailerAdapter = $mailerAdapter;
43+
$this->jobList = $jobList;
3944
}
4045

4146
/**
@@ -46,7 +51,19 @@ public function __construct(Handler $handler, NotificationMailerAdapter $mailerA
4651
*/
4752
public function notify(INotification $notification) {
4853
$this->handler->add($notification);
49-
$this->mailerAdapter->sendMail($notification);
54+
}
55+
56+
/**
57+
* Notification of a share to user(s) by email is achieved by background job
58+
* @param string $shareFullId
59+
* @return null
60+
*/
61+
public function emailNotify($shareFullId) {
62+
$this->jobList->add('OCA\Notifications\BackgroundJob\MailNotificationSender',
63+
[
64+
'shareFullId' => $shareFullId,
65+
'webroot' => \OC::$WEBROOT //This is required to get the url link correctly
66+
]);
5067
}
5168

5269
/**
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
<?php
2+
/**
3+
* @author Sujith Haridasan <[email protected]>
4+
*
5+
* @copyright Copyright (c) 2018, ownCloud GmbH
6+
* @license AGPL-3.0
7+
*
8+
* This code is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Affero General Public License, version 3,
10+
* as published by the Free Software Foundation.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Affero General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Affero General Public License, version 3,
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>
19+
*
20+
*/
21+
22+
namespace OCA\Notifications\BackgroundJob;
23+
24+
use OC\BackgroundJob\Job;
25+
use OC\User\Manager;
26+
use OCA\Notifications\Configuration\OptionsStorage;
27+
use OCA\Notifications\Mailer\NotificationMailer;
28+
use OCA\Notifications\Mailer\NotificationMailerAdapter;
29+
use OCP\IConfig;
30+
use OCP\IGroupManager;
31+
use OCP\ILogger;
32+
use OCP\IRequest;
33+
use OCP\IURLGenerator;
34+
use OCP\Mail\IMailer;
35+
use OCP\Share\Exceptions\ShareNotFound;
36+
use OCP\Share\IManager;
37+
use OCP\Notification\IManager as NotificationManager;
38+
39+
/**
40+
* Class MailNotificationSender
41+
*
42+
* @package OCA\Notifications\BackgroundJob
43+
*/
44+
class MailNotificationSender extends Job {
45+
46+
/** @var IManager */
47+
private $shareManager;
48+
49+
/** @var \OC\Group\Manager|IGroupManager */
50+
private $groupManager;
51+
52+
/** @var Manager */
53+
private $userManager;
54+
55+
/** @var NotificationManager */
56+
private $notificationManager;
57+
58+
/** @var IConfig */
59+
private $config;
60+
61+
/** @var IMailer */
62+
private $mailer;
63+
64+
/** @var NotificationMailerAdapter */
65+
private $mailerAdapter;
66+
67+
/** @var IURLGenerator */
68+
private $urlGenerator;
69+
70+
/** @var IRequest */
71+
private $request;
72+
73+
/** @var ILogger */
74+
private $logger;
75+
76+
public function __construct(IManager $shareManager = null,
77+
IGroupManager $groupManager = null,
78+
Manager $userManager = null,
79+
NotificationManager $notificationManager = null,
80+
NotificationMailerAdapter $mailerAdapter = null,
81+
IMailer $mailer = null,
82+
IConfig $config = null,
83+
IURLGenerator $urlGenerator = null,
84+
IRequest $request = null,
85+
ILogger $logger = null) {
86+
$this->shareManager = $shareManager ? $shareManager : \OC::$server->getShareManager();
87+
$this->groupManager = $groupManager ? $groupManager : \OC::$server->getGroupManager();
88+
$this->userManager = $userManager ? $userManager : \OC::$server->getUserManager();
89+
$this->notificationManager = $notificationManager ? $notificationManager : \OC::$server->getNotificationManager();
90+
$this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator();
91+
$this->request = $request ? $request : \OC::$server->getRequest();
92+
$this->logger = $logger ? $logger : \OC::$server->getLogger();
93+
$this->mailer = $mailer ? $mailer : \OC::$server->getMailer();
94+
$this->config = $config ? $config : \OC::$server->getConfig();
95+
96+
$optionsStorage = new OptionsStorage($this->config);
97+
$notificationMailer = new NotificationMailer($this->notificationManager, $this->mailer, $optionsStorage);
98+
99+
$this->mailerAdapter = $mailerAdapter ? $mailerAdapter :
100+
new NotificationMailerAdapter($notificationMailer, $this->userManager, $this->logger, $this->urlGenerator);
101+
}
102+
103+
/**
104+
* @param $notificationURL
105+
* @return string
106+
*/
107+
public function fixURL($notificationURL) {
108+
$url = $this->request->getServerProtocol() . '://' . $this->request->getServerHost();
109+
$partURL = \explode($url, $notificationURL)[1];
110+
$webRoot = $this->getArgument()['webroot'];
111+
if (\strpos($partURL, $webRoot) === false) {
112+
$notificationURL = $url . $this->getArgument()['webroot'] . $partURL;
113+
}
114+
return $notificationURL;
115+
}
116+
117+
/**
118+
* @param $shareFullId
119+
*/
120+
public function sendNotify($shareFullId) {
121+
$notificationList = [];
122+
$maxCountSendNotification = 100;
123+
124+
//Check if its an internal share or not
125+
try {
126+
$share = $this->shareManager->getShareById($shareFullId);
127+
} catch (ShareNotFound $e) {
128+
return null;
129+
}
130+
131+
$users = [];
132+
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
133+
//Notify all the group members
134+
$group = $this->groupManager->get($share->getSharedWith());
135+
$users = $group->getUsers();
136+
} elseif ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
137+
$users[] = $this->userManager->get($share->getSharedWith());
138+
}
139+
140+
foreach ($users as $user) {
141+
if ($user->getEMailAddress() === null) {
142+
\OC::$server->getLogger()->warning("Mail notification can not be sent to " . $user->getUID() . " for share " . $share->getName() . " as email for user is not set");
143+
continue;
144+
}
145+
$notification = $this->notificationManager->createNotification();
146+
$notification->setApp('files_sharing')
147+
->setUser($user->getUID())
148+
->setDateTime(new \DateTime())
149+
->setObject('local_share', $shareFullId);
150+
151+
$fileLink = $this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileId' => $share->getNode()->getId()]);
152+
153+
$fileLink = $this->fixURL($fileLink);
154+
$notification->setLink($fileLink);
155+
156+
$notification->setSubject('local_share', [$share->getShareOwner(), $share->getSharedBy(), $share->getNode()->getName()]);
157+
$notification->setMessage('local_share', [$share->getShareOwner(), $share->getSharedBy(), $share->getNode()->getName()]);
158+
159+
//Adding action because sendMail requires an action for the notificaiton
160+
$acceptAction = $notification->createAction();
161+
$acceptAction->setLabel('email');
162+
$acceptAction->setLink($fileLink, 'POST');
163+
$notification->addAction($acceptAction);
164+
165+
if (\count($notificationList) < $maxCountSendNotification) {
166+
$notificationList[] = $notification;
167+
} else {
168+
foreach ($notificationList as $notificationDispatch) {
169+
$this->mailerAdapter->sendMail($notificationDispatch);
170+
}
171+
172+
//Once users in notificationList recieve notification reset the list
173+
$notificationList = [$notification];
174+
}
175+
}
176+
177+
if (\count($notificationList) < $maxCountSendNotification) {
178+
foreach ($notificationList as $notificationDispatch) {
179+
$this->mailerAdapter->sendMail($notificationDispatch);
180+
}
181+
}
182+
}
183+
184+
public function execute($jobList, ILogger $logger = null) {
185+
$this->sendNotify($this->getArgument()['shareFullId']);
186+
$jobList->remove($this);
187+
}
188+
189+
public function run($argument) {
190+
$this->sendNotify($this->getArgument()['shareFullId']);
191+
//Remove the joblist once the notification is completed.
192+
\OC::$server->getJobList()->removeById($this->getId());
193+
}
194+
}

tests/Unit/AppTest.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
namespace OCA\Notifications\Tests\Unit;
2424

25+
use OCP\BackgroundJob\IJobList;
2526
use OCP\Notification\INotification;
2627
use OCA\Notifications\App;
2728
use OCA\Notifications\Handler;
@@ -40,6 +41,8 @@ class AppTest extends TestCase {
4041
/** @var \OCA\Notifications\App */
4142
protected $app;
4243

44+
protected $jobList;
45+
4346
protected function setUp() {
4447
parent::setUp();
4548

@@ -55,23 +58,30 @@ protected function setUp() {
5558
->disableOriginalConstructor()
5659
->getMock();
5760

61+
$this->jobList = $this->createMock(IJobList::class);
62+
5863
$this->app = new App(
5964
$this->handler,
60-
$this->mailerAdapter
65+
$this->mailerAdapter,
66+
$this->jobList
6167
);
6268
}
6369

6470
public function testNotify() {
6571
$this->handler->expects($this->once())
6672
->method('add')
6773
->with($this->notification);
68-
$this->mailerAdapter->expects($this->once())
69-
->method('sendMail')
70-
->with($this->notification);
7174

7275
$this->app->notify($this->notification);
7376
}
7477

78+
public function testEmailNotify() {
79+
$this->jobList->expects($this->once())
80+
->method('add')
81+
->with('OCA\Notifications\BackgroundJob\MailNotificationSender', ['shareFullId' => 'ocinternal:12', 'webroot' => \OC::$WEBROOT]);
82+
$this->app->emailNotify('ocinternal:12');
83+
}
84+
7585
public function testGetCount() {
7686
$this->handler->expects($this->once())
7787
->method('count')

0 commit comments

Comments
 (0)