@@ -13,56 +13,59 @@ const users: User[] = [
1313@Injectable ( )
1414export class FakeBackendInterceptor implements HttpInterceptor {
1515 intercept ( request : HttpRequest < any > , next : HttpHandler ) : Observable < HttpEvent < any > > {
16- const authHeader = request . headers . get ( 'Authorization' ) ;
17- const isLoggedIn = authHeader && authHeader . startsWith ( 'Bearer fake-jwt-token' ) ;
18- const roleString = isLoggedIn && authHeader . split ( '.' ) [ 1 ] ;
19- const role = roleString ? Role [ roleString ] : null ;
16+ const { url, method, headers, body } = request ;
2017
2118 // wrap in delayed observable to simulate server api call
22- return of ( null ) . pipe ( mergeMap ( handleRoute ) )
23- . pipe ( materialize ( ) ) // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648)
24- . pipe ( delay ( 500 ) )
25- . pipe ( dematerialize ( ) ) ;
19+ return of ( null )
20+ . pipe ( mergeMap ( handleRoute ) )
21+ . pipe ( materialize ( ) ) // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648)
22+ . pipe ( delay ( 500 ) )
23+ . pipe ( dematerialize ( ) ) ;
2624
2725 function handleRoute ( ) {
28- // authenticate - public
29- if ( request . url . endsWith ( '/users/authenticate' ) && request . method === 'POST' ) {
30- const user = users . find ( x => x . username === request . body . username && x . password === request . body . password ) ;
31- if ( ! user ) return error ( 'Username or password is incorrect' ) ;
32- return ok ( {
33- id : user . id ,
34- username : user . username ,
35- firstName : user . firstName ,
36- lastName : user . lastName ,
37- role : user . role ,
38- token : `fake-jwt-token.${ user . role } `
39- } ) ;
26+ switch ( true ) {
27+ case url . endsWith ( '/users/authenticate' ) && method === 'POST' :
28+ return authenticate ( ) ;
29+ case url . endsWith ( '/users' ) && method === 'GET' :
30+ return getUsers ( ) ;
31+ case url . match ( / \/ u s e r s \/ \d + $ / ) && method === 'GET' :
32+ return getUserById ( ) ;
33+ default :
34+ // pass through any requests not handled above
35+ return next . handle ( request ) ;
4036 }
4137
42- // get user by id - admin or user (user can only access their own record)
43- if ( request . url . match ( / \/ u s e r s \/ \d + $ / ) && request . method === 'GET' ) {
44- if ( ! isLoggedIn ) return unauthorised ( ) ;
38+ }
4539
46- // get id from request url
47- let urlParts = request . url . split ( '/' ) ;
48- let id = parseInt ( urlParts [ urlParts . length - 1 ] ) ;
40+ // route functions
41+
42+ function authenticate ( ) {
43+ const { username, password } = body ;
44+ const user = users . find ( x => x . username === username && x . password === password ) ;
45+ if ( ! user ) return error ( 'Username or password is incorrect' ) ;
46+ return ok ( {
47+ id : user . id ,
48+ username : user . username ,
49+ firstName : user . firstName ,
50+ lastName : user . lastName ,
51+ role : user . role ,
52+ token : `fake-jwt-token.${ user . id } `
53+ } ) ;
54+ }
4955
50- // only allow normal users access to their own record
51- const currentUser = users . find ( x => x . role === role ) ;
52- if ( id !== currentUser . id && role !== Role . Admin ) return unauthorised ( ) ;
56+ function getUsers ( ) {
57+ if ( ! isAdmin ( ) ) return unauthorized ( ) ;
58+ return ok ( users ) ;
59+ }
5360
54- const user = users . find ( x => x . id === id ) ;
55- return ok ( user ) ;
56- }
61+ function getUserById ( ) {
62+ if ( ! isLoggedIn ( ) ) return unauthorized ( ) ;
5763
58- // get all users (admin only)
59- if ( request . url . endsWith ( '/users' ) && request . method === 'GET' ) {
60- if ( role !== Role . Admin ) return unauthorised ( ) ;
61- return ok ( users ) ;
62- }
64+ // only admins can access other user records
65+ if ( ! isAdmin ( ) && currentUser ( ) . id !== idFromUrl ( ) ) return unauthorized ( ) ;
6366
64- // pass through any requests not handled above
65- return next . handle ( request ) ;
67+ const user = users . find ( x => x . id === idFromUrl ( ) ) ;
68+ return ok ( user ) ;
6669 }
6770
6871 // helper functions
@@ -71,17 +74,37 @@ export class FakeBackendInterceptor implements HttpInterceptor {
7174 return of ( new HttpResponse ( { status : 200 , body } ) ) ;
7275 }
7376
74- function unauthorised ( ) {
75- return throwError ( { status : 401 , error : { message : 'Unauthorised ' } } ) ;
77+ function unauthorized ( ) {
78+ return throwError ( { status : 401 , error : { message : 'unauthorized ' } } ) ;
7679 }
7780
7881 function error ( message ) {
7982 return throwError ( { status : 400 , error : { message } } ) ;
8083 }
84+
85+ function isLoggedIn ( ) {
86+ const authHeader = headers . get ( 'Authorization' ) || '' ;
87+ return authHeader . startsWith ( 'Bearer fake-jwt-token' ) ;
88+ }
89+
90+ function isAdmin ( ) {
91+ return isLoggedIn ( ) && currentUser ( ) . role === Role . Admin ;
92+ }
93+
94+ function currentUser ( ) {
95+ if ( ! isLoggedIn ( ) ) return ;
96+ const id = parseInt ( headers . get ( 'Authorization' ) . split ( '.' ) [ 1 ] ) ;
97+ return users . find ( x => x . id === id ) ;
98+ }
99+
100+ function idFromUrl ( ) {
101+ const urlParts = url . split ( '/' ) ;
102+ return parseInt ( urlParts [ urlParts . length - 1 ] ) ;
103+ }
81104 }
82105}
83106
84- export let fakeBackendProvider = {
107+ export const fakeBackendProvider = {
85108 // use fake backend in place of Http service for backend-less development
86109 provide : HTTP_INTERCEPTORS ,
87110 useClass : FakeBackendInterceptor ,
0 commit comments