204 lines
5.8 KiB
TypeScript
204 lines
5.8 KiB
TypeScript
// src/app/services/login.service.ts
|
|
import { Injectable, NgZone } from "@angular/core";
|
|
import { HttpClient, HttpHeaders } from "@angular/common/http";
|
|
import {
|
|
BehaviorSubject,
|
|
Observable,
|
|
of,
|
|
Subject,
|
|
timer,
|
|
fromEvent,
|
|
merge,
|
|
} from "rxjs";
|
|
import { jwtDecode } from "jwt-decode";
|
|
import { Router } from "@angular/router";
|
|
import { switchMap, debounceTime, mapTo, startWith } from "rxjs/operators";
|
|
import { AuthService } from "src/app/_services/auth.service";
|
|
|
|
const BASE_URL = "https://kapi.absys.ninja/hemat";
|
|
interface CustomJwtPayload {
|
|
exp: number;
|
|
scope: string;
|
|
iat: number;
|
|
preferred_username: string;
|
|
name: string;
|
|
email: string;
|
|
family_name: string;
|
|
given_name: string;
|
|
sub: string;
|
|
}
|
|
|
|
@Injectable({
|
|
providedIn: "root",
|
|
})
|
|
export class LoginService {
|
|
private readonly tokenKey = "currentUser";
|
|
private tabSelected = new BehaviorSubject<string | null>(null);
|
|
public _tabSelected = this.tabSelected.asObservable();
|
|
|
|
private activitySubject = new Subject<boolean>();
|
|
public activity$: Observable<boolean> = this.activitySubject.asObservable();
|
|
|
|
currentUser: any;
|
|
|
|
constructor(
|
|
private http: HttpClient,
|
|
private router: Router,
|
|
private authService: AuthService,
|
|
private ngZone: NgZone
|
|
) {
|
|
this.startTrackingActivity();
|
|
this.startTokenCheck();
|
|
this.currentUser = JSON.parse(localStorage.getItem("currentUser"));
|
|
}
|
|
|
|
setTabsSelected(e: string) {
|
|
this.tabSelected.next(e);
|
|
}
|
|
|
|
updatePassword(data: any): Observable<any> {
|
|
const endpoint = `/users`;
|
|
const url = `${BASE_URL}${endpoint}/reset-password`;
|
|
const headers = new HttpHeaders({
|
|
"Content-Type": "application/json",
|
|
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
|
});
|
|
return this.http.put<any>(url, data, { headers });
|
|
}
|
|
|
|
getDataProfil(id: string): Observable<any> {
|
|
const endpoint = `/users`;
|
|
const url = `${BASE_URL}${endpoint}/byUserid/${id}`;
|
|
const headers = new HttpHeaders({
|
|
"Content-Type": "application/json",
|
|
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
|
});
|
|
return this.http.get<any>(url, { headers });
|
|
}
|
|
|
|
updateProfile(data: any, userId: string): Observable<any> {
|
|
const endpoint = `/users`;
|
|
const url = `${BASE_URL}${endpoint}/update/${userId}`;
|
|
const headers = new HttpHeaders({
|
|
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
|
});
|
|
|
|
return this.http.post<any>(`${url}`, data, { headers });
|
|
}
|
|
|
|
updateUserProfile(data: any): Observable<any> {
|
|
const body = { refresh_token: data };
|
|
const endpoint = `/users`;
|
|
const url = `${BASE_URL}${endpoint}/refresh-token`;
|
|
const headers = new HttpHeaders({
|
|
"x-api-key": "j2yaYvPSQcsEEmHh3NEobfiXyyXmmnHT",
|
|
});
|
|
|
|
return this.http.post<any>(`${url}`, body, { headers });
|
|
}
|
|
|
|
isTokenExpired(): Observable<boolean> {
|
|
const tokenData = localStorage.getItem(this.tokenKey);
|
|
if (tokenData) {
|
|
const tokenInfo = JSON.parse(tokenData);
|
|
const decodedToken = jwtDecode<CustomJwtPayload>(tokenInfo.refresh_token);
|
|
const expiryDate = decodedToken.exp * 1000;
|
|
const now = new Date().getTime();
|
|
const timeLeft = expiryDate - now;
|
|
return of(timeLeft <= 2 * 60 * 1000);
|
|
}
|
|
return of(true);
|
|
}
|
|
|
|
checkTokenAndRedirect(): void {
|
|
this.isTokenExpired().subscribe((isExpired) => {
|
|
if (isExpired) {
|
|
this.authService.doLogout().then(
|
|
() => {
|
|
this.router.navigate(["/login"]);
|
|
window.location.reload();
|
|
},
|
|
(err) => {
|
|
console.log(err);
|
|
}
|
|
);
|
|
this.router.navigate(["/login"]);
|
|
window.location.reload();
|
|
} else {
|
|
console.log("Token is valid, continuing...");
|
|
}
|
|
});
|
|
}
|
|
|
|
startTokenCheck(): void {
|
|
timer(0, 2 * 60 * 1000) // Check every 5 minutes
|
|
.pipe(switchMap(() => this.isTokenExpired()))
|
|
.subscribe((isExpired) => {
|
|
// console.log(isExpired);
|
|
|
|
if (isExpired) {
|
|
this.activity$.subscribe((isActive) => {
|
|
// console.log(isActive);
|
|
|
|
if (!isActive) {
|
|
this.checkTokenAndRedirect();
|
|
} else {
|
|
console.log(
|
|
"Token expired but user is active. Refresh token not implemented."
|
|
);
|
|
|
|
this.updateUserProfile(this.currentUser.refresh_token).subscribe(
|
|
(resp) => {
|
|
const decodedToken = jwtDecode<CustomJwtPayload>(
|
|
resp.access_token
|
|
);
|
|
localStorage.setItem(
|
|
"account_info",
|
|
JSON.stringify(decodedToken)
|
|
);
|
|
const userProfile = {
|
|
access_token: resp.access_token,
|
|
refresh_token: resp.refresh_token,
|
|
displayName: decodedToken.name,
|
|
buildingId: 4,
|
|
};
|
|
localStorage.setItem(
|
|
"currentUser",
|
|
JSON.stringify(userProfile)
|
|
);
|
|
window.location.reload();
|
|
}
|
|
);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
startTrackingActivity(): void {
|
|
this.ngZone.runOutsideAngular(() => {
|
|
const activityEvents$ = merge(
|
|
fromEvent(window, "mousemove"),
|
|
fromEvent(window, "click"),
|
|
fromEvent(window, "keypress"),
|
|
fromEvent(window, "scroll")
|
|
);
|
|
|
|
activityEvents$
|
|
.pipe(
|
|
startWith(null),
|
|
switchMap(() =>
|
|
merge(
|
|
timer(0).pipe(mapTo(true)),
|
|
timer(5 * 60 * 1000).pipe(mapTo(false)) // 5 minutes of inactivity
|
|
)
|
|
),
|
|
debounceTime(300)
|
|
)
|
|
.subscribe((active) => {
|
|
this.ngZone.run(() => this.activitySubject.next(active));
|
|
});
|
|
});
|
|
}
|
|
}
|