Merge pull request #14263 from nextcloud/publish-activity-app-token
Publish activity if app password created by ocs api or client login flow
This commit is contained in:
commit
e7f0e8ba03
5 changed files with 86 additions and 5 deletions
|
@ -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
|
||||
]);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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'));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue