]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/staff/resolver.service.ts
LP2061136 - Stamping 1405 DB upgrade script
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / resolver.service.ts
1 import {Injectable} from '@angular/core';
2 import {Location} from '@angular/common';
3 import {Observable, Observer, of} from 'rxjs';
4 import {Router, Resolve, RouterStateSnapshot,
5         ActivatedRoute, ActivatedRouteSnapshot} from '@angular/router';
6 import {StoreService} from '@eg/core/store.service';
7 import {NetService} from '@eg/core/net.service';
8 import {AuthService, AuthWsState} from '@eg/core/auth.service';
9 import {PermService} from '@eg/core/perm.service';
10 import {OrgService} from '@eg/core/org.service';
11 import {FormatService} from '@eg/core/format.service';
12 import {HatchService} from '@eg/core/hatch.service';
13
14 const LOGIN_PATH = '/staff/login';
15 const WS_MANAGE_PATH = '/staff/admin/workstation/workstations/manage';
16
17 // Define these at the staff application level so they will be honored
18 // regardless of which interface is loaded / reloaded / etc.
19 const STAFF_LOGIN_SESSION_KEYS = [
20     'eg.circ.patron_hold_target',
21     'eg.catalog.recent_searches',
22     'eg.circ.recent_patrons'
23 ];
24
25 /**
26  * Load data used by all staff modules.
27  */
28 @Injectable()
29 export class StaffResolver implements Resolve<Observable<any>> {
30
31     // Tracks the primary resolve observable.
32     observer: Observer<any>;
33
34     constructor(
35         private router: Router,
36         private route: ActivatedRoute,
37         private ngLocation: Location,
38         private hatch: HatchService,
39         private store: StoreService,
40         private org: OrgService,
41         private net: NetService,
42         private auth: AuthService,
43         private perm: PermService,
44         private format: FormatService
45     ) {}
46
47     resolve(
48         route: ActivatedRouteSnapshot,
49         state: RouterStateSnapshot): Observable<any> {
50
51         this.hatch.connect();
52
53         STAFF_LOGIN_SESSION_KEYS.forEach(
54             key => this.store.addLoginSessionKey(key));
55
56         // Staff cookies stay in /$base/staff/
57         // NOTE: storing session data at '/' so it can be shared by
58         // Angularjs apps.
59         this.store.loginSessionBasePath = '/';
60         // ^-- = this.ngLocation.prepareExternalUrl('/staff');
61
62         // Not sure how to get the path without params... using this for now.
63         const path = state.url.split('?')[0];
64         if (path === '/staff/login') {
65             return of(true);
66         }
67
68         const observable: Observable<any>
69             = Observable.create(o => this.observer = o);
70
71         this.auth.testAuthToken().then(
72             tokenOk => {
73                 this.confirmStaffPerms().then(
74                     hasPerms => {
75                         this.auth.verifyWorkstation().then(
76                             wsOk => {
77                                 this.loadStartupData()
78                                 .then(ok => {
79                                     // Resolve observable must emit /something/
80                                     this.observer.next(true);
81                                     this.observer.complete();
82                                 });
83                             },
84                             wsNotOk => this.handleInvalidWorkstation(path)
85                         );
86                     },
87                     hasNotPerms => {
88                         this.observer.error(
89                             'User does not have staff permissions');
90                     }
91                 );
92             },
93             tokenNotOk => this.handleInvalidToken(state)
94         );
95
96         return observable;
97     }
98
99
100     // Confirm the user has the STAFF_LOGIN permission anywhere before
101     // allowing the staff sub-tree to load. This will prevent users
102     // with valid, non-staff authtokens from attempting to connect and
103     // subsequently getting redirected to the workstation admin page
104     // (since they won't have a valid WS either).
105     confirmStaffPerms(): Promise<any> {
106         return new Promise((resolve, reject) => {
107             this.perm.hasWorkPermAt(['STAFF_LOGIN']).then(
108                 permMap => {
109                     if (permMap.STAFF_LOGIN.length) {
110                         resolve('perm check OK');
111                     } else {
112                         reject('perm check faield');
113                     }
114                 }
115             );
116         });
117     }
118
119
120     // A page that's not the login page was requested without a
121     // valid auth token.  Send the caller back to the login page.
122     handleInvalidToken(state: RouterStateSnapshot): void {
123         console.debug('StaffResolver: authtoken is not valid');
124         const url = this.ngLocation.prepareExternalUrl(state.url);
125         this.router.navigate([LOGIN_PATH], {queryParams: {routeTo: url}});
126         this.observer.error('invalid or no auth token');
127     }
128
129     handleInvalidWorkstation(path: string): void {
130
131         if (path.startsWith(WS_MANAGE_PATH)) {
132             // user is navigating to the WS admin page.
133             this.observer.next(true);
134             // Resolve observable must emit /something/
135             this.observer.complete();
136         } else {
137             this.router.navigate([WS_MANAGE_PATH]);
138             this.observer.error(`Auth session linked to no
139                 workstation or a workstation unknown to this browser`);
140         }
141     }
142
143     /**
144      * Fetches data common to all staff interfaces.
145      */
146     loadStartupData(): Promise<any> {
147
148         // Fetch settings needed globally.  This will cache the values
149         // in the org service.
150         return this.org.settings([
151             'lib.timezone',
152             'webstaff.format.dates',
153             'webstaff.format.date_and_time',
154             'ui.staff.max_recent_patrons',
155             'circ.curbside', // navbar
156             'ui.staff.angular_circ.enabled',
157             'ui.staff.angular_catalog.enabled' // navbar
158         ]).then(settings => {
159             // Avoid clobbering defaults
160             if (settings['lib.timezone']) {
161                 this.format.wsOrgTimezone = settings['lib.timezone'];
162             }
163             if (settings['webstaff.format.dates']) {
164                 this.format.dateFormat = settings['webstaff.format.dates'];
165             }
166             if (settings['webstaff.format.date_and_time']) {
167                 this.format.dateTimeFormat =
168                     settings['webstaff.format.date_and_time'];
169             }
170             // TODO remove these once Angular Circ takes over.
171             if (settings['ui.staff.angular_circ.enabled']) {
172                 return this.perm.hasWorkPermHere(['ACCESS_ANGULAR_CIRC']);
173             }
174         });
175     }
176 }
177