diff options
author | Christoph Wurst <christoph@winzerhof-wurst.at> | 2018-07-30 13:37:12 +0300 |
---|---|---|
committer | Christoph Wurst <christoph@winzerhof-wurst.at> | 2018-07-31 10:01:11 +0300 |
commit | 4252b9b778a7ffed10e39857095932d474531e16 (patch) | |
tree | 015417a6fe285420aab4f8fce830509de59abd31 /lib | |
parent | 279860969dbcae7b7cd9953030c864f2dc03dce6 (diff) |
Refactor state change to use events
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AppInfo/Application.php | 17 | ||||
-rw-r--r-- | lib/Event/StateChanged.php | 57 | ||||
-rw-r--r-- | lib/Listener/IListener.php | 33 | ||||
-rw-r--r-- | lib/Listener/StateChangeActivity.php | 54 | ||||
-rw-r--r-- | lib/Service/Totp.php | 42 |
5 files changed, 176 insertions, 27 deletions
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 45be45f..d3dd60b 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -1,6 +1,6 @@ <?php -declare(strict_types = 1); +declare(strict_types=1); /** * @author Christoph Wurst <christoph@winzerhof-wurst.at> @@ -23,6 +23,9 @@ declare(strict_types = 1); namespace OCA\TwoFactorTOTP\AppInfo; +use OCA\TwoFactorTOTP\Event\StateChanged; +use OCA\TwoFactorTOTP\Listener\IListener; +use OCA\TwoFactorTOTP\Listener\StateChangeActivity; use OCA\TwoFactorTOTP\Service\ITotp; use OCA\TwoFactorTOTP\Service\Totp; use OCP\AppFramework\App; @@ -34,6 +37,18 @@ class Application extends App { $container = $this->getContainer(); $container->registerAlias(ITotp::class, Totp::class); + + $dispatcher = $container->getServer()->getEventDispatcher(); + $dispatcher->addListener(StateChanged::class, function (StateChanged $event) use ($container) { + /** @var IListener[] $listeners */ + $listeners = [ + $container->query(StateChangeActivity::class), + ]; + + foreach ($listeners as $listener) { + $listener->handle($event); + } + }); } } diff --git a/lib/Event/StateChanged.php b/lib/Event/StateChanged.php new file mode 100644 index 0000000..4abf896 --- /dev/null +++ b/lib/Event/StateChanged.php @@ -0,0 +1,57 @@ +<?php + +declare(strict_types=1); + +/** + * @author Christoph Wurst <christoph@winzerhof-wurst.at> + * @copyright Copyright (c) 2018 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * Two-factor TOTP + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\TwoFactorTOTP\Event; + +use OCP\IUser; +use Symfony\Component\EventDispatcher\Event; + +class StateChanged extends Event { + + /** @var IUser */ + private $user; + + /** @var bool */ + private $enabled; + + public function __construct(IUser $user, bool $enabled) { + $this->user = $user; + $this->enabled = $enabled; + } + + /** + * @return IUser + */ + public function getUser(): IUser { + return $this->user; + } + + /** + * @return bool + */ + public function isEnabled(): bool { + return $this->enabled; + } + +}
\ No newline at end of file diff --git a/lib/Listener/IListener.php b/lib/Listener/IListener.php new file mode 100644 index 0000000..7e5f13d --- /dev/null +++ b/lib/Listener/IListener.php @@ -0,0 +1,33 @@ +<?php + +declare(strict_types=1); + +/** + * @author Christoph Wurst <christoph@winzerhof-wurst.at> + * @copyright Copyright (c) 2018 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * Two-factor TOTP + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\TwoFactorTOTP\Listener; + +use Symfony\Component\EventDispatcher\Event; + +interface IListener { + + public function handle(Event $event); + +} diff --git a/lib/Listener/StateChangeActivity.php b/lib/Listener/StateChangeActivity.php new file mode 100644 index 0000000..d60af3f --- /dev/null +++ b/lib/Listener/StateChangeActivity.php @@ -0,0 +1,54 @@ +<?php + +declare(strict_types=1); + +/** + * @author Christoph Wurst <christoph@winzerhof-wurst.at> + * @copyright Copyright (c) 2018 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * Two-factor TOTP + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\TwoFactorTOTP\Listener; + +use OCA\TwoFactorTOTP\Event\StateChanged; +use OCP\Activity\IManager as ActivityManager; +use Symfony\Component\EventDispatcher\Event; + +class StateChangeActivity implements IListener { + + /** @var ActivityManager */ + private $activityManager; + + public function __construct(ActivityManager $activityManager) { + $this->activityManager = $activityManager; + } + + public function handle(Event $event) { + if ($event instanceof StateChanged) { + $user = $event->getUser(); + $subject = $event->isEnabled() ? 'totp_enabled_subject' : 'totp_disabled_subject'; + + $activity = $this->activityManager->generateEvent(); + $activity->setApp('twofactor_totp') + ->setType('security') + ->setAuthor($user->getUID()) + ->setAffectedUser($user->getUID()); + $activity->setSubject($subject); + $this->activityManager->publish($activity); + } + } +}
\ No newline at end of file diff --git a/lib/Service/Totp.php b/lib/Service/Totp.php index 47ec8cc..f40716c 100644 --- a/lib/Service/Totp.php +++ b/lib/Service/Totp.php @@ -1,6 +1,6 @@ <?php -declare(strict_types = 1); +declare(strict_types=1); /** * @author Christoph Wurst <christoph@winzerhof-wurst.at> @@ -27,13 +27,14 @@ namespace OCA\TwoFactorTOTP\Service; use Base32\Base32; use OCA\TwoFactorTOTP\Db\TotpSecret; use OCA\TwoFactorTOTP\Db\TotpSecretMapper; +use OCA\TwoFactorTOTP\Event\StateChanged; use OCA\TwoFactorTOTP\Exception\NoTotpSecretFoundException; -use OCP\Activity\IManager as ActivityManager; use OCP\AppFramework\Db\DoesNotExistException; use OCP\IUser; use OCP\Security\ICrypto; use Otp\GoogleAuthenticator; use Otp\Otp; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; class Totp implements ITotp { @@ -43,19 +44,21 @@ class Totp implements ITotp { /** @var ICrypto */ private $crypto; - /** @var ActivityManager */ - private $activityManager; + /** @var EventDispatcherInterface */ + private $eventDispatcher; - public function __construct(TotpSecretMapper $secretMapper, ICrypto $crypto, ActivityManager $activityManager) { + public function __construct(TotpSecretMapper $secretMapper, + ICrypto $crypto, + EventDispatcherInterface $eventDispatcher) { $this->secretMapper = $secretMapper; $this->crypto = $crypto; - $this->activityManager = $activityManager; + $this->eventDispatcher = $eventDispatcher; } public function hasSecret(IUser $user) { try { $secret = $this->secretMapper->getSecret($user); - return ITotp::STATE_ENABLED === (int) $secret->getState(); + return ITotp::STATE_ENABLED === (int)$secret->getState(); } catch (DoesNotExistException $ex) { return false; } @@ -66,7 +69,7 @@ class Totp implements ITotp { */ public function createSecret(IUser $user): string { try { - // Delet existing one + // Delete existing one $oldSecret = $this->secretMapper->getSecret($user); $this->secretMapper->delete($oldSecret); } catch (DoesNotExistException $ex) { @@ -85,22 +88,6 @@ class Totp implements ITotp { return $secret; } - /** - * Push an TOTP event the user's activity stream - * - * @param IUser $user - * @param string $event - */ - private function publishEvent(IUser $user, $event) { - $activity = $this->activityManager->generateEvent(); - $activity->setApp('twofactor_totp') - ->setType('security') - ->setAuthor($user->getUID()) - ->setAffectedUser($user->getUID()); - $activity->setSubject($event . '_subject'); - $this->activityManager->publish($activity); - } - public function enable(IUser $user, $key): bool { if (!$this->validateSecret($user, $key)) { return false; @@ -108,7 +95,9 @@ class Totp implements ITotp { $dbSecret = $this->secretMapper->getSecret($user); $dbSecret->setState(ITotp::STATE_ENABLED); $this->secretMapper->update($dbSecret); - $this->publishEvent($user, 'totp_enabled'); + + $this->eventDispatcher->dispatch(StateChanged::class, new StateChanged($user, true)); + return true; } @@ -120,7 +109,8 @@ class Totp implements ITotp { } catch (DoesNotExistException $ex) { // Ignore } - $this->publishEvent($user, 'totp_disabled'); + + $this->eventDispatcher->dispatch(StateChanged::class, new StateChanged($user, false)); } public function validateSecret(IUser $user, $key): bool { |