From c583c5e7e2608c3a5a1f5d15f750b7f3f57c6c93 Mon Sep 17 00:00:00 2001 From: Daniel Kesselberg Date: Mon, 18 Feb 2019 17:38:38 +0100 Subject: [PATCH] Emit event if app password created Signed-off-by: Daniel Kesselberg --- core/Controller/AppPasswordController.php | 37 ++++------------ core/Controller/ClientFlowLoginController.php | 37 ++++------------ settings/Application.php | 31 +++++++++++++ .../Controller/AppPasswordControllerTest.php | 29 ++++-------- .../ClientFlowLoginControllerTest.php | 44 ++++++------------- 5 files changed, 72 insertions(+), 106 deletions(-) diff --git a/core/Controller/AppPasswordController.php b/core/Controller/AppPasswordController.php index b7cbc65e8c..a858bb025d 100644 --- a/core/Controller/AppPasswordController.php +++ b/core/Controller/AppPasswordController.php @@ -24,20 +24,18 @@ declare(strict_types=1); namespace OC\Core\Controller; -use BadMethodCallException; use OC\Authentication\Token\IProvider; use OC\Authentication\Token\IToken; -use OC\Settings\Activity\Provider; -use OCP\Activity\IManager as IActivityManager; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSForbiddenException; use OCP\Authentication\Exceptions\CredentialsUnavailableException; use OCP\Authentication\Exceptions\PasswordUnavailableException; use OCP\Authentication\LoginCredentials\IStore; -use OCP\ILogger; use OCP\IRequest; use OCP\ISession; use OCP\Security\ISecureRandom; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\GenericEvent; class AppPasswordController extends \OCP\AppFramework\OCSController { @@ -50,31 +48,26 @@ class AppPasswordController extends \OCP\AppFramework\OCSController { /** @var IProvider */ private $tokenProvider; - /** @var IActivityManager */ - private $activityManager; - - /** @var ILogger */ - private $logger; - /** @var IStore */ private $credentialStore; + /** @var EventDispatcherInterface */ + private $eventDispatcher; + public function __construct(string $appName, IRequest $request, ISession $session, ISecureRandom $random, IProvider $tokenProvider, IStore $credentialStore, - IActivityManager $activityManager, - ILogger $logger) { + EventDispatcherInterface $eventDispatcher) { parent::__construct($appName, $request); $this->session = $session; $this->random = $random; $this->tokenProvider = $tokenProvider; $this->credentialStore = $credentialStore; - $this->activityManager = $activityManager; - $this->logger = $logger; + $this->eventDispatcher = $eventDispatcher; } /** @@ -115,20 +108,8 @@ class AppPasswordController extends \OCP\AppFramework\OCSController { IToken::DO_NOT_REMEMBER ); - $event = $this->activityManager->generateEvent(); - $event->setApp('settings') - ->setType('security') - ->setAffectedUser($credentials->getUID()) - ->setAuthor($credentials->getUID()) - ->setSubject(Provider::APP_TOKEN_CREATED, ['name' => $generatedToken->getName()]) - ->setObject('app_token', $generatedToken->getId(), 'App Password'); - - try { - $this->activityManager->publish($event); - } catch (BadMethodCallException $e) { - $this->logger->warning('could not publish activity'); - $this->logger->logException($e); - } + $event = new GenericEvent($generatedToken); + $this->eventDispatcher->dispatch('app_password_created', $event); return new DataResponse([ 'apppassword' => $token diff --git a/core/Controller/ClientFlowLoginController.php b/core/Controller/ClientFlowLoginController.php index 9ca530184a..748139fe83 100644 --- a/core/Controller/ClientFlowLoginController.php +++ b/core/Controller/ClientFlowLoginController.php @@ -26,23 +26,19 @@ namespace OC\Core\Controller; -use BadMethodCallException; use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Exceptions\PasswordlessTokenException; use OC\Authentication\Token\IProvider; use OC\Authentication\Token\IToken; -use OC\Settings\Activity\Provider; use OCA\OAuth2\Db\AccessToken; use OCA\OAuth2\Db\AccessTokenMapper; use OCA\OAuth2\Db\ClientMapper; -use OCP\Activity\IManager as IActivityManager; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\StandaloneTemplateResponse; use OCP\Defaults; use OCP\IL10N; -use OCP\ILogger; use OCP\IRequest; use OCP\ISession; use OCP\IURLGenerator; @@ -50,6 +46,8 @@ use OCP\IUserSession; use OCP\Security\ICrypto; use OCP\Security\ISecureRandom; use OCP\Session\Exceptions\SessionNotAvailableException; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\GenericEvent; class ClientFlowLoginController extends Controller { /** @var IUserSession */ @@ -72,10 +70,8 @@ class ClientFlowLoginController extends Controller { private $accessTokenMapper; /** @var ICrypto */ private $crypto; - /** @var IActivityManager */ - private $activityManager; - /** @var ILogger */ - private $logger; + /** @var EventDispatcherInterface */ + private $eventDispatcher; const stateName = 'client.flow.state.token'; @@ -92,8 +88,7 @@ class ClientFlowLoginController extends Controller { * @param ClientMapper $clientMapper * @param AccessTokenMapper $accessTokenMapper * @param ICrypto $crypto - * @param IActivityManager $activityManager - * @param ILogger $logger + * @param EventDispatcherInterface $eventDispatcher */ public function __construct($appName, IRequest $request, @@ -107,8 +102,7 @@ class ClientFlowLoginController extends Controller { ClientMapper $clientMapper, AccessTokenMapper $accessTokenMapper, ICrypto $crypto, - IActivityManager $activityManager, - ILogger $logger) { + EventDispatcherInterface $eventDispatcher) { parent::__construct($appName, $request); $this->userSession = $userSession; $this->l10n = $l10n; @@ -120,8 +114,7 @@ class ClientFlowLoginController extends Controller { $this->clientMapper = $clientMapper; $this->accessTokenMapper = $accessTokenMapper; $this->crypto = $crypto; - $this->activityManager = $activityManager; - $this->logger = $logger; + $this->eventDispatcher = $eventDispatcher; } /** @@ -338,20 +331,8 @@ class ClientFlowLoginController extends Controller { $this->tokenProvider->invalidateToken($sessionId); } - $event = $this->activityManager->generateEvent(); - $event->setApp('settings') - ->setType('security') - ->setAffectedUser($uid) - ->setAuthor($uid) - ->setSubject(Provider::APP_TOKEN_CREATED, ['name' => $generatedToken->getName()]) - ->setObject('app_token', $generatedToken->getId(), 'App Password'); - - try { - $this->activityManager->publish($event); - } catch (BadMethodCallException $e) { - $this->logger->warning('could not publish activity'); - $this->logger->logException($e); - } + $event = new GenericEvent($generatedToken); + $this->eventDispatcher->dispatch('app_password_created', $event); return new Http\RedirectResponse($redirectUri); } diff --git a/settings/Application.php b/settings/Application.php index 4a14408242..111cb6a6e0 100644 --- a/settings/Application.php +++ b/settings/Application.php @@ -28,8 +28,10 @@ namespace OC\Settings; +use BadMethodCallException; use OC\AppFramework\Utility\TimeFactory; use OC\Authentication\Token\IProvider; +use OC\Authentication\Token\IToken; use OC\Server; use OC\Settings\Activity\Provider; use OC\Settings\Activity\SecurityFilter; @@ -38,11 +40,15 @@ use OC\Settings\Activity\SecuritySetting; use OC\Settings\Activity\Setting; use OC\Settings\Mailer\NewUserMailHelper; use OC\Settings\Middleware\SubadminMiddleware; +use OCP\Activity\IManager as IActivityManager; use OCP\AppFramework\App; use OCP\Defaults; use OCP\IContainer; +use OCP\ILogger; use OCP\Settings\IManager; use OCP\Util; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\GenericEvent; /** * @package OC\Settings @@ -109,6 +115,31 @@ class Application extends App { Util::getDefaultEmailAddress('no-reply') ); }); + + /** @var EventDispatcherInterface $eventDispatcher */ + $eventDispatcher = $container->getServer()->getEventDispatcher(); + $eventDispatcher->addListener('app_password_created', function (GenericEvent $event) use ($container) { + if (($token = $event->getSubject()) instanceof IToken) { + /** @var IActivityManager $activityManager */ + $activityManager = $container->query(IActivityManager::class); + /** @var ILogger $logger */ + $logger = $container->query(ILogger::class); + + $activity = $activityManager->generateEvent(); + $activity->setApp('settings') + ->setType('security') + ->setAffectedUser($token->getUID()) + ->setAuthor($token->getUID()) + ->setSubject(Provider::APP_TOKEN_CREATED, ['name' => $token->getName()]) + ->setObject('app_token', $token->getId()); + + try { + $activityManager->publish($activity); + } catch (BadMethodCallException $e) { + $logger->logException($e, ['message' => 'could not publish activity', 'level' => ILogger::WARN]); + } + } + }); } public function register() { diff --git a/tests/Core/Controller/AppPasswordControllerTest.php b/tests/Core/Controller/AppPasswordControllerTest.php index ace6170f98..a66bcb3fc2 100644 --- a/tests/Core/Controller/AppPasswordControllerTest.php +++ b/tests/Core/Controller/AppPasswordControllerTest.php @@ -27,18 +27,16 @@ namespace Tests\Core\Controller; use OC\Authentication\Token\IProvider; use OC\Authentication\Token\IToken; use OC\Core\Controller\AppPasswordController; -use OCP\Activity\IEvent; -use OCP\Activity\IManager as IActivityManager; use OCP\AppFramework\OCS\OCSForbiddenException; use OCP\Authentication\Exceptions\CredentialsUnavailableException; use OCP\Authentication\Exceptions\PasswordUnavailableException; use OCP\Authentication\LoginCredentials\ICredentials; use OCP\Authentication\LoginCredentials\IStore; -use OCP\ILogger; use OCP\IRequest; use OCP\ISession; use OCP\Security\ISecureRandom; use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Test\TestCase; class AppPasswordControllerTest extends TestCase { @@ -58,8 +56,8 @@ class AppPasswordControllerTest extends TestCase { /** @var IRequest|MockObject */ private $request; - /** @var IActivityManager|\PHPUnit_Framework_MockObject_MockObject */ - private $activityManager; + /** @var EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $eventDispatcher; /** @var AppPasswordController */ private $controller; @@ -72,9 +70,7 @@ class AppPasswordControllerTest extends TestCase { $this->tokenProvider = $this->createMock(IProvider::class); $this->credentialStore = $this->createMock(IStore::class); $this->request = $this->createMock(IRequest::class); - $this->activityManager = $this->createMock(IActivityManager::class); - /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject $logger */ - $logger = $this->createMock(ILogger::class); + $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class); $this->controller = new AppPasswordController( 'core', @@ -83,8 +79,7 @@ class AppPasswordControllerTest extends TestCase { $this->random, $this->tokenProvider, $this->credentialStore, - $this->activityManager, - $logger + $this->eventDispatcher ); } @@ -145,11 +140,8 @@ class AppPasswordControllerTest extends TestCase { IToken::DO_NOT_REMEMBER ); - $this->activityManager->expects($this->once()) - ->method('generateEvent') - ->willReturn($this->createMock(IEvent::class)); - $this->activityManager->expects($this->once()) - ->method('publish'); + $this->eventDispatcher->expects($this->once()) + ->method('dispatch'); $this->controller->getAppPassword(); } @@ -189,11 +181,8 @@ class AppPasswordControllerTest extends TestCase { IToken::DO_NOT_REMEMBER ); - $this->activityManager->expects($this->once()) - ->method('generateEvent') - ->willReturn($this->createMock(IEvent::class)); - $this->activityManager->expects($this->once()) - ->method('publish'); + $this->eventDispatcher->expects($this->once()) + ->method('dispatch'); $this->controller->getAppPassword(); } diff --git a/tests/Core/Controller/ClientFlowLoginControllerTest.php b/tests/Core/Controller/ClientFlowLoginControllerTest.php index ed84d456de..73b8118a87 100644 --- a/tests/Core/Controller/ClientFlowLoginControllerTest.php +++ b/tests/Core/Controller/ClientFlowLoginControllerTest.php @@ -29,13 +29,10 @@ use OC\Core\Controller\ClientFlowLoginController; use OCA\OAuth2\Db\AccessTokenMapper; use OCA\OAuth2\Db\Client; use OCA\OAuth2\Db\ClientMapper; -use OCP\Activity\IEvent; -use OCP\Activity\IManager as IActivityManager; use OCP\AppFramework\Http; use OCP\AppFramework\Http\StandaloneTemplateResponse; use OCP\Defaults; use OCP\IL10N; -use OCP\ILogger; use OCP\IRequest; use OCP\ISession; use OCP\IURLGenerator; @@ -44,6 +41,7 @@ use OCP\IUserSession; use OCP\Security\ICrypto; use OCP\Security\ISecureRandom; use OCP\Session\Exceptions\SessionNotAvailableException; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Test\TestCase; class ClientFlowLoginControllerTest extends TestCase { @@ -69,8 +67,9 @@ class ClientFlowLoginControllerTest extends TestCase { private $accessTokenMapper; /** @var ICrypto|\PHPUnit_Framework_MockObject_MockObject */ private $crypto; - /** @var IActivityManager|\PHPUnit_Framework_MockObject_MockObject */ - private $activityManager; + /** @var EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $eventDispatcher; + /** @var ClientFlowLoginController */ private $clientFlowLoginController; @@ -95,9 +94,7 @@ class ClientFlowLoginControllerTest extends TestCase { $this->clientMapper = $this->createMock(ClientMapper::class); $this->accessTokenMapper = $this->createMock(AccessTokenMapper::class); $this->crypto = $this->createMock(ICrypto::class); - $this->activityManager = $this->createMock(IActivityManager::class); - /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject $logger */ - $logger = $this->createMock(ILogger::class); + $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class); $this->clientFlowLoginController = new ClientFlowLoginController( 'core', @@ -112,8 +109,7 @@ class ClientFlowLoginControllerTest extends TestCase { $this->clientMapper, $this->accessTokenMapper, $this->crypto, - $this->activityManager, - $logger + $this->eventDispatcher ); } @@ -388,11 +384,8 @@ class ClientFlowLoginControllerTest extends TestCase { ->method('getHeader') ->willReturn(''); - $this->activityManager->expects($this->once()) - ->method('generateEvent') - ->willReturn($this->createMock(IEvent::class)); - $this->activityManager->expects($this->once()) - ->method('publish'); + $this->eventDispatcher->expects($this->once()) + ->method('dispatch'); $expected = new Http\RedirectResponse('nc://login/server:http://example.com&user:MyLoginName&password:MyGeneratedToken'); $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken')); @@ -478,11 +471,8 @@ class ClientFlowLoginControllerTest extends TestCase { ->with('MyClientIdentifier') ->willReturn($client); - $this->activityManager->expects($this->once()) - ->method('generateEvent') - ->willReturn($this->createMock(IEvent::class)); - $this->activityManager->expects($this->once()) - ->method('publish'); + $this->eventDispatcher->expects($this->once()) + ->method('dispatch'); $expected = new Http\RedirectResponse('https://example.com/redirect.php?state=MyOauthState&code=MyAccessCode'); $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken', 'MyClientIdentifier')); @@ -556,11 +546,8 @@ class ClientFlowLoginControllerTest extends TestCase { ->method('getHeader') ->willReturn(''); - $this->activityManager->expects($this->once()) - ->method('generateEvent') - ->willReturn($this->createMock(IEvent::class)); - $this->activityManager->expects($this->once()) - ->method('publish'); + $this->eventDispatcher->expects($this->once()) + ->method('dispatch'); $expected = new Http\RedirectResponse('nc://login/server:http://example.com&user:MyLoginName&password:MyGeneratedToken'); $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken')); @@ -690,11 +677,8 @@ class ClientFlowLoginControllerTest extends TestCase { ->method('getHeader') ->willReturnMap($headers); - $this->activityManager->expects($this->once()) - ->method('generateEvent') - ->willReturn($this->createMock(IEvent::class)); - $this->activityManager->expects($this->once()) - ->method('publish'); + $this->eventDispatcher->expects($this->once()) + ->method('dispatch'); $expected = new Http\RedirectResponse('nc://login/server:' . $expected . '://example.com&user:MyLoginName&password:MyGeneratedToken'); $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));