luci-theme-bootstrap: simplify login dialog
Use an traditional HTML form with post submit action to the same URL in
order to simplify the login process and not rely on the discarded login
XHR reply properly setting the login cookie.
This will also avoid one useless request on login and hopefully fix login
issues reported with various browser environments.
As a bonus, the resulting code is somewhat smaller as well.
Ref: https://forum.openwrt.org/t/login-does-not-work/113360
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
(cherry picked from commit c81b09ec3d
)
This commit is contained in:
parent
1390f78fad
commit
40051f0302
2 changed files with 49 additions and 85 deletions
|
@ -1,98 +1,33 @@
|
|||
'use strict';
|
||||
'require ui';
|
||||
'require dom';
|
||||
'require form';
|
||||
'require view';
|
||||
'require request';
|
||||
|
||||
var data = { login: {} };
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
var m, s, o;
|
||||
render: function() {
|
||||
var form = document.querySelector('form'),
|
||||
btn = document.querySelector('button');
|
||||
|
||||
m = new form.JSONMap(data);
|
||||
s = m.section(form.NamedSection, 'login');
|
||||
var dlg = ui.showModal(
|
||||
_('Authorization Required'),
|
||||
[].slice.call(document.querySelectorAll('section > *')),
|
||||
'login'
|
||||
);
|
||||
|
||||
o = s.option(form.Value, 'username', _('Username'));
|
||||
o.default = L.env.default_login_user;
|
||||
|
||||
o = s.option(form.Value, 'password', _('Password'));
|
||||
o.password = true;
|
||||
o.validate = function(section_id, value) {
|
||||
var msg = document.querySelector('alert-message');
|
||||
|
||||
if (msg && value.length)
|
||||
msg.parentNode.removeChild(msg);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return m.render();
|
||||
},
|
||||
|
||||
render: function(form) {
|
||||
ui.showModal(_('Authorization Required'), [
|
||||
form,
|
||||
E('hr'),
|
||||
E('div', { 'class': 'alert-message error hidden' }, [
|
||||
_('Invalid username and/or password! Please try again.')
|
||||
]),
|
||||
E('button', {
|
||||
'class': 'btn cbi-button-positive important',
|
||||
'click': ui.createHandlerFn(this, 'handleLogin', form)
|
||||
}, [ _('Login') ])
|
||||
], 'login');
|
||||
|
||||
document.querySelector('[id="widget.cbid.json.login.password"]').focus();
|
||||
|
||||
form.addEventListener('keyup', L.bind(function(form, ev) {
|
||||
if (ev.key === 'Enter' || ev.keyCode === 13)
|
||||
document.querySelector('.cbi-button-positive.important').click();
|
||||
}, this, form));
|
||||
|
||||
return E('div', { 'class': 'spinning' }, _('Loading view…'));
|
||||
},
|
||||
|
||||
handleLoginError: function(err) {
|
||||
document.querySelectorAll('.alert-message.error').forEach(function(msg) {
|
||||
msg.firstChild.data = _('The login request failed with error: %h').format(err.message);
|
||||
msg.classList.remove('hidden');
|
||||
msg.classList.add('flash');
|
||||
});
|
||||
},
|
||||
|
||||
handleLoginReply: function(res) {
|
||||
if (res.status != 403) {
|
||||
ui.hideModal();
|
||||
location.reload();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
document.querySelectorAll('.alert-message.error').forEach(function(msg) {
|
||||
msg.firstChild.data = _('Invalid username and/or password! Please try again.');
|
||||
msg.classList.remove('hidden');
|
||||
msg.classList.add('flash');
|
||||
});
|
||||
},
|
||||
|
||||
handleLogin: function(form, ev) {
|
||||
var fd = new FormData();
|
||||
|
||||
document.querySelectorAll('.alert-message.error').forEach(function(msg) {
|
||||
msg.classList.add('hidden');
|
||||
msg.classList.remove('flash');
|
||||
form.addEventListener('keypress', function(ev) {
|
||||
if (ev.key == 'Enter')
|
||||
btn.click();
|
||||
});
|
||||
|
||||
dom.callClassMethod(form, 'save');
|
||||
btn.addEventListener('click', function() {
|
||||
dlg.querySelectorAll('*').forEach(function(node) { node.style.display = 'none' });
|
||||
dlg.appendChild(E('div', { 'class': 'spinning' }, _('Logging in…')));
|
||||
|
||||
fd.append('luci_username', data.login.username != null ? data.login.username : '');
|
||||
fd.append('luci_password', data.login.password != null ? data.login.password : '');
|
||||
form.submit()
|
||||
});
|
||||
|
||||
Object.getPrototypeOf(L).notifySessionExpiry = function() {};
|
||||
document.querySelector('input[type="password"]').focus();
|
||||
|
||||
return request.post(location.href, fd).then(this.handleLoginReply, this.handleLoginError);
|
||||
return '';
|
||||
},
|
||||
|
||||
addFooter: function() {}
|
||||
|
|
|
@ -10,11 +10,40 @@
|
|||
|
||||
<%+header%>
|
||||
|
||||
<section hidden>
|
||||
<form method="post" class="cbi-map">
|
||||
<div class="cbi-section">
|
||||
<div class="cbi-section-node">
|
||||
<div class="cbi-value">
|
||||
<label class="cbi-value-title" for="luci_username">Username</label>
|
||||
<div class="cbi-value-field">
|
||||
<input name="luci_username" type="text"<%=attr("value", duser)%>>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cbi-value">
|
||||
<label class="cbi-value-title" for="luci_password">Password</label>
|
||||
<div class="cbi-value-field">
|
||||
<input name="luci_password" type="password">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
|
||||
<% if fuser then %>
|
||||
<div class="alert-message error">
|
||||
<%:Invalid username and/or password! Please try again.%>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<button class="btn cbi-button-positive important"><%:Login%></button>
|
||||
</section>
|
||||
|
||||
<div id="view">
|
||||
<div class="spinning"><%:Loading view…%></div>
|
||||
<script type="text/javascript">
|
||||
L.env.default_login_user = <%=luci.http.write_json(duser) %>;
|
||||
|
||||
L.require('ui').then(function(ui) {
|
||||
ui.instantiateView('bootstrap.sysauth');
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue