mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-02 14:07:04 +03:00
Added "Enforce 2-Step verification" setting
This commit is contained in:
parent
b7709c8117
commit
acb013fbb5
47 changed files with 1271 additions and 908 deletions
|
|
@ -1306,6 +1306,7 @@ class Actions
|
|||
'RegistrationLinkUrl' => \trim($oConfig->Get('login', 'registration_link_url', '')),
|
||||
'ContactsIsAllowed' => false,
|
||||
'ChangePasswordIsAllowed' => false,
|
||||
'RequireTwoFactor' => false,
|
||||
'JsHash' => \md5(\RainLoop\Utils::GetConnectionToken()),
|
||||
'UseImapThread' => (bool) $oConfig->Get('labs', 'use_imap_thread', false),
|
||||
'UseImapSubscribe' => (bool) $oConfig->Get('labs', 'use_imap_list_subscribe', true),
|
||||
|
|
@ -1479,6 +1480,20 @@ class Actions
|
|||
}
|
||||
|
||||
$aResult['Capa'] = $this->Capa(false, $oAccount);
|
||||
|
||||
if ($aResult['Auth'] && !$aResult['RequireTwoFactor'])
|
||||
{
|
||||
if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::TWO_FACTOR, $oAccount) &&
|
||||
$this->GetCapa(false, \RainLoop\Enumerations\Capa::TWO_FACTOR_FORCE, $oAccount) &&
|
||||
$this->TwoFactorAuthProvider()->IsActive())
|
||||
{
|
||||
$aData = $this->getTwoFactorInfo($oAccount, true);
|
||||
|
||||
$aResult['RequireTwoFactor'] = !$aData ||
|
||||
!isset($aData['User'], $aData['IsSet'], $aData['Enable']) ||
|
||||
!($aData['IsSet'] && $aData['Enable']);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3111,6 +3126,9 @@ class Actions
|
|||
case \RainLoop\Enumerations\Capa::TWO_FACTOR:
|
||||
$this->setConfigFromParams($oConfig, $sParamName, 'security', 'allow_two_factor_auth', 'bool');
|
||||
break;
|
||||
case \RainLoop\Enumerations\Capa::TWO_FACTOR_FORCE:
|
||||
$this->setConfigFromParams($oConfig, $sParamName, 'security', 'force_two_factor_auth', 'bool');
|
||||
break;
|
||||
case \RainLoop\Enumerations\Capa::GRAVATAR:
|
||||
$this->setConfigFromParams($oConfig, $sParamName, 'labs', 'allow_gravatar', 'bool');
|
||||
break;
|
||||
|
|
@ -3216,6 +3234,7 @@ class Actions
|
|||
$this->setCapaFromParams($oConfig, 'CapaAdditionalAccounts', \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS);
|
||||
$this->setCapaFromParams($oConfig, 'CapaTemplates', \RainLoop\Enumerations\Capa::TEMPLATES);
|
||||
$this->setCapaFromParams($oConfig, 'CapaTwoFactorAuth', \RainLoop\Enumerations\Capa::TWO_FACTOR);
|
||||
$this->setCapaFromParams($oConfig, 'CapaTwoFactorAuthForce', \RainLoop\Enumerations\Capa::TWO_FACTOR_FORCE);
|
||||
$this->setCapaFromParams($oConfig, 'CapaOpenPGP', \RainLoop\Enumerations\Capa::OPEN_PGP);
|
||||
$this->setCapaFromParams($oConfig, 'CapaGravatar', \RainLoop\Enumerations\Capa::GRAVATAR);
|
||||
$this->setCapaFromParams($oConfig, 'CapaThemes', \RainLoop\Enumerations\Capa::THEMES);
|
||||
|
|
@ -7772,6 +7791,12 @@ class Actions
|
|||
($bAdmin || ($oAccount && !$oAccount->IsAdditionalAccount())))
|
||||
{
|
||||
$aResult[] = \RainLoop\Enumerations\Capa::TWO_FACTOR;
|
||||
|
||||
if ($oConfig->Get('security', 'force_two_factor_auth', false) &&
|
||||
($bAdmin || ($oAccount && !$oAccount->IsAdditionalAccount())))
|
||||
{
|
||||
$aResult[] = \RainLoop\Enumerations\Capa::TWO_FACTOR_FORCE;
|
||||
}
|
||||
}
|
||||
|
||||
if ($oConfig->Get('labs', 'allow_gravatar', false))
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ class Application extends \RainLoop\Config\AbstractConfig
|
|||
'admin_password' => array('12345'),
|
||||
'allow_admin_panel' => array(true, 'Access settings'),
|
||||
'allow_two_factor_auth' => array(false),
|
||||
'force_two_factor_auth' => array(false),
|
||||
'allow_universal_login' => array(false),
|
||||
'admin_panel_host' => array(''),
|
||||
'core_install_access_domain' => array('')
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ class Capa
|
|||
{
|
||||
const PREM = 'PREM';
|
||||
const TWO_FACTOR = 'TWO_FACTOR';
|
||||
const TWO_FACTOR_FORCE = 'TWO_FACTOR_FORCE';
|
||||
const OPEN_PGP = 'OPEN_PGP';
|
||||
const PREFETCH = 'PREFETCH';
|
||||
const GRAVATAR = 'GRAVATAR';
|
||||
|
|
|
|||
|
|
@ -5,15 +5,38 @@
|
|||
<div class="controls">
|
||||
<div data-bind="component: {
|
||||
name: 'Checkbox',
|
||||
params: { value: capaTwoFactorAuth, label: 'TAB_SECURITY/LABEL_ALLOW_TWO_STEP' }
|
||||
params: {
|
||||
value: capaTwoFactorAuth,
|
||||
label: 'TAB_SECURITY/LABEL_ALLOW_TWO_STEP',
|
||||
inline: true
|
||||
}
|
||||
}"></div>
|
||||
|
||||
<div data-bind="component: {
|
||||
name: 'Checkbox',
|
||||
params: {
|
||||
value: capaTwoFactorAuthForce,
|
||||
enable: capaTwoFactorAuth,
|
||||
label: 'TAB_SECURITY/LABEL_FORCE_TWO_STEP',
|
||||
inline: true
|
||||
}
|
||||
}"></div>
|
||||
<br />
|
||||
<br />
|
||||
<div data-bind="component: {
|
||||
name: 'Checkbox',
|
||||
params: {
|
||||
value: useLocalProxyForExternalImages,
|
||||
label: 'TAB_SECURITY/LABEL_USE_IMAGE_PROXY'
|
||||
}
|
||||
}"></div>
|
||||
<div data-bind="component: {
|
||||
name: 'Checkbox',
|
||||
params: { value: useLocalProxyForExternalImages, label: 'TAB_SECURITY/LABEL_USE_IMAGE_PROXY' }
|
||||
}"></div>
|
||||
<div data-bind="component: {
|
||||
name: 'Checkbox',
|
||||
params: { value: capaOpenPGP, label: 'TAB_SECURITY/LABEL_ALLOW_OPEN_PGP', inline: true }
|
||||
params: {
|
||||
value: capaOpenPGP,
|
||||
label: 'TAB_SECURITY/LABEL_ALLOW_OPEN_PGP',
|
||||
inline: true
|
||||
}
|
||||
}"></div>
|
||||
|
||||
<span style="color:red">(<span data-i18n="HINTS/BETA"></span>)</span>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
<div class="popups">
|
||||
<div class="modal hide b-two-factor-content g-ui-user-select-none" data-bind="modal: modalVisibility">
|
||||
<div>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-bind="visible: viewEnable() || !lock(), command: cancelCommand">×</button>
|
||||
<h3>
|
||||
<span class="i18n" data-i18n="POPUPS_TWO_FACTOR_CFG/LEGEND_TWO_FACTOR_AUTH"></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row" style="margin-top: 10px;">
|
||||
|
||||
<div class="form-horizontal" data-bind="visible: capaTwoFactor">
|
||||
<div class="control-group" data-bind="visible: twoFactorStatus">
|
||||
<div class="controls">
|
||||
<div style="display: inline-block" data-tooltip-join="top" data-bind="tooltip: viewTwoFactorEnableTooltip">
|
||||
<div data-bind="component: {
|
||||
name: 'Checkbox',
|
||||
params: {
|
||||
label: 'POPUPS_TWO_FACTOR_CFG/LABEL_ENABLE_TWO_FACTOR',
|
||||
enable: twoFactorAllowedEnable,
|
||||
value: viewEnable,
|
||||
inline: true
|
||||
}
|
||||
}"></div>
|
||||
</div>
|
||||
|
||||
<span class="i18n g-ui-link" data-bind="click: testTwoFactor, visible: twoFactorStatus"
|
||||
data-i18n="POPUPS_TWO_FACTOR_CFG/LINK_TEST"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">
|
||||
<span class="i18n" data-i18n="POPUPS_TWO_FACTOR_CFG/LABEL_TWO_FACTOR_USER"></span>
|
||||
</label>
|
||||
<div class="controls" style="padding-top: 5px;">
|
||||
<strong><span data-bind="text: viewUser"></span></strong>
|
||||
<div style="padding-top: 15px;" data-bind="visible: lock">
|
||||
<blockquote>
|
||||
<p class="muted i18n" style="width: 550px" data-i18n="POPUPS_TWO_FACTOR_CFG/TWO_FACTOR_REQUIRE_DESC"></p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" data-bind="visible: '' === viewSecret() && twoFactorStatus() && !clearing()">
|
||||
<div class="controls" style="padding-top: 5px;">
|
||||
<strong data-bind="visible: secreting">...</strong>
|
||||
<span class="g-ui-link i18n" data-bind="click: showSecret, visible: !secreting()"
|
||||
data-i18n="POPUPS_TWO_FACTOR_CFG/BUTTON_SHOW_SECRET"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" data-bind="visible: '' !== viewSecret()">
|
||||
<label class="control-label">
|
||||
<span class="i18n" data-i18n="POPUPS_TWO_FACTOR_CFG/LABEL_TWO_FACTOR_SECRET"></span>
|
||||
</label>
|
||||
<div class="controls" style="padding-top: 5px;">
|
||||
<strong data-bind="text: viewSecret"></strong>
|
||||
|
||||
<span class="g-ui-link i18n" data-bind="click: hideSecret" data-i18n="POPUPS_TWO_FACTOR_CFG/BUTTON_HIDE_SECRET"></span>
|
||||
<br />
|
||||
<br />
|
||||
<blockquote>
|
||||
<p class="muted i18n" style="width: 550px" data-i18n="POPUPS_TWO_FACTOR_CFG/TWO_FACTOR_SECRET_DESC"></p>
|
||||
</blockquote>
|
||||
<!-- ko if: '' !== viewUrl() -->
|
||||
<img style="margin-left: -7px;" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2P8DwQACgAD/il4QJ8AAAAASUVORK5CYII=" data-bind="attr: {'src': viewUrl}" />
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" data-bind="visible: '' !== viewBackupCodes()">
|
||||
<label class="control-label">
|
||||
<span class="i18n" data-i18n="POPUPS_TWO_FACTOR_CFG/LABEL_TWO_FACTOR_BACKUP_CODES"></span>
|
||||
</label>
|
||||
<div class="controls" style="padding-top: 5px;">
|
||||
<pre data-bind="text: viewBackupCodes" style="width: 230px; word-break: break-word;"></pre>
|
||||
<br />
|
||||
<blockquote>
|
||||
<p class="muted i18n" style="width: 550px" data-i18n="POPUPS_TWO_FACTOR_CFG/TWO_FACTOR_BACKUP_CODES_DESC"></p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a class="btn pull-left" data-bind="visible: lock, click: logout">
|
||||
<i class="icon-power"></i>
|
||||
|
||||
<span class="i18n" data-i18n="POPUPS_TWO_FACTOR_CFG/BUTTON_LOGOUT"></span>
|
||||
</a>
|
||||
<a class="btn btn-danger" data-bind="click: clearTwoFactor, visible: twoFactorStatus">
|
||||
<i class="icon-remove" data-bind="css: {'icon-remove': !clearing(), 'icon-spinner animated': clearing()}" ></i>
|
||||
|
||||
<span class="i18n" data-i18n="POPUPS_TWO_FACTOR_CFG/BUTTON_CLEAR"></span>
|
||||
</a>
|
||||
<a class="btn" data-bind="click: createTwoFactor, visible: !twoFactorStatus()">
|
||||
<i class="icon-ok" data-bind="css: {'icon-ok': !processing(), 'icon-spinner animated': processing()}" ></i>
|
||||
|
||||
<span class="i18n" data-i18n="POPUPS_TWO_FACTOR_CFG/BUTTON_ACTIVATE"></span>
|
||||
</a>
|
||||
<a class="btn" data-bind="command: cancelCommand, visible: viewEnable() || !lock()">
|
||||
<i class="icon-ok" ></i>
|
||||
|
||||
<span class="i18n" data-i18n="POPUPS_TWO_FACTOR_CFG/BUTTON_DONE"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
<div class="popups">
|
||||
<div class="modal hide b-filter-content g-ui-user-select-none" data-bind="modal: modalVisibility">
|
||||
<div>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-bind="command: cancelCommand">×</button>
|
||||
<h3>
|
||||
<span class="i18n" data-i18n="POPUPS_FILTER/TITLE_CREATE_FILTER" data-bind="visible: isNew"></span>
|
||||
<span class="i18n" data-i18n="POPUPS_FILTER/TITLE_EDIT_FILTER" data-bind="visible: !isNew()"></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row filter" data-bind="with: filter, i18nInit: filter">
|
||||
<div class="span9" data-bind="i18nInit: true">
|
||||
|
||||
<div class="control-group" data-bind="css: {'error': name.error}">
|
||||
<div class="controls">
|
||||
<input type="text" class="i18n span5"
|
||||
data-bind="value: name, hasFocus: name.focused"
|
||||
autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-i18n="[placeholder]POPUPS_FILTER/FILTER_NAME"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legend i18n" data-i18n="POPUPS_FILTER/LEGEND_CONDITIONS"></div>
|
||||
<div>
|
||||
<div data-bind="visible: 1 < conditions().length">
|
||||
<select class="span4" data-bind="value: conditionsType">
|
||||
<option value="Any" class="i18n"
|
||||
data-i18n="POPUPS_FILTER/SELECT_MATCH_ANY"></option>
|
||||
<option value="All" class="i18n"
|
||||
data-i18n="POPUPS_FILTER/SELECT_MATCH_ALL"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div data-bind="visible: 0 < conditions().length, foreach: conditions">
|
||||
<div data-bind="template: {'name': template(), 'data': $data}"></div>
|
||||
</div>
|
||||
<div data-bind="visible: 0 === conditions().length">
|
||||
<span class="i18n" data-i18n="POPUPS_FILTER/ALL_INCOMING_MESSAGES_DESC"></span>
|
||||
</div>
|
||||
<br />
|
||||
<a class="btn" data-bind="click: addCondition, i18nInit: true">
|
||||
<i class="icon-plus"></i>
|
||||
|
||||
<span class="i18n" data-i18n="POPUPS_FILTER/BUTTON_ADD_CONDITION"></span>
|
||||
</a>
|
||||
</div>
|
||||
<br />
|
||||
<div class="legend i18n" data-i18n="POPUPS_FILTER/LEGEND_ACTIONS"></div>
|
||||
<select class="span3" data-bind="options: $root.actionTypeOptions, value: actionType, optionsText: 'name', optionsValue: 'id'"></select>
|
||||
<div data-bind="template: {'name': actionTemplate()}, i18nUpdate: actionTemplate"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a class="btn buttonSave" data-bind="command: saveFilter">
|
||||
<i class="icon-ok"></i>
|
||||
|
||||
<span class="i18n" data-i18n="POPUPS_FILTER/BUTTON_DONE"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -22,86 +22,12 @@
|
|||
</div>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
<div class="form-horizontal" data-bind="visible: capaTwoFactor">
|
||||
<div class="legend">
|
||||
<span class="i18n" data-i18n="SETTINGS_SECURITY/LEGEND_TWO_FACTOR_AUTH"></span>
|
||||
</div>
|
||||
<div class="control-group" data-bind="visible: twoFactorStatus">
|
||||
<div class="controls" style="display: inline-block" data-bind="tooltip: viewTwoFactorEnableTooltip">
|
||||
<div data-bind="component: {
|
||||
name: 'Checkbox',
|
||||
params: {
|
||||
label: 'SETTINGS_SECURITY/LABEL_ENABLE_TWO_FACTOR',
|
||||
enable: twoFactorAllowedEnable,
|
||||
value: viewEnable
|
||||
}
|
||||
}"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">
|
||||
<span class="i18n" data-i18n="SETTINGS_SECURITY/LABEL_TWO_FACTOR_USER"></span>
|
||||
</label>
|
||||
<div class="controls" style="padding-top: 5px;">
|
||||
<strong><span data-bind="text: viewUser"></span></strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="control-group" data-bind="visible: capaTwoFactor">
|
||||
<label class="control-label"></label>
|
||||
<div class="controls">
|
||||
<a class="btn" data-bind="click: clearTwoFactor, visible: twoFactorStatus">
|
||||
<i class="icon-remove" data-bind="css: {'icon-remove': !clearing(), 'icon-spinner animated': clearing()}" ></i>
|
||||
|
||||
<span class="i18n" data-i18n="SETTINGS_SECURITY/BUTTON_CLEAR"></span>
|
||||
</a>
|
||||
<a class="btn" data-bind="click: createTwoFactor, visible: !twoFactorStatus()">
|
||||
<i class="icon-ok" data-bind="css: {'icon-ok': !processing(), 'icon-spinner animated': processing()}" ></i>
|
||||
|
||||
<span class="i18n" data-i18n="SETTINGS_SECURITY/BUTTON_CREATE"></span>
|
||||
</a>
|
||||
<span> </span>
|
||||
<a class="btn" data-bind="click: testTwoFactor, visible: twoFactorStatus">
|
||||
<i class="icon-info"></i>
|
||||
|
||||
<span class="i18n" data-i18n="SETTINGS_SECURITY/BUTTON_TEST"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" data-bind="visible: '' === viewSecret() && twoFactorStatus() && !clearing()">
|
||||
<div class="controls" style="padding-top: 5px;">
|
||||
<strong data-bind="visible: secreting">...</strong>
|
||||
<span class="g-ui-link i18n" data-bind="click: showSecret, visible: !secreting()"
|
||||
data-i18n="SETTINGS_SECURITY/BUTTON_SHOW_SECRET"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" data-bind="visible: '' !== viewSecret()">
|
||||
<label class="control-label">
|
||||
<span class="i18n" data-i18n="SETTINGS_SECURITY/LABEL_TWO_FACTOR_SECRET"></span>
|
||||
</label>
|
||||
<div class="controls" style="padding-top: 5px;">
|
||||
<strong data-bind="text: viewSecret"></strong>
|
||||
<i class="icon-lock" />
|
||||
|
||||
<span class="g-ui-link i18n" data-bind="click: hideSecret" data-i18n="SETTINGS_SECURITY/BUTTON_HIDE_SECRET"></span>
|
||||
<br />
|
||||
<br />
|
||||
<blockquote>
|
||||
<p class="muted i18n" style="width: 550px" data-i18n="SETTINGS_SECURITY/TWO_FACTOR_SECRET_DESC"></p>
|
||||
</blockquote>
|
||||
<!-- ko if: '' !== viewUrl() -->
|
||||
<img style="margin-left: -7px;" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2P8DwQACgAD/il4QJ8AAAAASUVORK5CYII=" data-bind="attr: {'src': viewUrl}" />
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" data-bind="visible: '' !== viewBackupCodes()">
|
||||
<label class="control-label">
|
||||
<span class="i18n" data-i18n="SETTINGS_SECURITY/LABEL_TWO_FACTOR_BACKUP_CODES"></span>
|
||||
</label>
|
||||
<div class="controls" style="padding-top: 5px;">
|
||||
<pre data-bind="text: viewBackupCodes" style="width: 230px; word-break: break-word;"></pre>
|
||||
<br />
|
||||
<blockquote>
|
||||
<p class="muted i18n" style="width: 550px" data-i18n="SETTINGS_SECURITY/TWO_FACTOR_BACKUP_CODES_DESC"></p>
|
||||
</blockquote>
|
||||
<span class="i18n g-ui-link" data-i18n="SETTINGS_SECURITY/LABEL_CONFIGURATE_TWO_FACTOR" data-bind="click:configureTwoFactor"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue