luci-theme-bootstrap: simplify login dialog
authorJo-Philipp Wich <jo@mein.io>
Thu, 9 Dec 2021 18:48:12 +0000 (19:48 +0100)
committerJo-Philipp Wich <jo@mein.io>
Thu, 9 Dec 2021 18:52:48 +0000 (19:52 +0100)
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>
themes/luci-theme-bootstrap/htdocs/luci-static/resources/view/bootstrap/sysauth.js
themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/sysauth.htm

index 344b043a36e5917bcc8bbe55b7c720d39402db41..fd936c9b1037a75356f65226a7e97864c0d6d390 100644 (file)
@@ -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;
-
-               m = new form.JSONMap(data);
-               s = m.section(form.NamedSection, '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');
+       render: function() {
+               var form = document.querySelector('form'),
+                   btn = document.querySelector('button');
+
+               var dlg = ui.showModal(
+                       _('Authorization Required'),
+                       [].slice.call(document.querySelectorAll('section > *')),
+                       'login'
+               );
+
+               form.addEventListener('keypress', function(ev) {
+                       if (ev.key == 'Enter')
+                               btn.click();
                });
-       },
-
-       handleLoginReply: function(res) {
-               if (res.status != 403) {
-                       ui.hideModal();
-                       location.reload();
 
-                       return;
-               }
+               btn.addEventListener('click', function() {
+                       dlg.querySelectorAll('*').forEach(function(node) { node.style.display = 'none' });
+                       dlg.appendChild(E('div', { 'class': 'spinning' }, _('Logging in…')));
 
-               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');
+                       form.submit()
                });
-       },
-
-       handleLogin: function(form, ev) {
-               var fd = new FormData();
-
-               document.querySelectorAll('.alert-message.error').forEach(function(msg) {
-                       msg.classList.add('hidden');
-                       msg.classList.remove('flash');
-               });
-
-               dom.callClassMethod(form, 'save');
-
-               fd.append('luci_username', data.login.username != null ? data.login.username : '');
-               fd.append('luci_password', data.login.password != null ? data.login.password : '');
 
-               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() {}
index 2427199bf550e8b2a485c99eea8f1aa1a4c8d075..b5413ed36ec264c644a218f9234bdf4f52a629e0 100644 (file)
 
 <%+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');
                });