Skip to content

Commit

Permalink
Merge pull request #32 from humhub/fix/31-impersonate-action
Browse files Browse the repository at this point in the history
Don't require 2FA on administration action "Impersonate"
  • Loading branch information
luke- authored Aug 10, 2021
2 parents 84a8759 + a4c5a2a commit 6382186
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 1 deletion.
34 changes: 34 additions & 0 deletions Events.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@

namespace humhub\modules\twofa;

use humhub\components\Controller;
use humhub\modules\admin\controllers\UserController as AdminUserController;
use humhub\modules\admin\permissions\ManageUsers;
use humhub\modules\twofa\helpers\TwofaHelper;
use humhub\modules\twofa\helpers\TwofaUrl;
use humhub\modules\ui\menu\MenuLink;
use humhub\modules\user\controllers\AuthController;
use humhub\modules\user\events\UserEvent;
use humhub\modules\user\widgets\AccountMenu;
use Yii;
Expand Down Expand Up @@ -57,12 +61,42 @@ public static function onBeforeAction($event)
return false;
}

if (self::isImpersonateAction($event->sender)) {
Yii::$app->session->set('twofa.switchedUserId', Yii::$app->user->id);
}

if (TwofaHelper::isVerifyingRequired() &&
!Yii::$app->getModule('twofa')->isTwofaCheckUrl()) {
return Yii::$app->getResponse()->redirect(TwofaUrl::toCheck());
}
}

/**
* Check if currently action "Impersonate" is called
*
* @param $controller Controller
* @return bool
*/
protected static function isImpersonateAction(Controller $controller): bool
{
return ($controller instanceof AdminUserController) &&
isset($controller->action) &&
$controller->action->id == 'impersonate' &&
Yii::$app->user->can(ManageUsers::class);
}

/**
* Clear temp user ID which was used for administration action "Impersonate"
*
* @param $event
*/
public static function onAfterAction($event)
{
if ($event->sender instanceof AuthController && $event->sender->action->id == 'logout') {
Yii::$app->session->remove('twofa.switchedUserId');
}
}

/**
* Set flag after login to user who need 2fa
*
Expand Down
1 change: 1 addition & 0 deletions config.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
[Application::class, Application::EVENT_BEFORE_REQUEST, [Events::class, 'onBeforeRequest']],
[AuthController::class, AuthController::EVENT_AFTER_LOGIN, [Events::class, 'onAfterLogin']],
[Controller::class, Controller::EVENT_BEFORE_ACTION, [Events::class, 'onBeforeAction']],
[Controller::class, Controller::EVENT_AFTER_ACTION, [Events::class, 'onAfterAction']],
[AccountSettingsMenu::class, AccountSettingsMenu::EVENT_INIT, [Events::class, 'onProfileSettingMenuInit']],
],
];
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Changelog
1.0.5 (Unreleased)
---------------------
- Fix #29: Fix button "Log out" to prevent pjax
- Fix #31: Don't require 2FA on administration action "Impersonate"

1.0.4 (15 June, 2021)
---------------------
Expand Down
33 changes: 32 additions & 1 deletion helpers/TwofaHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace humhub\modules\twofa\helpers;

use humhub\modules\admin\Module as AdminModule;
use humhub\modules\content\components\ContentContainerSettingsManager;
use humhub\modules\twofa\drivers\BaseDriver;
use humhub\modules\twofa\Module as TwofaModule;
Expand Down Expand Up @@ -230,7 +231,37 @@ public static function disableVerifying()
*/
public static function isVerifyingRequired()
{
return self::getDriver() && self::getCode() !== null;
return !self::isImpersonateMode() && self::getDriver() && self::getCode() !== null;
}

/**
* Check if current User was logged in from administration action "Impersonate"
*
* @return bool
*/
protected static function isImpersonateMode(): bool
{
$switchedUserId = Yii::$app->session->get('twofa.switchedUserId');
if (empty($switchedUserId)) {
return false;
}

if (Yii::$app->user->isGuest) {
return false;
}

/* @var $adminModule AdminModule */
$adminModule = Yii::$app->getModule('admin');
if (!$adminModule->allowUserImpersonate) {
return false;
}

/* @var $switchedUser User */
if (!($switchedUser = User::findOne(['id' => $switchedUserId]))) {
return false;
}

return $switchedUser->id != Yii::$app->user->id;
}

/**
Expand Down

0 comments on commit 6382186

Please sign in to comment.