Added "Enforce 2-Step verification" setting

This commit is contained in:
RainLoop Team 2015-04-07 20:39:43 +04:00
parent b7709c8117
commit acb013fbb5
47 changed files with 1271 additions and 908 deletions

View file

@ -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))

View file

@ -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('')

View file

@ -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';

View file

@ -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>
&nbsp;&nbsp;&nbsp;&nbsp;
<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>
&nbsp;&nbsp;
<span style="color:red">(<span data-i18n="HINTS/BETA"></span>)</span>

View file

@ -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">&times;</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>
&nbsp;&nbsp;&nbsp;
<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>
&nbsp;&nbsp;
<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>
&nbsp;&nbsp;
<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>
&nbsp;&nbsp;
<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>
&nbsp;&nbsp;
<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>
&nbsp;&nbsp;
<span class="i18n" data-i18n="POPUPS_TWO_FACTOR_CFG/BUTTON_DONE"></span>
</a>
</div>
</div>
</div>
</div>

View file

@ -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">&times;</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>
&nbsp;&nbsp;
<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>
&nbsp;&nbsp;
<span class="i18n" data-i18n="POPUPS_FILTER/BUTTON_DONE"></span>
</a>
</div>
</div>
</div>
</div>

View file

@ -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>
&nbsp;&nbsp;
<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>
&nbsp;&nbsp;
<span class="i18n" data-i18n="SETTINGS_SECURITY/BUTTON_CREATE"></span>
</a>
<span>&nbsp;&nbsp;</span>
<a class="btn" data-bind="click: testTwoFactor, visible: twoFactorStatus">
<i class="icon-info"></i>
&nbsp;&nbsp;
<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" />
&nbsp;&nbsp;
<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>