From 653d47e74eab4bf4e097447e4de12556a73d23b0 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Wed, 28 Sep 2016 12:22:44 -0400 Subject: [PATCH] LP#1467663 webstaff: login requires valid workstation Hide the workstation selector when no workstations are registered. After successful login, direct the user to the new workstation admin page to create a new workstation. After successful login with an invalid workstation, direct the user to the workstation admin page, issuing a 'remove' command to un-register the offending WS. On the WS admin page, the user can create a new workstation or select from their existing workstations. Any attempt to access a browser client interface (minus the WS admin page) without a valid workstation will cause the page to redirect to the workstation admin page. Signed-off-by: Bill Erickson Signed-off-by: Mike Rylander Signed-off-by: Kathy Lussier --- Open-ILS/src/templates/staff/t_login.tt2 | 2 +- Open-ILS/web/js/ui/default/staff/app.js | 38 +++- .../web/js/ui/default/staff/services/auth.js | 164 ++++++++++++------ 3 files changed, 138 insertions(+), 66 deletions(-) diff --git a/Open-ILS/src/templates/staff/t_login.tt2 b/Open-ILS/src/templates/staff/t_login.tt2 index 135e9daacd..ce06e6b097 100644 --- a/Open-ILS/src/templates/staff/t_login.tt2 +++ b/Open-ILS/src/templates/staff/t_login.tt2 @@ -29,7 +29,7 @@ -
+
diff --git a/Open-ILS/web/js/ui/default/staff/app.js b/Open-ILS/web/js/ui/default/staff/app.js index 41910b9bec..4cf388ce85 100644 --- a/Open-ILS/web/js/ui/default/staff/app.js +++ b/Open-ILS/web/js/ui/default/staff/app.js @@ -43,6 +43,8 @@ function($routeProvider , $locationProvider) { ['$scope','$location','$window','egCore', function($scope , $location , $window , egCore) { $scope.focusMe = true; + $scope.args = {}; + $scope.workstations = []; // if the user is already logged in, jump to splash page if (egCore.auth.user()) $location.path('/'); @@ -92,17 +94,37 @@ function($routeProvider , $locationProvider) { if (! (args.username && args.password) ) return; + // if at least one workstation exists, it must be used. + if (!args.workstation && $scope.workstations.length > 0) return; + args.type = 'staff'; egCore.auth.login(args).then( - function() { - // after login, send the user back to the originally - // requested page or, if none, the home page. - // TODO: this is a little hinky because it causes 2 - // redirects if no route_to is defined. Improve. - $window.location.href = - $location.search().route_to || - $location.path('/').absUrl() + function(result) { + // After login, send the user to: + // 1. The WS admin page for WS maintenance. + // 2. The page originally requested by the caller + // 3. Home page. + + // NOTE: using $location.path(...) results in + // confusing intermediate page loads, since + // path(...) is a setter function. Build the URL by + // hand instead from the configured base path. + var route_to = egCore.env.basePath; + + if (result.invalid_workstation) { + // route to WS admin page to delete the offending + // WS and create a new one. + route_to += + 'admin/workstation/workstations?remove=' + + encodeURIComponent(args.workstation); + + } else if ($location.search().route_to) { + // Route to the originally requested page. + route_to = $location.search().route_to; + } + + $window.location.href = route_to; }, function() { $scope.args.password = ''; diff --git a/Open-ILS/web/js/ui/default/staff/services/auth.js b/Open-ILS/web/js/ui/default/staff/services/auth.js index a677ff4bf2..3446f4a80a 100644 --- a/Open-ILS/web/js/ui/default/staff/services/auth.js +++ b/Open-ILS/web/js/ui/default/staff/services/auth.js @@ -6,8 +6,8 @@ angular.module('egCoreMod') .factory('egAuth', - ['$q','$timeout','$rootScope','egNet','egHatch', -function($q , $timeout , $rootScope , egNet , egHatch) { + ['$q','$timeout','$rootScope','$window','$location','egNet','egHatch', +function($q , $timeout , $rootScope , $window , $location , egNet , egHatch) { var service = { // the currently active user (au) object @@ -49,23 +49,8 @@ function($q , $timeout , $rootScope , egNet , egHatch) { // authtoken test succeeded service._user = user; service.poll(); - - if (user.wsid()) { - // user previously logged in with a workstation. - // Find the workstation name from the list - // of configured workstations - egHatch.getItem('eg.workstation.all') - .then(function(all) { - if (all) { - var ws = all.filter( - function(w) {return w.id == user.wsid()})[0]; - if (ws) service.ws = ws.name; - } - deferred.resolve(); // found WS - }); - } else { - deferred.resolve(); // no WS - } + service.check_workstation(deferred); + } else { // authtoken test failed egHatch.clearLoginSessionItems(); @@ -75,60 +60,125 @@ function($q , $timeout , $rootScope , egNet , egHatch) { } else { // no authtoken to test - deferred.reject(); + deferred.reject('No authtoken found'); } return deferred.promise; }; + service.check_workstation = function(deferred) { + + var user = service.user(); + var ws_path = '/admin/workstation/workstations'; + + return egHatch.getItem('eg.workstation.all') + .then(function(workstations) { + if (!workstations) workstations = []; + + // If the user is authenticated with a workstation, get the + // name from the locally registered version of the workstation. + + if (user.wsid()) { + + var ws = workstations.filter( + function(w) {return w.id == user.wsid()})[0]; + + if (ws) { // success + service.ws = ws.name; + deferred.resolve(); + return; + } + } + + if ($location.path() == ws_path) { + // User is on the workstation admin page. No need + // to redirect. + deferred.resolve(); + return; + } + + // At this point, the user is trying to access a page + // besides the workstation admin page without a valid + // registered workstation. Send them back to the + // workstation admin page. + + // NOTE: egEnv also defines basePath, but we cannot import + // egEnv here becuase it creates a circular reference. + $window.location.href = '/eg/staff' + ws_path; + deferred.resolve(); + }); + } + /** * Returns a promise, which is resolved on successful * login and rejected on failed login. */ - service.login = function(args) { - var deferred = $q.defer(); + service.login = function(args, ops) { + // avoid modifying the caller's data structure. + args = angular.copy(args); + + if (!ops) { // only set on redo attempts. + ops = {deferred : $q.defer()}; + + // Clear old LoginSession keys that were left in localStorage + // when the previous user closed the browser without logging + // out. Under normal circumstance, LoginSession data would + // have been cleared by now, either during logout or cookie + // expiration. But, if for some reason the user manually + // removed the auth token cookie w/o closing the browser + // (say, for testing), then this serves double duty to ensure + // LoginSession data cannot persist across logins. + egHatch.clearLoginSessionItems(); + } - // Clear old LoginSession keys that were left in localStorage - // when the previous user closed the browser without logging - // out. Under normal circumstance, LoginSession data would - // have been cleared by now, either during logout or cookie - // expiration. But, if for some reason the user manually - // removed the auth token cookie w/o closing the browser - // (say, for testing), then this serves double duty to ensure - // LoginSession data cannot persist across logins. - egHatch.clearLoginSessionItems(); + service.login_api(args).then(function(evt) { - egNet.request( + if (evt.textcode == 'SUCCESS') { + service.handle_login_ok(args, evt); + ops.deferred.resolve({ + invalid_workstation : ops.invalid_workstation + }); + + } else if (evt.textcode == 'WORKSTATION_NOT_FOUND') { + ops.invalid_workstation = true; + delete args.workstation; + service.login(args, ops); // redo w/o workstation + + } else { + // note: the likely outcome here is a NO_SESION + // server event, which results in broadcasting an + // egInvalidAuth by egNet. + console.error('login failed ' + js2JSON(evt)); + ops.deferred.reject(); + } + }); + + return ops.deferred.promise; + } + + service.login_api = function(args) { + return egNet.request( 'open-ils.auth', - 'open-ils.auth.authenticate.init', args.username).then( - function(seed) { - args.password = hex_md5(seed + hex_md5(args.password)) - egNet.request( + 'open-ils.auth.authenticate.init', args.username) + .then(function(seed) { + // avoid clobbering the bare password in case + // we need it for a login redo attempt. + var login_args = angular.copy(args); + login_args.password = hex_md5(seed + hex_md5(args.password)); + + return egNet.request( 'open-ils.auth', - 'open-ils.auth.authenticate.complete', args).then( - function(evt) { - if (evt.textcode == 'SUCCESS') { - service.ws = args.workstation; - service.poll(); - egHatch.setLoginSessionItem( - 'eg.auth.token', evt.payload.authtoken); - egHatch.setLoginSessionItem( - 'eg.auth.time', evt.payload.authtime); - deferred.resolve(); - } else { - // note: the likely outcome here is a NO_SESION - // server event, which results in broadcasting an - // egInvalidAuth by egNet. - console.error('login failed ' + js2JSON(evt)); - deferred.reject(); - } - } - ) + 'open-ils.auth.authenticate.complete', login_args) } ); + } - return deferred.promise; - }; + service.handle_login_ok = function(args, evt) { + service.ws = args.workstation; + egHatch.setLoginSessionItem('eg.auth.token', evt.payload.authtoken); + egHatch.setLoginSessionItem('eg.auth.time', evt.payload.authtime); + service.poll(); + } /** * Force-check the validity of the authtoken on occasion. -- 2.43.2