-
Notifications
You must be signed in to change notification settings - Fork 185
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
71d8b15
commit f071ba4
Showing
12 changed files
with
1,022 additions
and
1,955 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,19 @@ | ||
import { Injectable } from '@angular/core'; | ||
import { Router, CanActivate } from '@angular/router'; | ||
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; | ||
|
||
@Injectable() | ||
export class AuthGuard implements CanActivate { | ||
|
||
constructor(private router: Router) { } | ||
|
||
canActivate() { | ||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { | ||
if (localStorage.getItem('currentUser')) { | ||
// logged in so return true | ||
return true; | ||
} | ||
|
||
// not logged in so redirect to login page | ||
this.router.navigate(['/login']); | ||
this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }}); | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,61 @@ | ||
import { Http, BaseRequestOptions, Response, ResponseOptions, RequestMethod } from '@angular/http'; | ||
import { MockBackend, MockConnection } from '@angular/http/testing'; | ||
|
||
export function fakeBackendFactory(backend: MockBackend, options: BaseRequestOptions) { | ||
// configure fake backend | ||
backend.connections.subscribe((connection: MockConnection) => { | ||
let testUser = { username: 'test', password: 'test', firstName: 'Test', lastName: 'User' }; | ||
|
||
// wrap in timeout to simulate server api call | ||
setTimeout(() => { | ||
|
||
// fake authenticate api end point | ||
if (connection.request.url.endsWith('/api/authenticate') && connection.request.method === RequestMethod.Post) { | ||
// get parameters from post request | ||
let params = JSON.parse(connection.request.getBody()); | ||
|
||
// check user credentials and return fake jwt token if valid | ||
if (params.username === testUser.username && params.password === testUser.password) { | ||
connection.mockRespond(new Response( | ||
new ResponseOptions({ status: 200, body: { token: 'fake-jwt-token' } }) | ||
)); | ||
import { Injectable } from '@angular/core'; | ||
import { HttpRequest, HttpResponse, HttpHandler, HttpEvent, HttpInterceptor, HTTP_INTERCEPTORS } from '@angular/common/http'; | ||
import { Observable } from 'rxjs/Observable'; | ||
import 'rxjs/add/observable/of'; | ||
import 'rxjs/add/observable/throw'; | ||
import 'rxjs/add/operator/delay'; | ||
import 'rxjs/add/operator/mergeMap'; | ||
import 'rxjs/add/operator/materialize'; | ||
import 'rxjs/add/operator/dematerialize'; | ||
|
||
@Injectable() | ||
export class FakeBackendInterceptor implements HttpInterceptor { | ||
|
||
constructor() { } | ||
|
||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | ||
let testUser = { id: 1, username: 'test', password: 'test', firstName: 'Test', lastName: 'User' }; | ||
|
||
// wrap in delayed observable to simulate server api call | ||
return Observable.of(null).mergeMap(() => { | ||
|
||
// authenticate | ||
if (request.url.endsWith('/api/authenticate') && request.method === 'POST') { | ||
if (request.body.username === testUser.username && request.body.password === testUser.password) { | ||
// if login details are valid return 200 OK with a fake jwt token | ||
return Observable.of(new HttpResponse({ status: 200, body: { token: 'fake-jwt-token' } })); | ||
} else { | ||
connection.mockRespond(new Response( | ||
new ResponseOptions({ status: 200 }) | ||
)); | ||
// else return 400 bad request | ||
return Observable.throw('Username or password is incorrect'); | ||
} | ||
} | ||
|
||
// fake users api end point | ||
if (connection.request.url.endsWith('/api/users') && connection.request.method === RequestMethod.Get) { | ||
// check for fake auth token in header and return test users if valid, this security is implemented server side | ||
// in a real application | ||
if (connection.request.headers.get('Authorization') === 'Bearer fake-jwt-token') { | ||
connection.mockRespond(new Response( | ||
new ResponseOptions({ status: 200, body: [testUser] }) | ||
)); | ||
// get users | ||
if (request.url.endsWith('/api/users') && request.method === 'GET') { | ||
// check for fake auth token in header and return users if valid, this security is implemented server side in a real application | ||
if (request.headers.get('Authorization') === 'Bearer fake-jwt-token') { | ||
return Observable.of(new HttpResponse({ status: 200, body: [testUser] })); | ||
} else { | ||
// return 401 not authorised if token is null or invalid | ||
connection.mockRespond(new Response( | ||
new ResponseOptions({ status: 401 }) | ||
)); | ||
return Observable.throw('Unauthorised'); | ||
} | ||
} | ||
|
||
}, 500); | ||
// pass through any requests not handled above | ||
return next.handle(request); | ||
|
||
}) | ||
|
||
}); | ||
|
||
return new Http(backend, options); | ||
// call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648) | ||
.materialize() | ||
.delay(500) | ||
.dematerialize(); | ||
} | ||
} | ||
|
||
export let fakeBackendProvider = { | ||
// use fake backend in place of Http service for backend-less development | ||
provide: Http, | ||
useFactory: fakeBackendFactory, | ||
deps: [MockBackend, BaseRequestOptions] | ||
provide: HTTP_INTERCEPTORS, | ||
useClass: FakeBackendInterceptor, | ||
multi: true | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from './fake-backend'; | ||
export * from './jwt.interceptor'; | ||
export * from './fake-backend'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Injectable } from '@angular/core'; | ||
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; | ||
import { Observable } from 'rxjs/Observable'; | ||
|
||
@Injectable() | ||
export class JwtInterceptor implements HttpInterceptor { | ||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | ||
// add authorization header with jwt token if available | ||
let currentUser = JSON.parse(localStorage.getItem('currentUser')); | ||
if (currentUser && currentUser.token) { | ||
request = request.clone({ | ||
setHeaders: { | ||
Authorization: `Bearer ${currentUser.token}` | ||
} | ||
}); | ||
} | ||
|
||
return next.handle(request); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,27 @@ | ||
import { Injectable } from '@angular/core'; | ||
import { Http, Headers, Response } from '@angular/http'; | ||
import { Observable } from 'rxjs'; | ||
import { HttpClient, HttpHeaders } from '@angular/common/http'; | ||
import { Observable } from 'rxjs/Observable'; | ||
import 'rxjs/add/operator/map' | ||
|
||
@Injectable() | ||
export class AuthenticationService { | ||
public token: string; | ||
constructor(private http: HttpClient) { } | ||
|
||
constructor(private http: Http) { | ||
// set token if saved in local storage | ||
var currentUser = JSON.parse(localStorage.getItem('currentUser')); | ||
this.token = currentUser && currentUser.token; | ||
} | ||
|
||
login(username: string, password: string): Observable<boolean> { | ||
return this.http.post('/api/authenticate', JSON.stringify({ username: username, password: password })) | ||
.map((response: Response) => { | ||
login(username: string, password: string) { | ||
return this.http.post<any>('/api/authenticate', { username: username, password: password }) | ||
.map(user => { | ||
// login successful if there's a jwt token in the response | ||
let token = response.json() && response.json().token; | ||
if (token) { | ||
// set token property | ||
this.token = token; | ||
|
||
// store username and jwt token in local storage to keep user logged in between page refreshes | ||
localStorage.setItem('currentUser', JSON.stringify({ username: username, token: token })); | ||
|
||
// return true to indicate successful login | ||
return true; | ||
} else { | ||
// return false to indicate failed login | ||
return false; | ||
if (user && user.token) { | ||
// store user details and jwt token in local storage to keep user logged in between page refreshes | ||
localStorage.setItem('currentUser', JSON.stringify(user)); | ||
} | ||
|
||
return user; | ||
}); | ||
} | ||
|
||
logout(): void { | ||
// clear token remove user from local storage to log user out | ||
this.token = null; | ||
logout() { | ||
// remove user from local storage to log user out | ||
localStorage.removeItem('currentUser'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,13 @@ | ||
import { Injectable } from '@angular/core'; | ||
import { Http, Headers, RequestOptions, Response } from '@angular/http'; | ||
import { Observable } from 'rxjs'; | ||
import 'rxjs/add/operator/map' | ||
import { HttpClient } from '@angular/common/http'; | ||
|
||
import { AuthenticationService } from './index'; | ||
import { User } from '../_models/index'; | ||
|
||
@Injectable() | ||
export class UserService { | ||
constructor( | ||
private http: Http, | ||
private authenticationService: AuthenticationService) { | ||
} | ||
|
||
getUsers(): Observable<User[]> { | ||
// add authorization header with jwt token | ||
let headers = new Headers({ 'Authorization': 'Bearer ' + this.authenticationService.token }); | ||
let options = new RequestOptions({ headers: headers }); | ||
constructor(private http: HttpClient) { } | ||
|
||
// get users from api | ||
return this.http.get('/api/users', options) | ||
.map((response: Response) => response.json()); | ||
getAll() { | ||
return this.http.get<User[]>('/api/users'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.