diff options
-rw-r--r-- | core/Controller/AppPasswordController.php | 14 | ||||
-rw-r--r-- | core/Controller/ClientFlowLoginController.php | 12 | ||||
-rw-r--r-- | settings/Application.php | 31 | ||||
-rw-r--r-- | tests/Core/Controller/AppPasswordControllerTest.php | 14 | ||||
-rw-r--r-- | tests/Core/Controller/ClientFlowLoginControllerTest.php | 20 |
5 files changed, 86 insertions, 5 deletions
diff --git a/core/Controller/AppPasswordController.php b/core/Controller/AppPasswordController.php index ce06730694e..a858bb025d9 100644 --- a/core/Controller/AppPasswordController.php +++ b/core/Controller/AppPasswordController.php @@ -34,6 +34,8 @@ use OCP\Authentication\LoginCredentials\IStore; 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 { @@ -49,18 +51,23 @@ class AppPasswordController extends \OCP\AppFramework\OCSController { /** @var IStore */ private $credentialStore; + /** @var EventDispatcherInterface */ + private $eventDispatcher; + public function __construct(string $appName, IRequest $request, ISession $session, ISecureRandom $random, IProvider $tokenProvider, - IStore $credentialStore) { + IStore $credentialStore, + EventDispatcherInterface $eventDispatcher) { parent::__construct($appName, $request); $this->session = $session; $this->random = $random; $this->tokenProvider = $tokenProvider; $this->credentialStore = $credentialStore; + $this->eventDispatcher = $eventDispatcher; } /** @@ -91,7 +98,7 @@ class AppPasswordController extends \OCP\AppFramework\OCSController { $token = $this->random->generate(72, ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_DIGITS); - $this->tokenProvider->generateToken( + $generatedToken = $this->tokenProvider->generateToken( $token, $credentials->getUID(), $credentials->getLoginName(), @@ -101,6 +108,9 @@ class AppPasswordController extends \OCP\AppFramework\OCSController { IToken::DO_NOT_REMEMBER ); + $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 f73e3f260a7..748139fe832 100644 --- a/core/Controller/ClientFlowLoginController.php +++ b/core/Controller/ClientFlowLoginController.php @@ -46,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 */ @@ -68,6 +70,8 @@ class ClientFlowLoginController extends Controller { private $accessTokenMapper; /** @var ICrypto */ private $crypto; + /** @var EventDispatcherInterface */ + private $eventDispatcher; const stateName = 'client.flow.state.token'; @@ -84,6 +88,7 @@ class ClientFlowLoginController extends Controller { * @param ClientMapper $clientMapper * @param AccessTokenMapper $accessTokenMapper * @param ICrypto $crypto + * @param EventDispatcherInterface $eventDispatcher */ public function __construct($appName, IRequest $request, @@ -96,7 +101,8 @@ class ClientFlowLoginController extends Controller { IURLGenerator $urlGenerator, ClientMapper $clientMapper, AccessTokenMapper $accessTokenMapper, - ICrypto $crypto) { + ICrypto $crypto, + EventDispatcherInterface $eventDispatcher) { parent::__construct($appName, $request); $this->userSession = $userSession; $this->l10n = $l10n; @@ -108,6 +114,7 @@ class ClientFlowLoginController extends Controller { $this->clientMapper = $clientMapper; $this->accessTokenMapper = $accessTokenMapper; $this->crypto = $crypto; + $this->eventDispatcher = $eventDispatcher; } /** @@ -324,6 +331,9 @@ class ClientFlowLoginController extends Controller { $this->tokenProvider->invalidateToken($sessionId); } + $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 4a144082427..111cb6a6e0b 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 f0c223ccc1d..a66bcb3fc26 100644 --- a/tests/Core/Controller/AppPasswordControllerTest.php +++ b/tests/Core/Controller/AppPasswordControllerTest.php @@ -36,6 +36,7 @@ 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 { @@ -55,6 +56,9 @@ class AppPasswordControllerTest extends TestCase { /** @var IRequest|MockObject */ private $request; + /** @var EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $eventDispatcher; + /** @var AppPasswordController */ private $controller; @@ -66,6 +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->eventDispatcher = $this->createMock(EventDispatcherInterface::class); $this->controller = new AppPasswordController( 'core', @@ -73,7 +78,8 @@ class AppPasswordControllerTest extends TestCase { $this->session, $this->random, $this->tokenProvider, - $this->credentialStore + $this->credentialStore, + $this->eventDispatcher ); } @@ -134,6 +140,9 @@ class AppPasswordControllerTest extends TestCase { IToken::DO_NOT_REMEMBER ); + $this->eventDispatcher->expects($this->once()) + ->method('dispatch'); + $this->controller->getAppPassword(); } @@ -172,6 +181,9 @@ class AppPasswordControllerTest extends TestCase { IToken::DO_NOT_REMEMBER ); + $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 eddcc1bbdb9..73b8118a876 100644 --- a/tests/Core/Controller/ClientFlowLoginControllerTest.php +++ b/tests/Core/Controller/ClientFlowLoginControllerTest.php @@ -41,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 { @@ -66,6 +67,9 @@ class ClientFlowLoginControllerTest extends TestCase { private $accessTokenMapper; /** @var ICrypto|\PHPUnit_Framework_MockObject_MockObject */ private $crypto; + /** @var EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $eventDispatcher; + /** @var ClientFlowLoginController */ private $clientFlowLoginController; @@ -90,6 +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->eventDispatcher = $this->createMock(EventDispatcherInterface::class); $this->clientFlowLoginController = new ClientFlowLoginController( 'core', @@ -103,7 +108,8 @@ class ClientFlowLoginControllerTest extends TestCase { $this->urlGenerator, $this->clientMapper, $this->accessTokenMapper, - $this->crypto + $this->crypto, + $this->eventDispatcher ); } @@ -378,6 +384,9 @@ class ClientFlowLoginControllerTest extends TestCase { ->method('getHeader') ->willReturn(''); + $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')); } @@ -462,6 +471,9 @@ class ClientFlowLoginControllerTest extends TestCase { ->with('MyClientIdentifier') ->willReturn($client); + $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')); } @@ -534,6 +546,9 @@ class ClientFlowLoginControllerTest extends TestCase { ->method('getHeader') ->willReturn(''); + $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')); } @@ -662,6 +677,9 @@ class ClientFlowLoginControllerTest extends TestCase { ->method('getHeader') ->willReturnMap($headers); + $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')); } |