luci-mod-system: remplement password change as client side view
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
parent
a31d1d10e0
commit
9ae9657a85
4 changed files with 91 additions and 99 deletions
|
@ -50,7 +50,7 @@
|
|||
"ubus": {
|
||||
"file": [ "write", "remove" ],
|
||||
"iwinfo": [ "scan" ],
|
||||
"luci": [ "setInitAction", "setLocaltime" ],
|
||||
"luci": [ "setInitAction", "setLocaltime", "setPassword" ],
|
||||
"uci": [ "add", "apply", "confirm", "delete", "order", "set", "rename" ]
|
||||
},
|
||||
"uci": [ "*" ]
|
||||
|
|
|
@ -1,31 +1,94 @@
|
|||
function submitPassword(ev) {
|
||||
var pw1 = document.body.querySelector('[name="pw1"]'),
|
||||
pw2 = document.body.querySelector('[name="pw2"]');
|
||||
'use strict';
|
||||
'require form';
|
||||
'require rpc';
|
||||
|
||||
if (!pw1.value.length || !pw2.value.length)
|
||||
return;
|
||||
var formData = {
|
||||
password: {
|
||||
pw1: null,
|
||||
pw2: null
|
||||
}
|
||||
};
|
||||
|
||||
if (pw1.value === pw2.value) {
|
||||
L.showModal(_('Change login password'),
|
||||
E('p', { class: 'spinning' }, _('Changing password…')));
|
||||
var callSetPassword = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'setPassword',
|
||||
params: [ 'username', 'password' ],
|
||||
expect: { result: false }
|
||||
});
|
||||
|
||||
L.post('admin/system/admin/password/json', { password: pw1.value },
|
||||
function() {
|
||||
showModal(_('Change login password'), [
|
||||
E('div', _('The system password has been successfully changed.')),
|
||||
E('div', { 'class': 'right' },
|
||||
E('div', { class: 'btn', click: L.hideModal }, _('Dismiss')))
|
||||
]);
|
||||
return L.view.extend({
|
||||
checkPassword: function(section_id, value) {
|
||||
var strength = document.querySelector('.cbi-value-description'),
|
||||
strongRegex = new RegExp("^(?=.{8,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$", "g"),
|
||||
mediumRegex = new RegExp("^(?=.{7,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$", "g"),
|
||||
enoughRegex = new RegExp("(?=.{6,}).*", "g");
|
||||
|
||||
pw1.value = pw2.value = '';
|
||||
if (strength && value.length) {
|
||||
if (false == enoughRegex.test(value))
|
||||
strength.innerHTML = '%s: <span style="color:red">%s</span>'.format(_('Password strength'), _('More Characters'));
|
||||
else if (strongRegex.test(value))
|
||||
strength.innerHTML = '%s: <span style="color:green">%s</span>'.format(_('Password strength'), _('Strong'));
|
||||
else if (mediumRegex.test(value))
|
||||
strength.innerHTML = '%s: <span style="color:orange">%s</span>'.format(_('Password strength'), _('Medium'));
|
||||
else
|
||||
strength.innerHTML = '%s: <span style="color:red">%s</span>'.format(_('Password strength'), _('Weak'));
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var m, s, o;
|
||||
|
||||
m = new form.JSONMap(formData, _('Router Password'), _('Changes the administrator password for accessing the device'));
|
||||
s = m.section(form.NamedSection, 'password', 'password');
|
||||
|
||||
o = s.option(form.Value, 'pw1', _('Password'));
|
||||
o.password = true;
|
||||
o.validate = this.checkPassword;
|
||||
|
||||
o = s.option(form.Value, 'pw2', _('Confirmation'), ' ');
|
||||
o.password = true;
|
||||
o.renderWidget = function(/* ... */) {
|
||||
var node = form.Value.prototype.renderWidget.apply(this, arguments);
|
||||
|
||||
node.childNodes[1].addEventListener('keydown', function(ev) {
|
||||
if (ev.keyCode == 13 && !ev.currentTarget.classList.contains('cbi-input-invalid'))
|
||||
document.querySelector('.cbi-button-save').click();
|
||||
});
|
||||
}
|
||||
else {
|
||||
L.showModal(_('Change login password'), [
|
||||
E('div', { class: 'alert-message warning' },
|
||||
_('Given password confirmation did not match, password not changed!')),
|
||||
E('div', { 'class': 'right' },
|
||||
E('div', { class: 'btn', click: L.hideModal }, _('Dismiss')))
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
return m.render();
|
||||
},
|
||||
|
||||
handleSave: function() {
|
||||
var map = document.querySelector('.cbi-map');
|
||||
|
||||
return L.dom.callClassMethod(map, 'save').then(function() {
|
||||
if (formData.password.pw1 == null || formData.password.pw1.length == 0)
|
||||
return;
|
||||
|
||||
if (formData.password.pw1 != formData.password.pw2) {
|
||||
L.ui.addNotification(null, E('p', _('Given password confirmation did not match, password not changed!')), 'danger');
|
||||
return;
|
||||
}
|
||||
|
||||
return callSetPassword('root', formData.password.pw1).then(function(success) {
|
||||
if (success)
|
||||
L.ui.addNotification(null, E('p', _('The system password has been successfully changed.')), 'info');
|
||||
else
|
||||
L.ui.addNotification(null, E('p', _('Failed to change the system password.')), 'danger');
|
||||
|
||||
formData.password.pw1 = null;
|
||||
formData.password.pw2 = null;
|
||||
|
||||
L.dom.callClassMethod(map, 'render');
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
handleSaveApply: null,
|
||||
handleReset: null
|
||||
});
|
||||
|
|
|
@ -12,8 +12,7 @@ function index()
|
|||
entry({"admin", "system", "ntp_restart"}, call("action_ntp_restart"), nil).leaf = true
|
||||
|
||||
entry({"admin", "system", "admin"}, firstchild(), _("Administration"), 2)
|
||||
entry({"admin", "system", "admin", "password"}, template("admin_system/password"), _("Router Password"), 1)
|
||||
entry({"admin", "system", "admin", "password", "json"}, post("action_password"))
|
||||
entry({"admin", "system", "admin", "password"}, view("system/password"), _("Router Password"), 1)
|
||||
|
||||
if fs.access("/etc/config/dropbear") then
|
||||
entry({"admin", "system", "admin", "dropbear"}, cbi("admin_system/dropbear"), _("SSH Access"), 2)
|
||||
|
@ -281,17 +280,6 @@ function action_reset()
|
|||
http.redirect(luci.dispatcher.build_url('admin/system/flashops'))
|
||||
end
|
||||
|
||||
function action_password()
|
||||
local password = luci.http.formvalue("password")
|
||||
if not password then
|
||||
luci.http.status(400, "Bad Request")
|
||||
return
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ code = luci.sys.user.setpasswd("root", password) })
|
||||
end
|
||||
|
||||
function action_reboot()
|
||||
luci.sys.reboot()
|
||||
end
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
<%+header%>
|
||||
|
||||
<input type="password" aria-hidden="true" style="position:absolute; left:-10000px" />
|
||||
|
||||
<script type="text/javascript">
|
||||
function checkPassword() {
|
||||
var pw1 = document.body.querySelector('[name="pw1"]');
|
||||
var view = document.getElementById("passstrength");
|
||||
|
||||
var strongRegex = new RegExp("^(?=.{8,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$", "g");
|
||||
var mediumRegex = new RegExp("^(?=.{7,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$", "g");
|
||||
var enoughRegex = new RegExp("(?=.{6,}).*", "g");
|
||||
if (false == enoughRegex.test(pw1.value)) {
|
||||
view.innerHTML = '<%:Password strength%>: <span style="color:red"><%:More Characters%></span>';
|
||||
} else if (strongRegex.test(pw1.value)) {
|
||||
view.innerHTML = '<%:Password strength%>: <span style="color:green"><%:Strong%></span>';
|
||||
} else if (mediumRegex.test(pw1.value)) {
|
||||
view.innerHTML = '<%:Password strength%>: <span style="color:orange"><%:Medium%></span>';
|
||||
} else {
|
||||
view.innerHTML = '<%:Password strength%>: <span style="color:red"><%:Weak%></span>';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="cbi-map">
|
||||
<h2><%:Router Password%></h2>
|
||||
|
||||
<div class="cbi-section-descr">
|
||||
<%:Changes the administrator password for accessing the device%>
|
||||
</div>
|
||||
|
||||
<div class="cbi-section-node">
|
||||
<div class="cbi-value">
|
||||
<label class="cbi-value-title" for="image"><%:Password%></label>
|
||||
<div class="cbi-value-field">
|
||||
<input type="password" name="pw1" onkeyup="checkPassword()"/><!--
|
||||
--><button class="cbi-button cbi-button-neutral" title="<%:Reveal/hide password%>" aria-label="<%:Reveal/hide password%>" onclick="var e = this.previousElementSibling; e.type = (e.type === 'password') ? 'text' : 'password'">∗</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cbi-value">
|
||||
<label class="cbi-value-title" for="image"><%:Confirmation%></label>
|
||||
<div class="cbi-value-field">
|
||||
<input type="password" name="pw2" onkeydown="if (event.keyCode === 13) submitPassword(event)" /><!--
|
||||
--><button class="cbi-button cbi-button-neutral" title="<%:Reveal/hide password%>" aria-label="<%:Reveal/hide password%>" onclick="var e = this.previousElementSibling; e.type = (e.type === 'password') ? 'text' : 'password'">∗</button>
|
||||
<div id="passstrength" class="cbi-value-description"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cbi-page-actions">
|
||||
<button class="btn cbi-button-apply" onclick="submitPassword(event)"><%:Save%></button>
|
||||
</div>
|
||||
|
||||
<script type="application/javascript" src="<%=resource%>/view/system/password.js"></script>
|
||||
|
||||
<%+footer%>
|
Loading…
Reference in a new issue