]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/js/ui/default/staff/services/auth.js
LP#1350042 Browser client templates/scripts (phase 1)
[Evergreen.git] / Open-ILS / web / js / ui / default / staff / services / auth.js
1 /* Core Sevice - egAuth
2  *
3  * Manages login and auth session retrieval.
4  */
5
6 angular.module('egCoreMod')
7
8 .factory('egAuth', 
9        ['$q','$timeout','$rootScope','egNet','egHatch', 
10 function($q , $timeout , $rootScope , egNet , egHatch) {
11
12     var service = {
13         // the currently active user (au) object
14         user : function() {
15             return this._user;
16         },
17
18         // the currently active auth token string
19         token : function() {
20             return egHatch.getLocalItem('eg.auth.token');
21         },
22
23         // authtime in seconds
24         authtime : function() {
25             return egHatch.getLocalItem('eg.auth.time');
26         },
27
28         // the currently active workstation name
29         // For ws_ou or wsid(), see egAuth.user().ws_ou(), etc.
30         workstation : function() {
31             return this.ws;
32         }
33     };
34
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();
40
41         if (token) {
42
43             egNet.request(
44                 'open-ils.auth',
45                 'open-ils.auth.session.retrieve', token)
46
47             .then(function(user) {
48                 if (user && user.classname) {
49                     // authtoken test succeeded
50                     service._user = user;
51                     service.poll();
52                    
53                     if (user.wsid()) {
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')
58                         .then(function(all) { 
59                             if (all) {
60                                 var ws = all.filter(
61                                     function(w) {return w.id == user.wsid()})[0];
62                                 if (ws) service.ws = ws.name;
63                             }
64                             deferred.resolve(); // found WS
65                         });
66                     } else {
67                         deferred.resolve(); // no WS
68                     }
69                 } else {
70                     // authtoken test failed
71                     egHatch.removeLocalItem('eg.auth.token');
72                     deferred.reject(); 
73                 }
74             });
75
76         } else {
77             // no authtoken to test
78             deferred.reject();
79         }
80
81         return deferred.promise;
82     };
83
84     /**
85      * Returns a promise, which is resolved on successful 
86      * login and rejected on failed login.
87      */
88     service.login = function(args) {
89         var deferred = $q.defer();
90         egNet.request(
91             'open-ils.auth',
92             'open-ils.auth.authenticate.init', args.username).then(
93             function(seed) {
94                 args.password = hex_md5(seed + hex_md5(args.password))
95                 egNet.request(
96                     'open-ils.auth',
97                     'open-ils.auth.authenticate.complete', args).then(
98                     function(evt) {
99                         if (evt.textcode == 'SUCCESS') {
100                             service.ws = args.workstation; 
101                             service.poll();
102                             egHatch.setLocalItem(
103                                 'eg.auth.token', evt.payload.authtoken);
104                             egHatch.setLocalItem(
105                                 'eg.auth.time', evt.payload.authtime);
106                             deferred.resolve();
107                         } else {
108                             // note: the likely outcome here is a NO_SESION
109                             // server event, which results in broadcasting an 
110                             // egInvalidAuth by egNet. 
111                             console.error('login failed ' + js2JSON(evt));
112                             deferred.reject();
113                         }
114                     }
115                 )
116             }
117         );
118
119         return deferred.promise;
120     };
121
122     /**
123      * Force-check the validity of the authtoken on occasion. 
124      * This allows us to redirect an idle staff client back to the login
125      * page after the session times out.  Otherwise, the UI would stay
126      * open with potentially sensitive data visible.
127      * TODO: What is the practical difference (for a browser) between 
128      * checking auth validity and the ui.general.idle_timeout setting?
129      * Does that setting serve a purpose in a browser environment?
130      */
131     service.poll = function() {
132         if (!service.authtime()) return;
133
134         $timeout(
135             function() {
136                 if (!service.authtime()) return;
137                 egNet.request(                                                     
138                     'open-ils.auth',                                               
139                     'open-ils.auth.session.retrieve', service.token())   
140                 .then(function(user) {
141                     if (user && user.classname) { // all good
142                         service.poll();
143                     } else {
144                         $rootScope.$broadcast('egAuthExpired') 
145                     }
146                 })
147             },
148             // add a 5 second delay to give the token plenty of time
149             // to expire on the server.
150             service.authtime() * 1000 + 5000
151         );
152     }
153
154     service.logout = function() {
155         if (service.token()) {
156             egNet.request(
157                 'open-ils.auth', 
158                 'open-ils.auth.session.delete', 
159                 service.token()); // fire and forget
160             egHatch.removeLocalItem('eg.auth.token');
161             egHatch.removeLocalItem('eg.auth.time');
162         }
163         service._user = null;
164     };
165
166     return service;
167 }])
168
169
170 /**
171  * Service for testing user permissions.
172  * Note: this cannot live within egAuth, because it creates a circular
173  * dependency of egOrg -> egEnv -> egAuth -> egOrg
174  */
175 .factory('egPerm', 
176        ['$q','egNet','egAuth','egOrg',
177 function($q , egNet , egAuth , egOrg) {
178     var service = {};
179
180     /*
181      * Returns the full list of org unit objects at which the currently
182      * logged in user has the selected permissions.
183      * @permList - list or string.  If a list, the response object is a
184      * hash of perm => orgList maps.  If a string, the response is the
185      * org list for the requested perm.
186      */
187     service.hasPermAt = function(permList, asId) {
188         var deferred = $q.defer();
189         var isArray = true;
190         if (!angular.isArray(permList)) {
191             isArray = false;
192             permList = [permList];
193         }
194         // as called, this method will return the top-most org unit of the
195         // sub-tree at which this user has the selected permission.
196         // From there, flesh the descendant orgs locally.
197         egNet.request(
198             'open-ils.actor',
199             'open-ils.actor.user.has_work_perm_at.batch',
200             egAuth.token(), permList
201         ).then(function(resp) {
202             var answer = {};
203             angular.forEach(permList, function(perm) {
204                 var all = [];
205                 angular.forEach(resp[perm], function(oneOrg) {
206                     all = all.concat(egOrg.descendants(oneOrg, asId));
207                 });
208                 answer[perm] = all;
209             });
210             if (!isArray) answer = answer[permList[0]];
211             deferred.resolve(answer);
212         });
213        return deferred.promise;
214     };
215
216
217     /**
218      * Returns a hash of perm => hasPermBool for each requested permission.
219      * If the authenticated user has no workstation, no checks are made
220      * and all permissions return false.
221      */
222     service.hasPermHere = function(permList) {
223         var response = {};
224
225         var isArray = true;
226         if (!angular.isArray(permList)) {
227             isArray = false;
228             permList = [permList];
229         }
230
231         // no workstation, all are false
232         if (egAuth.user().wsid() === null) {
233             console.warn("egPerm.hasPermHere() called with no workstation");
234             if (isArray) {
235                 response = permList.map(function(perm) {
236                     return response[perm] = false;
237                 });
238             } else {
239                 response = false;
240             }
241             return $q.when(response);
242         }
243
244         ws_ou = Number(egAuth.user().ws_ou()); // from string
245
246         return service.hasPermAt(permList, true)
247         .then(function(orgMap) {
248             angular.forEach(orgMap, function(orgIds, perm) {
249                 // each permission is mapped to a flat list of org unit ids,
250                 // including descendants.  See if our workstation org unit
251                 // is in the list.
252                 response[perm] = orgIds.indexOf(ws_ou) > -1;
253             });
254             if (!isArray) response = response[permList[0]];
255             return response;
256         });
257     }
258
259     return service;
260 }])
261
262