diff options
Diffstat (limited to 'Timeline/ClientApp/src/app/user/user-service')
-rw-r--r-- | Timeline/ClientApp/src/app/user/user-service/user.service.spec.ts | 119 | ||||
-rw-r--r-- | Timeline/ClientApp/src/app/user/user-service/user.service.ts | 118 |
2 files changed, 0 insertions, 237 deletions
diff --git a/Timeline/ClientApp/src/app/user/user-service/user.service.spec.ts b/Timeline/ClientApp/src/app/user/user-service/user.service.spec.ts deleted file mode 100644 index 9effe000..00000000 --- a/Timeline/ClientApp/src/app/user/user-service/user.service.spec.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { TestBed } from '@angular/core/testing'; -import { HttpRequest } from '@angular/common/http'; -import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; - -import { UserInfo, UserCredentials } from '../entities'; -import { - UserService, CreateTokenResult, - UserLoginState, TokenValidationRequest, TokenValidationResult -} from './user.service'; - -describe('UserService', () => { - const tokenCreateUrl = '/api/User/CreateToken'; - - const mockUserCredentials: UserCredentials = { - username: 'user', - password: 'user' - }; - - beforeEach(() => TestBed.configureTestingModule({ - imports: [HttpClientTestingModule] - })); - - it('should be created', () => { - const service: UserService = TestBed.get(UserService); - expect(service).toBeTruthy(); - }); - - it('should be nologin at first', () => { - const service: UserService = TestBed.get(UserService); - service.validateUserLoginState().subscribe(result => { - expect(result.state).toBe('nologin'); - }); - }); - - it('login should work well', () => { - const service: UserService = TestBed.get(UserService); - - const mockUserInfo: UserInfo = { - username: 'user', - roles: ['user', 'other'] - }; - - service.tryLogin(mockUserCredentials).subscribe(result => { - expect(result).toEqual(mockUserInfo); - }); - - const httpController = TestBed.get(HttpTestingController) as HttpTestingController; - - httpController.expectOne((request: HttpRequest<UserCredentials>) => - request.url === tokenCreateUrl && - request.body.username === 'user' && - request.body.password === 'user').flush(<CreateTokenResult>{ - token: 'test-token', - userInfo: mockUserInfo - }); - - httpController.verify(); - }); - - describe('validateUserLoginState', () => { - let service: UserService; - let httpController: HttpTestingController; - - const mockUserInfo: UserInfo = { - username: 'user', - roles: ['user', 'other'] - }; - - const mockToken = 'mock-token'; - - const tokenValidateRequestMatcher = (req: HttpRequest<TokenValidationRequest>) => { - return req.url === '/api/User/ValidateToken' && req.body.token === mockToken; - }; - - beforeEach(() => { - service = TestBed.get(UserService); - httpController = TestBed.get(HttpTestingController); - - service.tryLogin(mockUserCredentials).subscribe(); // subscribe to activate login - - httpController.expectOne(tokenCreateUrl).flush(<CreateTokenResult>{ - token: mockToken, - userInfo: mockUserInfo - }); - }); - - it('success should work well', () => { - service.validateUserLoginState().subscribe((result: UserLoginState) => { - expect(result).toEqual(<UserLoginState>{ - state: 'success', - userInfo: mockUserInfo - }); - }); - - httpController.expectOne(tokenValidateRequestMatcher).flush(<TokenValidationResult>{ - isValid: true, - userInfo: mockUserInfo - }); - - httpController.verify(); - }); - - it('invalid should work well', () => { - service.validateUserLoginState().subscribe((result: UserLoginState) => { - expect(result).toEqual(<UserLoginState>{ - state: 'invalidlogin' - }); - }); - - httpController.expectOne(tokenValidateRequestMatcher).flush(<TokenValidationResult>{ - isValid: false - }); - - httpController.verify(); - }); - }); - - // TODO: test on error situations. -}); diff --git a/Timeline/ClientApp/src/app/user/user-service/user.service.ts b/Timeline/ClientApp/src/app/user/user-service/user.service.ts deleted file mode 100644 index e535537d..00000000 --- a/Timeline/ClientApp/src/app/user/user-service/user.service.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HttpClient, HttpErrorResponse } from '@angular/common/http'; -import { Observable, of, throwError } from 'rxjs'; -import { map, catchError, retry } from 'rxjs/operators'; - -import { UserCredentials, UserInfo } from '../entities'; -import { Router } from '@angular/router'; - -export interface CreateTokenResult { - token: string; - userInfo: UserInfo; -} - -export interface TokenValidationRequest { - token: string; -} - -export interface TokenValidationResult { - isValid: boolean; - userInfo?: UserInfo; -} - -export interface UserLoginState { - state: 'nologin' | 'invalidlogin' | 'success'; - userInfo?: UserInfo; -} - -export class BadNetworkException extends Error { - constructor() { - super('Network is bad.'); - } -} - -export class AlreadyLoginException extends Error { - constructor() { - super('There is already a token saved. Please call validateUserLoginState first.'); - } -} - -export class BadCredentialsException extends Error { - constructor() { - super(`Username or password is wrong.`); - } -} - -@Injectable({ - providedIn: 'root' -}) -export class UserService { - - private token: string; - userInfo: UserInfo; - - constructor(private httpClient: HttpClient, private router: Router) { } - - userRouteNavigate(commands: any[]) { - this.router.navigate([{ - outlets: { - user: commands - } - }]); - } - - validateUserLoginState(): Observable<UserLoginState> { - if (this.token === undefined || this.token === null) { - return of(<UserLoginState>{ state: 'nologin' }); - } - - return this.httpClient.post<TokenValidationResult>('/api/User/ValidateToken', <TokenValidationRequest>{ token: this.token }).pipe( - retry(3), - catchError(error => { - console.error('Failed to validate token.'); - return throwError(error); - }), - map(result => { - if (result.isValid) { - this.userInfo = result.userInfo; - return <UserLoginState>{ - state: 'success', - userInfo: result.userInfo - }; - } else { - this.token = null; - this.userInfo = null; - return <UserLoginState>{ - state: 'invalidlogin' - }; - } - }) - ); - } - - tryLogin(credentials: UserCredentials): Observable<UserInfo> { - if (this.token) { - return throwError(new AlreadyLoginException()); - } - - return this.httpClient.post<CreateTokenResult>('/api/User/CreateToken', credentials).pipe( - catchError((error: HttpErrorResponse) => { - if (error.error instanceof ErrorEvent) { - console.error('An error occurred when login: ' + error.error.message); - return throwError(new BadNetworkException()); - } else if (error.status === 400) { - console.error('An error occurred when login: wrong credentials.'); - return throwError(new BadCredentialsException()); - } else { - console.error('An unknown error occurred when login: ' + error); - return throwError(error); - } - }), - map(result => { - this.token = result.token; - this.userInfo = result.userInfo; - return result.userInfo; - }) - ); - } -} |