1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
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 { UserInfo } from '../user-info';
export interface UserCredentials {
username: string;
password: string;
}
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;
private userInfo: UserInfo;
constructor(private httpClient: HttpClient) { }
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(username: string, password: string): Observable<UserInfo> {
if (this.token) {
return throwError(new AlreadyLoginException());
}
return this.httpClient.post<CreateTokenResult>('/api/User/CreateToken', <UserCredentials>{
username, password
}).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;
})
);
}
}
|