changeset b70631ec1852 in sao:default
details: https://hg.tryton.org/sao?cmd=changeset&node=b70631ec1852
description:
        Add authentication services

        issue11582
        review417471003
diffstat:

 CHANGELOG      |    1 +
 src/sao.js     |   25 +++++++++
 src/session.js |  148 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 158 insertions(+), 16 deletions(-)

diffs (287 lines):

diff -r 4dacbcf16843 -r b70631ec1852 CHANGELOG
--- a/CHANGELOG Mon Oct 03 00:22:51 2022 +0200
+++ b/CHANGELOG Sun Oct 09 18:33:16 2022 +0200
@@ -1,3 +1,4 @@
+* Support authentication services
 * Check server version
 
 Version 6.4.0 - 2022-05-02
diff -r 4dacbcf16843 -r b70631ec1852 src/sao.js
--- a/src/sao.js        Mon Oct 03 00:22:51 2022 +0200
+++ b/src/sao.js        Sun Oct 09 18:33:16 2022 +0200
@@ -649,6 +649,10 @@
 
     Sao.logout = function() {
         var session = Sao.Session.current_session;
+        if (!session || !session.session) {
+            // Do not save states if there is no session
+            Sao.main_menu_screen = null;
+        }
         Sao.Tab.tabs.close(true).done(function() {
             jQuery('#user-preferences').empty();
             jQuery('#global-search').empty();
@@ -1153,6 +1157,27 @@
     }
 
     jQuery(document).ready(function() {
+        var url = new URL(window.location);
+        if (url.searchParams.has('session')) {
+            var database = url.searchParams.get('database');
+            var session = {
+                login_service: url.searchParams.get('login_service'),
+                login: url.searchParams.get('login'),
+                user_id: parseInt(url.searchParams.get('user_id'), 10),
+                session: url.searchParams.get('session'),
+            };
+            if (url.searchParams.has('renew')) {
+                var renew_id = parseInt(url.searchParams.get('renew'), 10);
+                if (session.user_id !== renew_id) {
+                    window.close();
+                    return;
+                }
+            }
+            session = JSON.stringify(session);
+            localStorage.setItem('sao_session_' + database, session);
+            window.close();
+            return;
+        }
         set_shortcuts();
         try {
             Notification.requestPermission();
diff -r 4dacbcf16843 -r b70631ec1852 src/session.js
--- a/src/session.js    Mon Oct 03 00:22:51 2022 +0200
+++ b/src/session.js    Sun Oct 09 18:33:16 2022 +0200
@@ -10,6 +10,7 @@
 
     Sao.Session = Sao.class_(Object, {
         init: function(database, login) {
+            this.login_service = null;
             this.user_id = null;
             this.session = null;
             this.cache = new Cache();
@@ -124,6 +125,7 @@
                 if (session_data !== null) {
                     session_data = JSON.parse(session_data);
                     if (!this.login || this.login == session_data.login) {
+                        this.login_service = session_data.login_service;
                         this.login = session_data.login;
                         this.user_id = session_data.user_id;
                         this.session = session_data.session;
@@ -215,6 +217,11 @@
             'name': 'login',
             'placeholder': Sao.i18n.gettext('User name')
         });
+        dialog.button = jQuery('<button/>', {
+            'class': 'btn btn-primary btn-block',
+            'type': 'submit',
+            'title': Sao.i18n.gettext("Login"),
+        }).text(' ' + Sao.i18n.gettext("Login"));
         dialog.body.append(jQuery('<div/>', {
             'class': 'form-group'
         }).append(jQuery('<label/>', {
@@ -222,20 +229,22 @@
             'for': 'database'
         }).text(Sao.i18n.gettext('Database')))
         .append(dialog.database_select)
-        .append(dialog.database_input)
-        ).append(jQuery('<div/>', {
+        .append(dialog.database_input))
+        .append(jQuery('<div/>', {
+            'class': 'panel panel-default',
+        })
+        .append(jQuery('<div/>', {
+            'class': 'panel-body',
+        })
+        .append(jQuery('<div/>', {
             'class': 'form-group'
         }).append(jQuery('<label/>', {
             'class': 'control-label',
             'for': 'login'
         }).text(Sao.i18n.gettext('User name')))
         .append(dialog.login_input)
-        );
-        dialog.button = jQuery('<button/>', {
-            'class': 'btn btn-primary',
-            'type': 'submit',
-            'title': Sao.i18n.gettext("Login"),
-        }).text(' ' + Sao.i18n.gettext("Login")).appendTo(dialog.footer);
+        )
+        .append(dialog.button)));
         return dialog;
     };
 
@@ -261,7 +270,11 @@
                 });
         };
 
-        var ok_func = function() {
+        var disable_form = function(disabled=true) {
+            dialog.body.find('input,select,button').prop('disabled', disabled);
+        };
+
+        var login = function() {
             var login = dialog.login_input.val();
             var database = database || dialog.database_select.val() ||
                 dialog.database_input.val();
@@ -271,7 +284,7 @@
                 return;
             }
             dialog.button.focus();
-            dialog.button.prop('disabled', true);
+            disable_form();
             dialog.modal.modal('hide');
             session.database = database;
             session.login = login;
@@ -284,19 +297,54 @@
                         window.location = '#' + database;
                     }
                 }, function() {
-                    dialog.button.prop('disabled', false);
+                    disable_form(false);
                     dialog.modal.modal('show');
                     empty_field().closest('.form-group').addClass('has-error');
                     empty_field().first().focus();
                 });
         };
 
+        var login_service = function(evt) {
+            var database = database || dialog.database_select.val() ||
+                dialog.database_input.val();
+            dialog.modal.find('.has-error').removeClass('has-error');
+            if (!database) {
+                dialog.database_select
+                    .closest('.form-group').addClass('has-error');
+                return;
+            }
+            disable_form();
+            var host = window.location.protocol + '//' + window.location.host;
+            var next = new URL(host + '/');
+            next.searchParams.append('login_service', evt.data);
+            var url = new URL(host + '/' + database + evt.data);
+            url.searchParams.append('next', next.href);
+            var service_window = window.open(url.href, '_blank', 'popup=1');
+            const timer = window.setInterval(() => {
+                if (service_window.closed) {
+                    window.clearInterval(timer);
+                    session.database = database;
+                    session.restore();
+                    if (session.session) {
+                        dfd.resolve(session);
+                        dialog.modal.remove();
+                        if (database_url() != database) {
+                            window.location = '#' + database;
+                        }
+                    } else {
+                        disable_form(false);
+                        empty_field().first().focus();
+                    }
+                }
+            }, 500);
+        };
+
         dialog.modal.modal({
             backdrop: false,
             keyboard: false
         });
         dialog.modal.find('form').unbind().submit(function(e) {
-            ok_func();
+            login();
             e.preventDefault();
         });
         dialog.modal.on('shown.bs.modal', function() {
@@ -324,6 +372,24 @@
         }, function() {
             dialog.database_input.show();
         });
+
+        jQuery.when(Sao.Authentication.services()).then(function(services) {
+            if (services.length) {
+                var panel_body = jQuery('<div/>', {
+                    'class': 'panel-body',
+                }).append(jQuery('<p/>')
+                    .text(Sao.i18n.gettext("Login with")));
+                dialog.body.append(jQuery('<div/>', {
+                    'class': 'panel panel-default',
+                }).append(panel_body));
+                for (const [name, url] of services) {
+                    panel_body.append(jQuery('<button/>', {
+                        'class': 'btn btn-block btn-default',
+                        'type': 'button',
+                    }).text(name).click(url, login_service));
+                }
+            }
+        });
         return dfd.promise();
     };
 
@@ -332,11 +398,36 @@
             return session.prm;
         }
         var dfd = jQuery.Deferred();
+        session.session = null;
         session.prm = dfd.promise();
-        session.do_login().then(dfd.resolve, function() {
-            Sao.logout();
-            dfd.reject();
-        }).done(function () {
+        if (!session.login_service) {
+            session.do_login().then(dfd.resolve, function() {
+                Sao.logout();
+                dfd.reject();
+            });
+        } else {
+            session.unstore();
+            var host = window.location.protocol + '//' + window.location.host;
+            var next = new URL(host + '/');
+            next.searchParams.append('login_service', session.login_service);
+            next.searchParams.append('renew', session.user_id);
+            var url = new URL(host + '/' + session.database + 
session.login_service);
+            url.searchParams.append('next', next.href);
+            var service_window = window.open(url.href, '_blank', 'popup=1');
+            const timer = window.setInterval(() => {
+                if (service_window.closed) {
+                    window.clearInterval(timer);
+                    session.restore();
+                    if (session.session) {
+                        dfd.resolve();
+                    } else {
+                        Sao.logout();
+                        dfd.reject();
+                    }
+                }
+            }, 500);
+        }
+        dfd.done(function() {
             Sao.Bus.listen();
         });
         return session.prm;
@@ -485,4 +576,29 @@
             return data.result;
         });
     };
+
+    Sao.Authentication = {};
+
+    Sao.Authentication.services = function() {
+        var timeoutID = Sao.common.processing.show();
+        return jQuery.ajax({
+            'contentType': 'application/json',
+            'data': JSON.stringify({
+                'id': 0,
+                'method': 'common.authentication.services',
+                'params': []
+            }),
+            'dataType': 'json',
+            'url': '/',
+            'type': 'post',
+            'complete': [function() {
+                Sao.common.processing.hide(timeoutID);
+            }]
+        }).then(function(data) {
+            Sao.Authentication.services = function() {
+                return data.result;
+            };
+            return data.result;
+        });
+    };
 }());

Reply via email to