1 /* Core Sevice - egAuth
3 * Manages login and auth session retrieval.
6 angular.module('egCoreMod')
9 ['$q','$timeout','$rootScope','egNet','egHatch',
10 function($q , $timeout , $rootScope , egNet , egHatch) {
13 // the currently active user (au) object
18 // the currently active auth token string
20 return egHatch.getLoginSessionItem('eg.auth.token');
23 // authtime in seconds
24 authtime : function() {
25 return egHatch.getLoginSessionItem('eg.auth.time');
28 // the currently active workstation name
29 // For ws_ou or wsid(), see egAuth.user().ws_ou(), etc.
30 workstation : function() {
35 /* Returns a promise, which is resolved if valid
36 * authtoken is found, otherwise rejected */
37 service.testAuthToken = function() {
38 var deferred = $q.defer();
39 var token = service.token();
45 'open-ils.auth.session.retrieve', token)
47 .then(function(user) {
48 if (user && user.classname) {
49 // authtoken test succeeded
54 // user previously logged in with a workstation.
55 // Find the workstation name from the list
56 // of configured workstations
57 egHatch.getItem('eg.workstation.all')
61 function(w) {return w.id == user.wsid()})[0];
62 if (ws) service.ws = ws.name;
64 deferred.resolve(); // found WS
67 deferred.resolve(); // no WS
70 // authtoken test failed
71 egHatch.clearLoginSessionItems();
77 // no authtoken to test
81 return deferred.promise;
85 * Returns a promise, which is resolved on successful
86 * login and rejected on failed login.
88 service.login = function(args) {
89 var deferred = $q.defer();
91 // Clear old LoginSession keys that were left in localStorage
92 // when the previous user closed the browser without logging
93 // out. Under normal circumstance, LoginSession data would
94 // have been cleared by now, either during logout or cookie
95 // expiration. But, if for some reason the user manually
96 // removed the auth token cookie w/o closing the browser
97 // (say, for testing), then this serves double duty to ensure
98 // LoginSession data cannot persist across logins.
99 egHatch.clearLoginSessionItems();
103 'open-ils.auth.authenticate.init', args.username).then(
105 args.password = hex_md5(seed + hex_md5(args.password))
108 'open-ils.auth.authenticate.complete', args).then(
110 if (evt.textcode == 'SUCCESS') {
111 service.ws = args.workstation;
113 egHatch.setLoginSessionItem(
114 'eg.auth.token', evt.payload.authtoken);
115 egHatch.setLoginSessionItem(
116 'eg.auth.time', evt.payload.authtime);
119 // note: the likely outcome here is a NO_SESION
120 // server event, which results in broadcasting an
121 // egInvalidAuth by egNet.
122 console.error('login failed ' + js2JSON(evt));
130 return deferred.promise;
134 * Force-check the validity of the authtoken on occasion.
135 * This allows us to redirect an idle staff client back to the login
136 * page after the session times out. Otherwise, the UI would stay
137 * open with potentially sensitive data visible.
138 * TODO: What is the practical difference (for a browser) between
139 * checking auth validity and the ui.general.idle_timeout setting?
140 * Does that setting serve a purpose in a browser environment?
142 service.poll = function() {
143 if (!service.authtime()) return;
147 if (!service.authtime()) return;
150 'open-ils.auth.session.retrieve', service.token())
151 .then(function(user) {
152 if (user && user.classname) { // all good
155 $rootScope.$broadcast('egAuthExpired')
159 // add a 5 second delay to give the token plenty of time
160 // to expire on the server.
161 service.authtime() * 1000 + 5000
165 service.logout = function() {
166 if (service.token()) {
169 'open-ils.auth.session.delete',
170 service.token()); // fire and forget
171 egHatch.clearLoginSessionItems();
173 service._user = null;
181 * Service for testing user permissions.
182 * Note: this cannot live within egAuth, because it creates a circular
183 * dependency of egOrg -> egEnv -> egAuth -> egOrg
186 ['$q','egNet','egAuth','egOrg',
187 function($q , egNet , egAuth , egOrg) {
191 * Returns the full list of org unit objects at which the currently
192 * logged in user has the selected permissions.
193 * @permList - list or string. If a list, the response object is a
194 * hash of perm => orgList maps. If a string, the response is the
195 * org list for the requested perm.
197 service.hasPermAt = function(permList, asId) {
198 var deferred = $q.defer();
200 if (!angular.isArray(permList)) {
202 permList = [permList];
204 // as called, this method will return the top-most org unit of the
205 // sub-tree at which this user has the selected permission.
206 // From there, flesh the descendant orgs locally.
209 'open-ils.actor.user.has_work_perm_at.batch',
210 egAuth.token(), permList
211 ).then(function(resp) {
213 angular.forEach(permList, function(perm) {
215 angular.forEach(resp[perm], function(oneOrg) {
216 all = all.concat(egOrg.descendants(oneOrg, asId));
220 if (!isArray) answer = answer[permList[0]];
221 deferred.resolve(answer);
223 return deferred.promise;
228 * Returns a hash of perm => hasPermBool for each requested permission.
229 * If the authenticated user has no workstation, no checks are made
230 * and all permissions return false.
232 service.hasPermHere = function(permList) {
236 if (!angular.isArray(permList)) {
238 permList = [permList];
241 // no workstation, all are false
242 if (egAuth.user().wsid() === null) {
243 console.warn("egPerm.hasPermHere() called with no workstation");
245 response = permList.map(function(perm) {
246 return response[perm] = false;
251 return $q.when(response);
254 ws_ou = Number(egAuth.user().ws_ou()); // from string
256 return service.hasPermAt(permList, true)
257 .then(function(orgMap) {
258 angular.forEach(orgMap, function(orgIds, perm) {
259 // each permission is mapped to a flat list of org unit ids,
260 // including descendants. See if our workstation org unit
262 response[perm] = orgIds.indexOf(ws_ou) > -1;
264 if (!isArray) response = response[permList[0]];