mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Added new admin login text input (Admin/Security)
Themes now work for admin panel too.
This commit is contained in:
parent
8cf8b94d39
commit
adb92ba3ef
7 changed files with 162 additions and 82 deletions
|
|
@ -1337,6 +1337,46 @@
|
||||||
return Utils.settingsSaveHelperFunction(null, koTrigger, oContext, 1000);
|
return Utils.settingsSaveHelperFunction(null, koTrigger, oContext, 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Utils.settingsSaveHelperSubscribeFunction = function (oRemote, sSettingName, sType, fTriggerFunction)
|
||||||
|
{
|
||||||
|
return function (mValue) {
|
||||||
|
|
||||||
|
if (oRemote)
|
||||||
|
{
|
||||||
|
switch (sType)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
mValue = Utils.pString(mValue);
|
||||||
|
break;
|
||||||
|
case 'bool':
|
||||||
|
case 'boolean':
|
||||||
|
mValue = mValue ? '1' : '0';
|
||||||
|
break;
|
||||||
|
case 'int':
|
||||||
|
case 'integer':
|
||||||
|
case 'number':
|
||||||
|
mValue = Utils.pInt(mValue);
|
||||||
|
break;
|
||||||
|
case 'trim':
|
||||||
|
mValue = Utils.trim(mValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var oData = {};
|
||||||
|
oData[sSettingName] = mValue;
|
||||||
|
|
||||||
|
if (oRemote.saveAdminConfig)
|
||||||
|
{
|
||||||
|
oRemote.saveAdminConfig(fTriggerFunction || null, oData);
|
||||||
|
}
|
||||||
|
else if (oRemote.saveSettings)
|
||||||
|
{
|
||||||
|
oRemote.saveSettings(fTriggerFunction || null, oData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} sHtml
|
* @param {string} sHtml
|
||||||
* @return {string}
|
* @return {string}
|
||||||
|
|
@ -2013,6 +2053,81 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Utils.__themeTimer = 0;
|
||||||
|
Utils.__themeAjax = null;
|
||||||
|
|
||||||
|
Utils.changeTheme = function (sValue, themeTrigger)
|
||||||
|
{
|
||||||
|
var
|
||||||
|
oThemeLink = $('#rlThemeLink'),
|
||||||
|
oThemeStyle = $('#rlThemeStyle'),
|
||||||
|
sUrl = oThemeLink.attr('href')
|
||||||
|
;
|
||||||
|
|
||||||
|
if (!sUrl)
|
||||||
|
{
|
||||||
|
sUrl = oThemeStyle.attr('data-href');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sUrl)
|
||||||
|
{
|
||||||
|
sUrl = sUrl.toString().replace(/\/-\/[^\/]+\/\-\//, '/-/' + sValue + '/-/');
|
||||||
|
sUrl = sUrl.toString().replace(/\/Css\/[^\/]+\/User\//, '/Css/0/User/');
|
||||||
|
|
||||||
|
if ('Json/' !== sUrl.substring(sUrl.length - 5, sUrl.length))
|
||||||
|
{
|
||||||
|
sUrl += 'Json/';
|
||||||
|
}
|
||||||
|
|
||||||
|
window.clearTimeout(Utils.__themeTimer);
|
||||||
|
themeTrigger(Enums.SaveSettingsStep.Animate);
|
||||||
|
|
||||||
|
if (Utils.__themeAjax && Utils.__themeAjax.abort)
|
||||||
|
{
|
||||||
|
Utils.__themeAjax.abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils.__themeAjax = $.ajax({
|
||||||
|
'url': sUrl,
|
||||||
|
'dataType': 'json'
|
||||||
|
}).done(function(aData) {
|
||||||
|
|
||||||
|
if (aData && Utils.isArray(aData) && 2 === aData.length)
|
||||||
|
{
|
||||||
|
if (oThemeLink && oThemeLink[0] && (!oThemeStyle || !oThemeStyle[0]))
|
||||||
|
{
|
||||||
|
oThemeStyle = $('<style id="rlThemeStyle"></style>');
|
||||||
|
oThemeLink.after(oThemeStyle);
|
||||||
|
oThemeLink.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oThemeStyle && oThemeStyle[0])
|
||||||
|
{
|
||||||
|
oThemeStyle.attr('data-href', sUrl).attr('data-theme', aData[0]);
|
||||||
|
if (oThemeStyle && oThemeStyle[0] && oThemeStyle[0].styleSheet && !Utils.isUnd(oThemeStyle[0].styleSheet.cssText))
|
||||||
|
{
|
||||||
|
oThemeStyle[0].styleSheet.cssText = aData[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oThemeStyle.text(aData[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
themeTrigger(Enums.SaveSettingsStep.TrueResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
}).always(function() {
|
||||||
|
|
||||||
|
Utils.__themeTimer = window.setTimeout(function () {
|
||||||
|
themeTrigger(Enums.SaveSettingsStep.Idle);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
Utils.__themeAjax = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = Utils;
|
module.exports = Utils;
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
|
@ -89,6 +89,9 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
self.theme.subscribe(function (sValue) {
|
self.theme.subscribe(function (sValue) {
|
||||||
|
|
||||||
|
Utils.changeTheme(sValue, self.themeTrigger);
|
||||||
|
|
||||||
Remote.saveAdminConfig(f3, {
|
Remote.saveAdminConfig(f3, {
|
||||||
'Theme': Utils.trim(sValue)
|
'Theme': Utils.trim(sValue)
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
this.capaTwoFactorAuth = ko.observable(Settings.capa(Enums.Capa.TwoFactor));
|
this.capaTwoFactorAuth = ko.observable(Settings.capa(Enums.Capa.TwoFactor));
|
||||||
|
|
||||||
this.adminLogin = ko.observable(Settings.settingsGet('AdminLogin'));
|
this.adminLogin = ko.observable(Settings.settingsGet('AdminLogin'));
|
||||||
|
this.adminLoginError = ko.observable(false);
|
||||||
this.adminPassword = ko.observable('');
|
this.adminPassword = ko.observable('');
|
||||||
this.adminPasswordNew = ko.observable('');
|
this.adminPasswordNew = ko.observable('');
|
||||||
this.adminPasswordNew2 = ko.observable('');
|
this.adminPasswordNew2 = ko.observable('');
|
||||||
|
|
@ -40,6 +41,10 @@
|
||||||
this.adminPasswordUpdateSuccess(false);
|
this.adminPasswordUpdateSuccess(false);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
|
this.adminLogin.subscribe(function () {
|
||||||
|
this.adminLoginError(false);
|
||||||
|
}, this);
|
||||||
|
|
||||||
this.adminPasswordNew.subscribe(function () {
|
this.adminPasswordNew.subscribe(function () {
|
||||||
this.adminPasswordUpdateError(false);
|
this.adminPasswordUpdateError(false);
|
||||||
this.adminPasswordUpdateSuccess(false);
|
this.adminPasswordUpdateSuccess(false);
|
||||||
|
|
@ -54,6 +59,12 @@
|
||||||
|
|
||||||
this.saveNewAdminPasswordCommand = Utils.createCommand(this, function () {
|
this.saveNewAdminPasswordCommand = Utils.createCommand(this, function () {
|
||||||
|
|
||||||
|
if ('' === Utils.trim(this.adminLogin()))
|
||||||
|
{
|
||||||
|
this.adminLoginError(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.adminPasswordNew() !== this.adminPasswordNew2())
|
if (this.adminPasswordNew() !== this.adminPasswordNew2())
|
||||||
{
|
{
|
||||||
this.adminPasswordNewError(true);
|
this.adminPasswordNewError(true);
|
||||||
|
|
@ -64,12 +75,13 @@
|
||||||
this.adminPasswordUpdateSuccess(false);
|
this.adminPasswordUpdateSuccess(false);
|
||||||
|
|
||||||
Remote.saveNewAdminPassword(this.onNewAdminPasswordResponse, {
|
Remote.saveNewAdminPassword(this.onNewAdminPasswordResponse, {
|
||||||
|
'Login': this.adminLogin(),
|
||||||
'Password': this.adminPassword(),
|
'Password': this.adminPassword(),
|
||||||
'NewPassword': this.adminPasswordNew()
|
'NewPassword': this.adminPasswordNew()
|
||||||
});
|
});
|
||||||
|
|
||||||
}, function () {
|
}, function () {
|
||||||
return '' !== this.adminPassword() && '' !== this.adminPasswordNew() && '' !== this.adminPasswordNew2();
|
return '' !== Utils.trim(this.adminLogin()) && '' !== this.adminPassword();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.onNewAdminPasswordResponse = _.bind(this.onNewAdminPasswordResponse, this);
|
this.onNewAdminPasswordResponse = _.bind(this.onNewAdminPasswordResponse, this);
|
||||||
|
|
|
||||||
|
|
@ -38,74 +38,7 @@
|
||||||
oTheme.selected(sValue === oTheme.name);
|
oTheme.selected(sValue === oTheme.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
var
|
Utils.changeTheme(sValue, self.themeTrigger);
|
||||||
oThemeLink = $('#rlThemeLink'),
|
|
||||||
oThemeStyle = $('#rlThemeStyle'),
|
|
||||||
sUrl = oThemeLink.attr('href')
|
|
||||||
;
|
|
||||||
|
|
||||||
if (!sUrl)
|
|
||||||
{
|
|
||||||
sUrl = oThemeStyle.attr('data-href');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sUrl)
|
|
||||||
{
|
|
||||||
sUrl = sUrl.toString().replace(/\/-\/[^\/]+\/\-\//, '/-/' + sValue + '/-/');
|
|
||||||
sUrl = sUrl.toString().replace(/\/Css\/[^\/]+\/User\//, '/Css/0/User/');
|
|
||||||
|
|
||||||
if ('Json/' !== sUrl.substring(sUrl.length - 5, sUrl.length))
|
|
||||||
{
|
|
||||||
sUrl += 'Json/';
|
|
||||||
}
|
|
||||||
|
|
||||||
window.clearTimeout(self.iTimer);
|
|
||||||
self.themeTrigger(Enums.SaveSettingsStep.Animate);
|
|
||||||
|
|
||||||
if (this.oThemeAjaxRequest && this.oThemeAjaxRequest.abort)
|
|
||||||
{
|
|
||||||
this.oThemeAjaxRequest.abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.oThemeAjaxRequest = $.ajax({
|
|
||||||
'url': sUrl,
|
|
||||||
'dataType': 'json'
|
|
||||||
}).done(function(aData) {
|
|
||||||
|
|
||||||
if (aData && Utils.isArray(aData) && 2 === aData.length)
|
|
||||||
{
|
|
||||||
if (oThemeLink && oThemeLink[0] && (!oThemeStyle || !oThemeStyle[0]))
|
|
||||||
{
|
|
||||||
oThemeStyle = $('<style id="rlThemeStyle"></style>');
|
|
||||||
oThemeLink.after(oThemeStyle);
|
|
||||||
oThemeLink.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oThemeStyle && oThemeStyle[0])
|
|
||||||
{
|
|
||||||
oThemeStyle.attr('data-href', sUrl).attr('data-theme', aData[0]);
|
|
||||||
if (oThemeStyle && oThemeStyle[0] && oThemeStyle[0].styleSheet && !Utils.isUnd(oThemeStyle[0].styleSheet.cssText))
|
|
||||||
{
|
|
||||||
oThemeStyle[0].styleSheet.cssText = aData[1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oThemeStyle.text(aData[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.themeTrigger(Enums.SaveSettingsStep.TrueResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
}).always(function() {
|
|
||||||
|
|
||||||
self.iTimer = window.setTimeout(function () {
|
|
||||||
self.themeTrigger(Enums.SaveSettingsStep.Idle);
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
self.oThemeAjaxRequest = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Remote.saveSettings(null, {
|
Remote.saveSettings(null, {
|
||||||
'Theme': sValue
|
'Theme': sValue
|
||||||
|
|
|
||||||
|
|
@ -1286,7 +1286,7 @@ class Actions
|
||||||
$sStaticCache = \md5(APP_VERSION.$this->Plugins()->Hash());
|
$sStaticCache = \md5(APP_VERSION.$this->Plugins()->Hash());
|
||||||
|
|
||||||
$sTheme = $this->ValidateTheme($sTheme);
|
$sTheme = $this->ValidateTheme($sTheme);
|
||||||
$sNewThemeLink = './?/Css/0/'.($bAdmin ? 'Admin' : 'User').'/-/'.($bAdmin ? 'Default' : $sTheme).'/-/'.$sStaticCache.'/';
|
$sNewThemeLink = './?/Css/0/'.($bAdmin ? 'Admin' : 'User').'/-/'.$sTheme.'/-/'.$sStaticCache.'/';
|
||||||
|
|
||||||
$bUserLanguage = false;
|
$bUserLanguage = false;
|
||||||
if (!$bAdmin && !$aResult['Auth'] && !empty($_COOKIE['rllang']) &&
|
if (!$bAdmin && !$aResult['Auth'] && !empty($_COOKIE['rllang']) &&
|
||||||
|
|
@ -2705,19 +2705,26 @@ class Actions
|
||||||
|
|
||||||
$sLogin = \trim($this->GetActionParam('Login', ''));
|
$sLogin = \trim($this->GetActionParam('Login', ''));
|
||||||
$sPassword = $this->GetActionParam('Password', '');
|
$sPassword = $this->GetActionParam('Password', '');
|
||||||
$sNewPassword = $this->GetActionParam('NewPassword', '');
|
|
||||||
|
|
||||||
$this->Logger()->AddSecret($sPassword);
|
$this->Logger()->AddSecret($sPassword);
|
||||||
|
|
||||||
|
$sNewPassword = $this->GetActionParam('NewPassword', '');
|
||||||
|
if (0 < \strlen(\trim($sNewPassword)))
|
||||||
|
{
|
||||||
$this->Logger()->AddSecret($sNewPassword);
|
$this->Logger()->AddSecret($sNewPassword);
|
||||||
|
}
|
||||||
|
|
||||||
if ($oConfig->ValidatePassword($sPassword))
|
if ($oConfig->ValidatePassword($sPassword))
|
||||||
{
|
{
|
||||||
if (0 < strlen($sLogin))
|
if (0 < \strlen($sLogin))
|
||||||
{
|
{
|
||||||
$oConfig->Set('security', 'admin_login', $sLogin);
|
$oConfig->Set('security', 'admin_login', $sLogin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 < \strlen(\trim($sNewPassword)))
|
||||||
|
{
|
||||||
$oConfig->SetPassword($sNewPassword);
|
$oConfig->SetPassword($sNewPassword);
|
||||||
|
}
|
||||||
|
|
||||||
$bResult = true;
|
$bResult = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@
|
||||||
<a class="btn" data-bind="click: showActivationForm">
|
<a class="btn" data-bind="click: showActivationForm">
|
||||||
<i class="icon-happy-smiley"></i>
|
<i class="icon-happy-smiley"></i>
|
||||||
|
|
||||||
Activate Subscription Key
|
Activate Subscription Key for this domain
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,20 +14,20 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<label data-bind="click: function () { capaOpenPGP(!capaOpenPGP()); }">
|
<label data-bind="click: function () { useLocalProxyForExternalImages(!useLocalProxyForExternalImages()); }">
|
||||||
<i data-bind="css: capaOpenPGP() ? 'icon-checkbox-checked' : 'icon-checkbox-unchecked'"></i>
|
<i data-bind="css: useLocalProxyForExternalImages() ? 'icon-checkbox-checked' : 'icon-checkbox-unchecked'"></i>
|
||||||
|
|
||||||
Allow OpenPGP
|
Use local proxy for external images
|
||||||
<span style="color:red">(beta)</span>
|
<span style="color:red">(beta)</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<label data-bind="click: function () { useLocalProxyForExternalImages(!useLocalProxyForExternalImages()); }">
|
<label data-bind="click: function () { capaOpenPGP(!capaOpenPGP()); }">
|
||||||
<i data-bind="css: useLocalProxyForExternalImages() ? 'icon-checkbox-checked' : 'icon-checkbox-unchecked'"></i>
|
<i data-bind="css: capaOpenPGP() ? 'icon-checkbox-checked' : 'icon-checkbox-unchecked'"></i>
|
||||||
|
|
||||||
Use local proxy for external images
|
Allow OpenPGP
|
||||||
<span style="color:red">(beta)</span>
|
<span style="color:red">(beta)</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -52,6 +52,16 @@
|
||||||
data-bind="textInput: adminPassword" />
|
data-bind="textInput: adminPassword" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<br />
|
||||||
|
<div class="control-group" data-bind="css: {'error': adminLoginError}">
|
||||||
|
<label class="control-label">
|
||||||
|
New login
|
||||||
|
</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||||
|
data-bind="textInput: adminLogin" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="control-group" data-bind="css: {'error': adminPasswordNewError}">
|
<div class="control-group" data-bind="css: {'error': adminPasswordNewError}">
|
||||||
<label class="control-label">
|
<label class="control-label">
|
||||||
New password
|
New password
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue