diff --git a/tryton/sao/src/sao.js b/tryton/sao/src/sao.js index bc6b3659..d495b9ad 100644 --- a/tryton/sao/src/sao.js +++ b/tryton/sao/src/sao.js @@ -649,6 +649,10 @@ var Sao = { 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 @@ var Sao = { } 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 --git a/tryton/sao/src/session.js b/tryton/sao/src/session.js index 5f4753fc..dfb01dcd 100644 --- a/tryton/sao/src/session.js +++ b/tryton/sao/src/session.js @@ -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('', { + 'class': 'btn btn-primary btn-block', + 'type': 'submit', + 'title': Sao.i18n.gettext("Login"), + }).text(' ' + Sao.i18n.gettext("Login")); dialog.body.append(jQuery('
', { 'class': 'form-group' }).append(jQuery('', { @@ -222,20 +229,22 @@ 'for': 'database' }).text(Sao.i18n.gettext('Database'))) .append(dialog.database_select) - .append(dialog.database_input) - ).append(jQuery('', { + .append(dialog.database_input)) + .append(jQuery('', { + 'class': 'panel panel-default', + }) + .append(jQuery('', { + 'class': 'panel-body', + }) + .append(jQuery('', { 'class': 'form-group' }).append(jQuery('', { 'class': 'control-label', 'for': 'login' }).text(Sao.i18n.gettext('User name'))) .append(dialog.login_input) - ); - dialog.button = jQuery('', { - '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('', { + 'class': 'panel-body', + }).append(jQuery('') + .text(Sao.i18n.gettext("Login with"))); + dialog.body.append(jQuery('', { + 'class': 'panel panel-default', + }).append(panel_body)); + for (const [name, url] of services) { + panel_body.append(jQuery('', { + '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; + }); + }; }());