source: Farmatiko/ClientApp/src/app/shared/services/auth.service.ts

Last change on this file was 1db5673, checked in by DimitarSlezenkovski <dslezenkovski@…>, 2 years ago

Fix bugs, add some more

  • Property mode set to 100644
File size: 4.4 KB
Line 
1import { Injectable, OnDestroy } from '@angular/core';
2import { Router } from '@angular/router';
3import { HttpClient } from '@angular/common/http';
4import { BehaviorSubject, Observable, of, Subscription } from 'rxjs';
5import { map, tap, delay, finalize } from 'rxjs/operators';
6import { IPharmacyHead } from '../interfaces';
7import { environment } from '../../../environments/environment';
8
9
10interface LoginResult {
11 userName: string;
12 role: string;
13 originalUserName?: string;
14 accessToken: string;
15 refreshToken: string;
16 head?: IPharmacyHead;
17}
18
19@Injectable({
20 providedIn: 'root',
21})
22export class AuthService implements OnDestroy {
23 private readonly apiUrl = `${environment.baseApiUrl}api/pharmacyhead`;
24 private timer: Subscription;
25 private _user = new BehaviorSubject<IPharmacyHead>(null);
26 user$: Observable<IPharmacyHead> = this._user.asObservable();
27
28 private storageEventListener(event: StorageEvent) {
29 if (event.storageArea === localStorage) {
30 if (event.key === 'logout-event') {
31 this.stopTokenTimer();
32 this._user.next(null);
33 }
34 if (event.key === 'login-event') {
35 this.stopTokenTimer();
36 this.http.get<LoginResult>(`${this.apiUrl}/user`).subscribe((x) => {
37 this._user.next({
38 Email: x.userName,
39 Passwd: x.head.Passwd,
40 Role: x.role,
41 originalUserName: x.originalUserName,
42 Name: x.head.Name,
43 PharmacyMedicines: x.head.PharmacyMedicines,
44 Pharmacy: x.head.Pharmacy
45 });
46 });
47 }
48 }
49 }
50
51 constructor(private router: Router, private http: HttpClient) {
52 window.addEventListener('storage', this.storageEventListener.bind(this));
53 console.log(this.apiUrl);
54 }
55
56 ngOnDestroy(): void {
57 window.removeEventListener('storage', this.storageEventListener.bind(this));
58 }
59
60 login(username: string, password: string) {
61 return this.http
62 .post<LoginResult>(`${this.apiUrl}/login`, { username, password })
63 .pipe(
64 map((x) => {
65 this._user.next({
66 Email: x.userName,
67 Passwd: x.head.Passwd,
68 Role: x.role,
69 originalUserName: x.originalUserName,
70 Name: x.head.Name,
71 PharmacyMedicines: x.head.PharmacyMedicines,
72 Pharmacy: x.head.Pharmacy
73 });
74 this.setLocalStorage(x);
75 this.startTokenTimer();
76 return x;
77 })
78 );
79 }
80
81 logout() {
82 this.http
83 .post<unknown>(`${this.apiUrl}/logout`, {})
84 .pipe(
85 finalize(() => {
86 this.clearLocalStorage();
87 this._user.next(null);
88 this.stopTokenTimer();
89 this.router.navigate(['login']);
90 })
91 )
92 .subscribe();
93 }
94
95 refreshToken() {
96 const refreshToken = localStorage.getItem('refresh_token');
97 if (!refreshToken) {
98 this.clearLocalStorage();
99 return of(null);
100 }
101
102 return this.http
103 .post<LoginResult>(`${this.apiUrl}/refresh-token`, { refreshToken })
104 .pipe(
105 map((x) => {
106 this._user.next({
107 Email: x.userName,
108 Passwd: x.head.Passwd,
109 Role: x.role,
110 originalUserName: x.originalUserName,
111 Name: x.head.Name,
112 PharmacyMedicines: x.head.PharmacyMedicines,
113 Pharmacy: x.head.Pharmacy
114 });
115 this.setLocalStorage(x);
116 this.startTokenTimer();
117 return x;
118 })
119 );
120 }
121
122 setLocalStorage(x: LoginResult) {
123 localStorage.setItem('access_token', x.accessToken);
124 localStorage.setItem('refresh_token', x.refreshToken);
125 localStorage.setItem('login-event', 'login' + Math.random());
126 }
127
128 clearLocalStorage() {
129 localStorage.removeItem('access_token');
130 localStorage.removeItem('refresh_token');
131 localStorage.setItem('logout-event', 'logout' + Math.random());
132 }
133
134 getUser() {
135 return this.user$;
136 }
137
138 private getTokenRemainingTime() {
139 const accessToken = localStorage.getItem('access_token');
140 if (!accessToken) {
141 return 0;
142 }
143 const jwtToken = JSON.parse(atob(accessToken.split('.')[1]));
144 const expires = new Date(jwtToken.exp * 1000);
145 return expires.getTime() - Date.now();
146 }
147
148 private startTokenTimer() {
149 const timeout = this.getTokenRemainingTime();
150 this.timer = of(true)
151 .pipe(
152 delay(timeout),
153 tap(() => this.refreshToken().subscribe())
154 )
155 .subscribe();
156 }
157
158 private stopTokenTimer() {
159 this.timer?.unsubscribe();
160 }
161}
Note: See TracBrowser for help on using the repository browser.