summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2019-09-16 07:54:25 +0200
committerJo-Philipp Wich <jo@mein.io>2019-09-16 07:54:25 +0200
commit9ae9657a8585b794bc93b993d83e64b6d7f65b92 (patch)
tree123624bc665e5a72291e07663399962ae46fd5bb
parenta31d1d10e09183a999ab9736e0625415bd87fe25 (diff)
luci-mod-system: remplement password change as client side view
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r--modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json2
-rw-r--r--modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js123
-rw-r--r--modules/luci-mod-system/luasrc/controller/admin/system.lua14
-rw-r--r--modules/luci-mod-system/luasrc/view/admin_system/password.htm59
4 files changed, 95 insertions, 103 deletions
diff --git a/modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json b/modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json
index e28bdfa72..32cb10596 100644
--- a/modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json
+++ b/modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json
@@ -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": [ "*" ]
diff --git a/modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js b/modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js
index 7a79d7e2d..6c5ffa1b2 100644
--- a/modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js
+++ b/modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js
@@ -1,31 +1,94 @@
-function submitPassword(ev) {
- var pw1 = document.body.querySelector('[name="pw1"]'),
- pw2 = document.body.querySelector('[name="pw2"]');
-
- if (!pw1.value.length || !pw2.value.length)
- return;
-
- if (pw1.value === pw2.value) {
- L.showModal(_('Change login password'),
- E('p', { class: 'spinning' }, _('Changing password…')));
-
- 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')))
- ]);
-
- pw1.value = pw2.value = '';
- });
- }
- 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')))
- ]);
+'use strict';
+'require form';
+'require rpc';
+
+var formData = {
+ password: {
+ pw1: null,
+ pw2: null
}
-}
+};
+
+var callSetPassword = rpc.declare({
+ object: 'luci',
+ method: 'setPassword',
+ params: [ 'username', 'password' ],
+ expect: { result: false }
+});
+
+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");
+
+ 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();
+ });
+
+ 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
+});
diff --git a/modules/luci-mod-system/luasrc/controller/admin/system.lua b/modules/luci-mod-system/luasrc/controller/admin/system.lua
index be00a3f67..d1fda1d7c 100644
--- a/modules/luci-mod-system/luasrc/controller/admin/system.lua
+++ b/modules/luci-mod-system/luasrc/controller/admin/system.lua
@@ -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
diff --git a/modules/luci-mod-system/luasrc/view/admin_system/password.htm b/modules/luci-mod-system/luasrc/view/admin_system/password.htm
deleted file mode 100644
index 6ca02a83c..000000000
--- a/modules/luci-mod-system/luasrc/view/admin_system/password.htm
+++ /dev/null
@@ -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%>