Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>tags/v17.0.0beta1
@@ -31,6 +31,7 @@ namespace OC\Core; | |||
use OC\Authentication\Events\RemoteWipeFinished; | |||
use OC\Authentication\Events\RemoteWipeStarted; | |||
use OC\Authentication\Listeners\RemoteWipeActivityListener; | |||
use OC\Authentication\Listeners\RemoteWipeEmailListener; | |||
use OC\Authentication\Listeners\RemoteWipeNotificationsListener; | |||
use OC\Authentication\Notifications\Notifier as AuthenticationNotifier; | |||
use OC\Core\Notification\RemoveLinkSharesNotifier; | |||
@@ -64,19 +65,19 @@ class Application extends App { | |||
$eventDispatcher = $server->query(IEventDispatcher::class); | |||
$notificationManager = $server->getNotificationManager(); | |||
$notificationManager->registerNotifier(function() use ($server) { | |||
$notificationManager->registerNotifier(function () use ($server) { | |||
return new RemoveLinkSharesNotifier( | |||
$server->getL10NFactory() | |||
); | |||
}, function() { | |||
}, function () { | |||
return [ | |||
'id' => 'core', | |||
'name' => 'core', | |||
]; | |||
}); | |||
$notificationManager->registerNotifier(function() use ($server) { | |||
$notificationManager->registerNotifier(function () use ($server) { | |||
return $server->query(AuthenticationNotifier::class); | |||
}, function() { | |||
}, function () { | |||
return [ | |||
'id' => 'auth', | |||
'name' => 'authentication notifier', | |||
@@ -84,7 +85,7 @@ class Application extends App { | |||
}); | |||
$eventDispatcher->addListener(IDBConnection::CHECK_MISSING_INDEXES_EVENT, | |||
function(GenericEvent $event) use ($container) { | |||
function (GenericEvent $event) use ($container) { | |||
/** @var MissingIndexInformation $subject */ | |||
$subject = $event->getSubject(); | |||
@@ -165,7 +166,10 @@ class Application extends App { | |||
$eventDispatcher->addServiceListener(RemoteWipeStarted::class, RemoteWipeActivityListener::class); | |||
$eventDispatcher->addServiceListener(RemoteWipeStarted::class, RemoteWipeNotificationsListener::class); | |||
$eventDispatcher->addServiceListener(RemoteWipeStarted::class, RemoteWipeEmailListener::class); | |||
$eventDispatcher->addServiceListener(RemoteWipeFinished::class, RemoteWipeActivityListener::class); | |||
$eventDispatcher->addServiceListener(RemoteWipeFinished::class, RemoteWipeNotificationsListener::class); | |||
$eventDispatcher->addServiceListener(RemoteWipeFinished::class, RemoteWipeEmailListener::class); | |||
} | |||
} |
@@ -522,6 +522,7 @@ return array( | |||
'OC\\Authentication\\Exceptions\\UserAlreadyLoggedInException' => $baseDir . '/lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php', | |||
'OC\\Authentication\\Exceptions\\WipeTokenException' => $baseDir . '/lib/private/Authentication/Exceptions/WipeTokenException.php', | |||
'OC\\Authentication\\Listeners\\RemoteWipeActivityListener' => $baseDir . '/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php', | |||
'OC\\Authentication\\Listeners\\RemoteWipeEmailListener' => $baseDir . '/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php', | |||
'OC\\Authentication\\Listeners\\RemoteWipeNotificationsListener' => $baseDir . '/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php', | |||
'OC\\Authentication\\LoginCredentials\\Credentials' => $baseDir . '/lib/private/Authentication/LoginCredentials/Credentials.php', | |||
'OC\\Authentication\\LoginCredentials\\Store' => $baseDir . '/lib/private/Authentication/LoginCredentials/Store.php', |
@@ -556,6 +556,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c | |||
'OC\\Authentication\\Exceptions\\UserAlreadyLoggedInException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php', | |||
'OC\\Authentication\\Exceptions\\WipeTokenException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/WipeTokenException.php', | |||
'OC\\Authentication\\Listeners\\RemoteWipeActivityListener' => __DIR__ . '/../../..' . '/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php', | |||
'OC\\Authentication\\Listeners\\RemoteWipeEmailListener' => __DIR__ . '/../../..' . '/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php', | |||
'OC\\Authentication\\Listeners\\RemoteWipeNotificationsListener' => __DIR__ . '/../../..' . '/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php', | |||
'OC\\Authentication\\LoginCredentials\\Credentials' => __DIR__ . '/../../..' . '/lib/private/Authentication/LoginCredentials/Credentials.php', | |||
'OC\\Authentication\\LoginCredentials\\Store' => __DIR__ . '/../../..' . '/lib/private/Authentication/LoginCredentials/Store.php', |
@@ -0,0 +1,171 @@ | |||
<?php declare(strict_types=1); | |||
/** | |||
* @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> | |||
* | |||
* @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at> | |||
* | |||
* @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 OC\Authentication\Listeners; | |||
use Exception; | |||
use OC\Authentication\Events\RemoteWipeFinished; | |||
use OC\Authentication\Events\RemoteWipeStarted; | |||
use OCP\EventDispatcher\Event; | |||
use OCP\EventDispatcher\IEventListener; | |||
use OCP\IL10N; | |||
use OCP\ILogger; | |||
use OCP\IUser; | |||
use OCP\IUserManager; | |||
use OCP\L10N\IFactory as IL10nFactory; | |||
use OCP\Mail\IMailer; | |||
use OCP\Mail\IMessage; | |||
use function substr; | |||
class RemoteWipeEmailListener implements IEventListener { | |||
/** @var IMailer */ | |||
private $mailer; | |||
/** @var IUserManager */ | |||
private $userManager; | |||
/** @var IL10N */ | |||
private $l10n; | |||
/** @var ILogger */ | |||
private $logger; | |||
public function __construct(IMailer $mailer, | |||
IUserManager $userManager, | |||
IL10nFactory $l10nFactory, | |||
ILogger $logger) { | |||
$this->mailer = $mailer; | |||
$this->userManager = $userManager; | |||
$this->l10n = $l10nFactory->get('core'); | |||
$this->logger = $logger; | |||
} | |||
/** | |||
* @param Event $event | |||
*/ | |||
public function handle(Event $event): void { | |||
if ($event instanceof RemoteWipeStarted) { | |||
$uid = $event->getToken()->getUID(); | |||
$user = $this->userManager->get($uid); | |||
if ($user === null) { | |||
$this->logger->warning("not sending a wipe started email because user <$uid> does not exist (anymore)"); | |||
return; | |||
} | |||
if ($user->getEMailAddress() === null) { | |||
$this->logger->info("not sending a wipe started email because user <$uid> has no email set"); | |||
return; | |||
} | |||
try { | |||
$this->mailer->send( | |||
$this->getWipingStartedMessage($event, $user) | |||
); | |||
} catch (Exception $e) { | |||
$this->logger->logException($e, [ | |||
'message' => "Could not send remote wipe started email to <$uid>", | |||
'level' => ILogger::ERROR, | |||
]); | |||
} | |||
} else if ($event instanceof RemoteWipeFinished) { | |||
$uid = $event->getToken()->getUID(); | |||
$user = $this->userManager->get($uid); | |||
if ($user === null) { | |||
$this->logger->warning("not sending a wipe finished email because user <$uid> does not exist (anymore)"); | |||
return; | |||
} | |||
if ($user->getEMailAddress() === null) { | |||
$this->logger->info("not sending a wipe finished email because user <$uid> has no email set"); | |||
return; | |||
} | |||
try { | |||
$this->mailer->send( | |||
$this->getWipingFinishedMessage($event, $user) | |||
); | |||
} catch (Exception $e) { | |||
$this->logger->logException($e, [ | |||
'message' => "Could not send remote wipe finished email to <$uid>", | |||
'level' => ILogger::ERROR, | |||
]); | |||
} | |||
} | |||
} | |||
private function getWipingStartedMessage(RemoteWipeStarted $event, IUser $user): IMessage { | |||
$message = $this->mailer->createMessage(); | |||
$emailTemplate = $this->mailer->createEMailTemplate('auth.RemoteWipeStarted'); | |||
$plainHeading = $this->l10n->t('Wiping of device %s has started', [$event->getToken()->getName()]); | |||
$htmlHeading = $this->l10n->t('Wiping of device »%s« has started', [$event->getToken()->getName()]); | |||
$emailTemplate->setSubject( | |||
$this->l10n->t( | |||
'»%s« started remote wipe', | |||
[ | |||
substr($event->getToken()->getName(), 0, 15) | |||
] | |||
) | |||
); | |||
$emailTemplate->addHeader(); | |||
$emailTemplate->addHeading( | |||
$htmlHeading, | |||
$plainHeading | |||
); | |||
$emailTemplate->addBodyText( | |||
$this->l10n->t('Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished', [$event->getToken()->getName()]) | |||
); | |||
$emailTemplate->addFooter(); | |||
$message->setTo([$user->getEMailAddress()]); | |||
$message->useTemplate($emailTemplate); | |||
return $message; | |||
} | |||
private function getWipingFinishedMessage(RemoteWipeFinished $event, IUser $user): IMessage { | |||
$message = $this->mailer->createMessage(); | |||
$emailTemplate = $this->mailer->createEMailTemplate('auth.RemoteWipeFinished'); | |||
$plainHeading = $this->l10n->t('Wiping of device %s has finished', [$event->getToken()->getName()]); | |||
$htmlHeading = $this->l10n->t('Wiping of device »%s« has finished', [$event->getToken()->getName()]); | |||
$emailTemplate->setSubject( | |||
$this->l10n->t( | |||
'»%s« finished remote wipe', | |||
[ | |||
substr($event->getToken()->getName(), 0, 15) | |||
] | |||
) | |||
); | |||
$emailTemplate->addHeader(); | |||
$emailTemplate->addHeading( | |||
$htmlHeading, | |||
$plainHeading | |||
); | |||
$emailTemplate->addBodyText( | |||
$this->l10n->t('Device or application »%s« has finished the remote wipe process.', [$event->getToken()->getName()]) | |||
); | |||
$emailTemplate->addFooter(); | |||
$message->setTo([$user->getEMailAddress()]); | |||
$message->useTemplate($emailTemplate); | |||
return $message; | |||
} | |||
} |
@@ -0,0 +1,241 @@ | |||
<?php declare(strict_types=1); | |||
/** | |||
* @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> | |||
* | |||
* @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at> | |||
* | |||
* @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 lib\Authentication\Listeners; | |||
use Exception; | |||
use OC\Authentication\Events\RemoteWipeFinished; | |||
use OC\Authentication\Events\RemoteWipeStarted; | |||
use OC\Authentication\Listeners\RemoteWipeEmailListener; | |||
use OC\Authentication\Token\IToken; | |||
use OCP\EventDispatcher\Event; | |||
use OCP\EventDispatcher\IEventListener; | |||
use OCP\IL10N; | |||
use OCP\ILogger; | |||
use OCP\IUser; | |||
use OCP\IUserManager; | |||
use OCP\L10N\IFactory; | |||
use OCP\Mail\IMailer; | |||
use OCP\Mail\IMessage; | |||
use PHPUnit\Framework\MockObject\MockObject; | |||
use Test\TestCase; | |||
class RemoteWipeEmailListenerTest extends TestCase { | |||
/** @var IMailer|MockObject */ | |||
private $mailer; | |||
/** @var IUserManager|MockObject */ | |||
private $userManager; | |||
/** @var IFactory|MockObject */ | |||
private $l10nFactory; | |||
/** @var IL10N|MockObject */ | |||
private $l10n; | |||
/** @var ILogger|MockObject */ | |||
private $logger; | |||
/** @var IEventListener */ | |||
private $listener; | |||
protected function setUp() { | |||
parent::setUp(); | |||
$this->mailer = $this->createMock(IMailer::class); | |||
$this->userManager = $this->createMock(IUserManager::class); | |||
$this->l10nFactory = $this->createMock(IFactory::class); | |||
$this->l10n = $this->createMock(IL10N::class); | |||
$this->logger = $this->createMock(ILogger::class); | |||
$this->l10nFactory->method('get')->with('core')->willReturn($this->l10n); | |||
$this->l10n->method('t')->willReturnArgument(0); | |||
$this->listener = new RemoteWipeEmailListener( | |||
$this->mailer, | |||
$this->userManager, | |||
$this->l10nFactory, | |||
$this->logger | |||
); | |||
} | |||
public function testHandleUnrelated() { | |||
$event = new Event(); | |||
$this->mailer->expects($this->never())->method('send'); | |||
$this->listener->handle($event); | |||
} | |||
public function testHandleRemoteWipeStartedInvalidUser() { | |||
/** @var IToken|MockObject $token */ | |||
$token = $this->createMock(IToken::class); | |||
$event = new RemoteWipeStarted($token); | |||
$token->method('getUID')->willReturn('nope'); | |||
$this->userManager->expects($this->once()) | |||
->method('get') | |||
->with('nope') | |||
->willReturn(null); | |||
$this->mailer->expects($this->never())->method('send'); | |||
$this->listener->handle($event); | |||
} | |||
public function testHandleRemoteWipeStartedNoEmailSet() { | |||
/** @var IToken|MockObject $token */ | |||
$token = $this->createMock(IToken::class); | |||
$event = new RemoteWipeStarted($token); | |||
$token->method('getUID')->willReturn('nope'); | |||
$user = $this->createMock(IUser::class); | |||
$this->userManager->expects($this->once()) | |||
->method('get') | |||
->with('nope') | |||
->willReturn($user); | |||
$user->method('getEMailAddress')->willReturn(null); | |||
$this->mailer->expects($this->never())->method('send'); | |||
$this->listener->handle($event); | |||
} | |||
public function testHandleRemoteWipeStartedTransmissionError() { | |||
/** @var IToken|MockObject $token */ | |||
$token = $this->createMock(IToken::class); | |||
$event = new RemoteWipeStarted($token); | |||
$token->method('getUID')->willReturn('nope'); | |||
$user = $this->createMock(IUser::class); | |||
$this->userManager->expects($this->once()) | |||
->method('get') | |||
->with('nope') | |||
->willReturn($user); | |||
$user->method('getEMailAddress')->willReturn('user@domain.org'); | |||
$this->mailer->expects($this->once()) | |||
->method('send') | |||
->willThrowException(new Exception()); | |||
$this->logger->expects($this->once()) | |||
->method('logException'); | |||
$this->listener->handle($event); | |||
} | |||
public function testHandleRemoteWipeStarted() { | |||
/** @var IToken|MockObject $token */ | |||
$token = $this->createMock(IToken::class); | |||
$event = new RemoteWipeStarted($token); | |||
$token->method('getUID')->willReturn('nope'); | |||
$user = $this->createMock(IUser::class); | |||
$this->userManager->expects($this->once()) | |||
->method('get') | |||
->with('nope') | |||
->willReturn($user); | |||
$user->method('getEMailAddress')->willReturn('user@domain.org'); | |||
$message = $this->createMock(IMessage::class); | |||
$this->mailer->expects($this->once()) | |||
->method('createMessage') | |||
->willReturn($message); | |||
$message->expects($this->once()) | |||
->method('setTo') | |||
->with($this->equalTo(['user@domain.org'])); | |||
$this->mailer->expects($this->once()) | |||
->method('send') | |||
->with($message); | |||
$this->listener->handle($event); | |||
} | |||
public function testHandleRemoteWipeFinishedInvalidUser() { | |||
/** @var IToken|MockObject $token */ | |||
$token = $this->createMock(IToken::class); | |||
$event = new RemoteWipeFinished($token); | |||
$token->method('getUID')->willReturn('nope'); | |||
$this->userManager->expects($this->once()) | |||
->method('get') | |||
->with('nope') | |||
->willReturn(null); | |||
$this->mailer->expects($this->never())->method('send'); | |||
$this->listener->handle($event); | |||
} | |||
public function testHandleRemoteWipeFinishedNoEmailSet() { | |||
/** @var IToken|MockObject $token */ | |||
$token = $this->createMock(IToken::class); | |||
$event = new RemoteWipeFinished($token); | |||
$token->method('getUID')->willReturn('nope'); | |||
$user = $this->createMock(IUser::class); | |||
$this->userManager->expects($this->once()) | |||
->method('get') | |||
->with('nope') | |||
->willReturn($user); | |||
$user->method('getEMailAddress')->willReturn(null); | |||
$this->mailer->expects($this->never())->method('send'); | |||
$this->listener->handle($event); | |||
} | |||
public function testHandleRemoteWipeFinishedTransmissionError() { | |||
/** @var IToken|MockObject $token */ | |||
$token = $this->createMock(IToken::class); | |||
$event = new RemoteWipeFinished($token); | |||
$token->method('getUID')->willReturn('nope'); | |||
$user = $this->createMock(IUser::class); | |||
$this->userManager->expects($this->once()) | |||
->method('get') | |||
->with('nope') | |||
->willReturn($user); | |||
$user->method('getEMailAddress')->willReturn('user@domain.org'); | |||
$this->mailer->expects($this->once()) | |||
->method('send') | |||
->willThrowException(new Exception()); | |||
$this->logger->expects($this->once()) | |||
->method('logException'); | |||
$this->listener->handle($event); | |||
} | |||
public function testHandleRemoteWipeFinished() { | |||
/** @var IToken|MockObject $token */ | |||
$token = $this->createMock(IToken::class); | |||
$event = new RemoteWipeFinished($token); | |||
$token->method('getUID')->willReturn('nope'); | |||
$user = $this->createMock(IUser::class); | |||
$this->userManager->expects($this->once()) | |||
->method('get') | |||
->with('nope') | |||
->willReturn($user); | |||
$user->method('getEMailAddress')->willReturn('user@domain.org'); | |||
$message = $this->createMock(IMessage::class); | |||
$this->mailer->expects($this->once()) | |||
->method('createMessage') | |||
->willReturn($message); | |||
$message->expects($this->once()) | |||
->method('setTo') | |||
->with($this->equalTo(['user@domain.org'])); | |||
$this->mailer->expects($this->once()) | |||
->method('send') | |||
->with($message); | |||
$this->listener->handle($event); | |||
} | |||
} |