diff --git a/js/impersonate_logout.js b/js/impersonate_logout.js
index 281b8f2..b2327ea 100644
--- a/js/impersonate_logout.js
+++ b/js/impersonate_logout.js
@@ -14,10 +14,9 @@ document.addEventListener('DOMContentLoaded', function() {
}
);
- function logoutHandler(userId) {
+ function logoutHandler() {
var promisObj = $.post(
- OC.generateUrl('apps/impersonate/logout'),
- {userId: userId}
+ OC.generateUrl('apps/impersonate/logout')
).promise()
promisObj.done(function () {
@@ -27,7 +26,6 @@ document.addEventListener('DOMContentLoaded', function() {
$('#settings ul li:last').on('click', function (event) {
event.preventDefault()
- var userId = $("#expandDisplayName").text()
- logoutHandler(userId)
+ logoutHandler()
})
})
diff --git a/lib/Controller/LogoutController.php b/lib/Controller/LogoutController.php
index 02c539d..44ec922 100644
--- a/lib/Controller/LogoutController.php
+++ b/lib/Controller/LogoutController.php
@@ -10,6 +10,8 @@
use OCP\ISession;
use OCP\IUserManager;
use OCP\IUserSession;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCA\Impersonate\Events\EndImpersonateEvent;
class LogoutController extends Controller {
/** @var IUserManager */
@@ -20,6 +22,8 @@ class LogoutController extends Controller {
private $logger;
/** @var ISession */
private $session;
+ /** @var IEventDispatcher */
+ private $eventDispatcher;
/**
* @param string $appName
@@ -34,38 +38,42 @@ public function __construct($appName,
IUserManager $userManager,
IUserSession $userSession,
ISession $session,
- LoggerInterface $logger) {
+ LoggerInterface $logger,
+ IEventDispatcher $eventDispatcher) {
parent::__construct($appName, $request);
$this->userManager = $userManager;
$this->userSession = $userSession;
$this->session = $session;
$this->logger = $logger;
+ $this->eventDispatcher = $eventDispatcher;
}
/**
* @UseSession
* @NoAdminRequired
*/
- public function logout(string $userId): JSONResponse {
- $user = $this->session->get('oldUserId');
- $user = $this->userManager->get($user);
+ public function logout(): JSONResponse {
+ /** @var ?string $impersonatorUid */
+ $impersonatorUid = $this->session->get('oldUserId');
+ $impersonator = $this->userManager->get($impersonatorUid);
- if ($user === null) {
+ if ($impersonator === null) {
return new JSONResponse(
- sprintf(
- 'No user found for %s',
- $userId
- ),
+ 'No impersonating user found.',
Http::STATUS_NOT_FOUND
);
}
- $this->userSession->setUser($user);
+ $impersonatedUser = $this->userSession->getUser();
+
+ $this->eventDispatcher->dispatchTyped(new EndImpersonateEvent($impersonator, $impersonatedUser));
+
+ $this->userSession->setUser($impersonator);
$this->logger->info(
sprintf(
- 'Switching back to previous user %s',
- $userId
+ 'Switching back to previous user %s from user %s',
+ $impersonatorUid, $impersonatedUser->getUID()
),
[
'app' => 'impersonate',
diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php
index 087b3ef..1011b72 100644
--- a/lib/Controller/SettingsController.php
+++ b/lib/Controller/SettingsController.php
@@ -24,6 +24,8 @@
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCA\Impersonate\Events\BeginImpersonateEvent;
class SettingsController extends Controller {
/** @var IUserManager */
@@ -40,19 +42,10 @@ class SettingsController extends Controller {
private $logger;
/** @var IL10N */
private $l;
+ /** @var IEventDispatcher */
+ private $eventDispatcher;
- /**
- * @param string $appName
- * @param IRequest $request
- * @param IUserManager $userManager
- * @param IGroupManager $groupManager
- * @param IUserSession $userSession
- * @param ISession $session
- * @param IConfig $config
- * @param LoggerInterface $logger
- * @param IL10N $l
- */
- public function __construct($appName,
+ public function __construct(string $appName,
IRequest $request,
IUserManager $userManager,
IGroupManager $groupManager,
@@ -60,7 +53,8 @@ public function __construct($appName,
ISession $session,
IConfig $config,
LoggerInterface $logger,
- IL10N $l) {
+ IL10N $l,
+ IEventDispatcher $eventDispatcher) {
parent::__construct($appName, $request);
$this->userManager = $userManager;
$this->groupManager = $groupManager;
@@ -69,6 +63,7 @@ public function __construct($appName,
$this->config = $config;
$this->logger = $logger;
$this->l = $l;
+ $this->eventDispatcher = $eventDispatcher;
}
/**
@@ -76,13 +71,13 @@ public function __construct($appName,
* @NoAdminRequired
*/
public function impersonate(string $userId): JSONResponse {
- /** @var IUser $currentUser */
- $currentUser = $this->userSession->getUser();
+ /** @var IUser $impersonator */
+ $impersonator = $this->userSession->getUser();
$this->logger->warning(
sprintf(
'User %s trying to impersonate user %s',
- $currentUser->getUID(),
+ $impersonator->getUID(),
$userId
),
[
@@ -90,8 +85,8 @@ public function impersonate(string $userId): JSONResponse {
]
);
- $user = $this->userManager->get($userId);
- if ($user === null) {
+ $impersonatee = $this->userManager->get($userId);
+ if ($impersonatee === null) {
return new JSONResponse(
[
'message' => $this->l->t('User not found'),
@@ -100,8 +95,8 @@ public function impersonate(string $userId): JSONResponse {
);
}
- if (!$this->groupManager->isAdmin($currentUser->getUID())
- && !$this->groupManager->getSubAdmin()->isUserAccessible($currentUser, $user)) {
+ if (!$this->groupManager->isAdmin($impersonator->getUID())
+ && !$this->groupManager->getSubAdmin()->isUserAccessible($impersonator, $impersonatee)) {
return new JSONResponse(
[
'message' => $this->l->t('Insufficient permissions to impersonate user'),
@@ -112,7 +107,7 @@ public function impersonate(string $userId): JSONResponse {
$authorized = json_decode($this->config->getAppValue('impersonate', 'authorized', '["admin"]'));
if (!empty($authorized)) {
- $userGroups = $this->groupManager->getUserGroupIds($currentUser);
+ $userGroups = $this->groupManager->getUserGroupIds($impersonator);
if (!array_intersect($userGroups, $authorized)) {
return new JSONResponse(
@@ -124,7 +119,7 @@ public function impersonate(string $userId): JSONResponse {
}
}
- if ($user->getLastLogin() === 0) {
+ if ($impersonatee->getLastLogin() === 0) {
return new JSONResponse(
[
'message' => $this->l->t('Cannot impersonate the user because it was never logged in'),
@@ -133,7 +128,7 @@ public function impersonate(string $userId): JSONResponse {
);
}
- if ($user->getUID() === $currentUser->getUID()) {
+ if ($impersonatee->getUID() === $impersonator->getUID()) {
return new JSONResponse(
[
'message' => $this->l->t('Cannot impersonate yourself'),
@@ -152,9 +147,12 @@ public function impersonate(string $userId): JSONResponse {
]
);
if ($this->session->get('oldUserId') === null) {
- $this->session->set('oldUserId', $currentUser->getUID());
+ $this->session->set('oldUserId', $impersonator->getUID());
}
- $this->userSession->setUser($user);
+
+ $this->eventDispatcher->dispatchTyped(new BeginImpersonateEvent($impersonator, $impersonatee));
+
+ $this->userSession->setUser($impersonatee);
return new JSONResponse();
}
}
diff --git a/lib/Events/AImpersonateEvent.php b/lib/Events/AImpersonateEvent.php
new file mode 100644
index 0000000..6c94d24
--- /dev/null
+++ b/lib/Events/AImpersonateEvent.php
@@ -0,0 +1,51 @@
+
+ * @author the-djmaze
+ *
+ * @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 .
+ *
+ */
+
+namespace OCA\Impersonate\Events;
+
+use OCP\EventDispatcher\Event;
+use OCP\IUser;
+
+abstract class AImpersonateEvent extends Event {
+ private IUser $impersonator;
+
+ private IUser $impersonatee;
+
+ public function __construct(IUser $impersonator, IUser $impersonatee) {
+ parent::__construct();
+ $this->impersonator = $impersonator;
+ $this->impersonatee = $impersonatee;
+ }
+
+ public function getImpersonator(): IUser {
+ return $this->impersonator;
+ }
+
+ public function getImpersonatedUser(): IUser {
+ return $this->impersonatee;
+ }
+}
diff --git a/lib/Events/BeginImpersonateEvent.php b/lib/Events/BeginImpersonateEvent.php
new file mode 100644
index 0000000..357661b
--- /dev/null
+++ b/lib/Events/BeginImpersonateEvent.php
@@ -0,0 +1,30 @@
+
+ *
+ * @author Arthur Schiwon
+ *
+ * @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 .
+ *
+ */
+
+namespace OCA\Impersonate\Events;
+
+class BeginImpersonateEvent extends AImpersonateEvent {
+}
diff --git a/lib/Events/EndImpersonateEvent.php b/lib/Events/EndImpersonateEvent.php
new file mode 100644
index 0000000..a57e09b
--- /dev/null
+++ b/lib/Events/EndImpersonateEvent.php
@@ -0,0 +1,30 @@
+
+ *
+ * @author Arthur Schiwon
+ *
+ * @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 .
+ *
+ */
+
+namespace OCA\Impersonate\Events;
+
+class EndImpersonateEvent extends AImpersonateEvent {
+}
diff --git a/tests/phpunit.xml b/tests/phpunit.xml
index 6c0ce78..cc0da19 100644
--- a/tests/phpunit.xml
+++ b/tests/phpunit.xml
@@ -1,6 +1,5 @@
.
-
-
-
- ../../impersonate
-
- ../../impersonate/tests
-
-
-
-
-
-
-
diff --git a/tests/unit/Controller/SettingsControllerTest.php b/tests/unit/Controller/SettingsControllerTest.php
index 7168ae6..1f34918 100644
--- a/tests/unit/Controller/SettingsControllerTest.php
+++ b/tests/unit/Controller/SettingsControllerTest.php
@@ -14,8 +14,10 @@
use OC\Group\Manager;
use OC\SubAdmin;
use OCA\Impersonate\Controller\SettingsController;
+use OCA\Impersonate\Events\BeginImpersonateEvent;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IL10N;
@@ -57,6 +59,8 @@ class SettingsControllerTest extends TestCase {
private $l;
/** @var SettingsController */
private $controller;
+ /** @var IEventDispatcher|IEventDispatcher&MockObject|MockObject */
+ private $eventDispatcher;
protected function setUp(): void {
parent::setUp();
@@ -79,6 +83,7 @@ protected function setUp(): void {
$this->groupManager->expects($this->any())
->method('getSubAdmin')
->willReturn($this->subadmin);
+ $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->controller = new SettingsController(
$this->appName,
@@ -89,7 +94,8 @@ protected function setUp(): void {
$this->session,
$this->config,
$this->logger,
- $this->l
+ $this->l,
+ $this->eventDispatcher
);
}
@@ -104,6 +110,9 @@ public function testImpersonateNotFound() {
$this->userSession->expects($this->never())
->method('setUser');
+ $this->eventDispatcher->expects($this->never())
+ ->method('dispatchTyped');
+
$this->assertEquals(
new JSONResponse(['message' => 'User not found'], Http::STATUS_NOT_FOUND),
$this->controller->impersonate('notexisting@uid')
@@ -161,6 +170,13 @@ public function testAdminImpersonate($query, $uid) {
->with('impersonate', 'authorized', '["admin"]')
->willReturnArgument(2);
+ $this->eventDispatcher->expects($this->once())
+ ->method('dispatchTyped')
+ ->willReturnCallback(function (BeginImpersonateEvent $event) use ($currentUser, $user) {
+ $this->assertSame($currentUser, $event->getImpersonator());
+ $this->assertSame($user, $event->getImpersonatedUser());
+ });
+
$this->assertEquals(
new JSONResponse(),
$this->controller->impersonate($query)
@@ -216,6 +232,13 @@ public function testSubAdminImpersonate($query, $uid) {
->with('impersonate', 'authorized', '["admin"]')
->willReturn(json_encode(['admin', 'subadmin']));
+ $this->eventDispatcher->expects($this->once())
+ ->method('dispatchTyped')
+ ->willReturnCallback(function (BeginImpersonateEvent $event) use ($currentUser, $user) {
+ $this->assertSame($currentUser, $event->getImpersonator());
+ $this->assertSame($user, $event->getImpersonatedUser());
+ });
+
$this->assertEquals(
new JSONResponse(),
$this->controller->impersonate($query)
@@ -271,6 +294,9 @@ public function testSubAdminImpersonateNotAllowed($query, $uid) {
->with('impersonate', 'authorized', '["admin"]')
->willReturnArgument(2);
+ $this->eventDispatcher->expects($this->never())
+ ->method('dispatchTyped');
+
$this->assertEquals(
new JSONResponse(['message' => 'Insufficient permissions to impersonate user'], Http::STATUS_FORBIDDEN),
$this->controller->impersonate($query)
@@ -316,6 +342,9 @@ public function testSubAdminImpersonateNotAccessible($query, $uid) {
->method('setUser')
->with($user);
+ $this->eventDispatcher->expects($this->never())
+ ->method('dispatchTyped');
+
$this->assertEquals(
new JSONResponse(['message' => 'Insufficient permissions to impersonate user'], Http::STATUS_FORBIDDEN),
$this->controller->impersonate($query)