%PDF- %PDF-
| Direktori : /home/vacivi36/intranet.vacivitta.com.br/protected/modules/twofa/helpers/ |
| Current File : /home/vacivi36/intranet.vacivitta.com.br/protected/modules/twofa/helpers/TwofaHelper.php |
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2020 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\modules\twofa\helpers;
use DateTime;
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;
use humhub\modules\user\models\User;
use humhub\modules\user\Module as UserModule;
use Yii;
use yii\helpers\BaseIpHelper;
use yii\web\Cookie;
class TwofaHelper
{
const USER_SETTING = 'twofaDriver';
const CODE_SETTING = 'twofaCode';
const CODE_CHARS = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
/**
* Get settings manager of current User
*
* @return ContentContainerSettingsManager|false
*/
public static function getSettings()
{
/** @var User $user */
$user = Yii::$app->user->getIdentity();
/** @var UserModule $module */
$module = Yii::$app->getModule('user');
return $user ? $module->settings->contentContainer($user) : false;
}
/**
* Get setting value of current User
*
* @param string $name Setting name
* @return string|null
*/
public static function getSetting($name)
{
return ($settings = self::getSettings()) ? $settings->get($name) : null;
}
/**
* Get setting value of current User
*
* @param string $name Setting name
* @param string|null $value Setting value, null - to delete the setting
* @return string|null
*/
public static function setSetting($name, $value = null)
{
if (!($settings = TwofaHelper::getSettings())) {
return false;
}
if (empty($value)) {
// Remove empty setting from DB
$settings->delete($name);
} else {
$settings->set($name, $value);
}
return true;
}
/**
* Get Driver setting value of current User
*
* @return string|null
*/
public static function getDriverSetting()
{
$driverClass = self::getSetting(self::USER_SETTING);
/** @var TwofaModule $module */
$module = Yii::$app->getModule('twofa');
if (!in_array($driverClass, $module->getEnabledDrivers())) {
$driverClass = null;
}
if (empty($driverClass) && self::isEnforcedUser()) {
return $module->getEnforcedMethod();
}
return $driverClass;
}
/**
* Get 2fa Driver by class name
*
* @param string Class name
* @return BaseDriver|false
*/
public static function getDriverByClassName($driverClassName)
{
if (empty($driverClassName)) {
return false;
}
$driverClassName = '\\' . trim($driverClassName, '\\');
if (class_exists($driverClassName)) {
return new $driverClassName();
}
return false;
}
/**
* Get 2fa Driver for current User
*
* @return BaseDriver|false
*/
public static function getDriver()
{
return self::getDriverByClassName(self::getDriverSetting());
}
/**
* Check if at least one Group of the current User is enforced to 2fa
*
* @return boolean
*/
public static function isEnforcedUser()
{
if (Yii::$app->user->isGuest) {
return false;
}
/** @var TwofaModule $module */
$module = Yii::$app->getModule('twofa');
$enforcedGroups = $module->getEnforcedGroups();
if (empty($enforcedGroups)) {
return false;
}
/** @var User $user */
$user = Yii::$app->user->getIdentity();
return $user->getGroups()->where(['in', 'id', $enforcedGroups])->exists();
}
/**
* Get verifying code of current User
*
* @return string|null
*/
public static function getCode()
{
return self::getSetting(self::CODE_SETTING);
}
/**
* Returns a random code
*
* @param $len
* @return string
*/
public static function generateCode($len)
{
// To complex: return Yii::$app->security->generateRandomString($len);
$noChars = strlen(static::CODE_CHARS);
$code = '';
for ($i = 0; $i < $len; $i++) {
$code .= static::CODE_CHARS[rand(0, $noChars - 1)];
}
return $code;
}
/**
* Hash code
*
* @param string $code Code value
* @return string Hashed code
*/
public static function hashCode($code)
{
return md5($code);
}
/**
* Enable verifying by 2fa for current User
*
* @return bool true on success enabling
*/
public static function enableVerifying()
{
$driver = self::getDriver();
// Send a verifying code to use by driver
if (!$driver || !$driver->send()) {
// Impossible to send a verifying code by Driver,
// because wrong driver OR current User has no enabled 2fa
return false;
}
// Store the sending verifying code in DB to use this as flag to display a form to check the code
if (!self::setSetting(self::CODE_SETTING, self::hashCode($driver->getCode()))) {
return false;
}
// TODO: Inform user about way of sending the verifying code
return true;
}
/**
* Disable verifying by 2fa for current User
*
* @return bool true on success disabling
*/
public static function disableVerifying()
{
// Remove the verifying code from DB:
return self::setSetting(self::CODE_SETTING);
}
/**
* Check if verifying by 2fa is required for current User
*
* @return bool
* @throws \yii\base\NotSupportedException
*/
public static function isVerifyingRequired()
{
// if impersonate mode of driver is not set up
if (self::isImpersonateMode() || !self::getDriver()) {
return false;
}
// if code is missing for a user, or user is trusted (ip whitelist)
if (self::getCode() === null || self::isTrusted()) {
return false;
}
// if user's ticked remember browser
if (self::isBrowserRemembered()) {
return false;
}
return true;
}
/**
* 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;
}
/**
* Check the requested code is valid for current User
*
* @param string $code Code value
* @return bool
*/
public static function isValidCode($code)
{
$driver = self::getDriver();
if (!$driver) {
// Don't restrict current User if proper Driver is not selected
return true;
}
return $driver->checkCode($code);
}
/**
* Returns the display name for TwoFactor devices/apps
*
* @return string
* @throws \Throwable
*/
public static function getAccountName()
{
return Yii::$app->name . ' - ' . Yii::$app->user->getIdentity()->username;
}
/**
* @return bool
* @throws \yii\base\NotSupportedException
*/
public static function isTrusted()
{
/** @var TwofaModule $module */
$module = Yii::$app->getModule('twofa');
foreach ($module->getTrustedNetworks() as $trustedNet) {
if (BaseIpHelper::inRange(Yii::$app->request->userIP, $trustedNet)) {
return true;
}
if (Yii::$app->request->userIP !== Yii::$app->request->remoteIP &&
BaseIpHelper::inRange(Yii::$app->request->remoteIP, $trustedNet)) {
return true;
}
}
return false;
}
/**
* @param int $days
*/
public static function rememberBrowser($days = null)
{
// calculate expiration date
$days = $days ?? Yii::$app->getModule('twofa')->getRememberMeDays();
$expire = (new DateTime())->modify("+$days DAYS")->getTimestamp();
// calculate array of remembered user's
$twofaRememberCookie = Yii::$app->request->cookies->get('twofa_remember');
$value = $twofaRememberCookie instanceof Cookie ? $twofaRememberCookie->value : [];
$value[] = Yii::$app->user->id;
// remember browser
$cookie = new Cookie(['name' => 'twofa_remember', 'value' => $value, 'expire' => $expire]);
Yii::$app->response->cookies->add($cookie);
}
/**
* @return bool
*/
public static function isBrowserRemembered()
{
if (empty(Yii::$app->getModule('twofa')->getRememberMeDays())) {
return false;
}
if ($cookie = Yii::$app->request->cookies->get('twofa_remember')) {
return in_array(Yii::$app->user->id, (array)$cookie->value);
}
return false;
}
}