import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { HttpClient } from '@angular/common/http'; import { TranslateService } from '@ngx-translate/core'; import { SessionStorageService } from 'ngx-webstorage'; import { Observable, ReplaySubject, of } from 'rxjs'; import { shareReplay, tap, catchError } from 'rxjs/operators'; import { StateStorageService } from 'app/core/auth/state-storage.service'; import { ApplicationConfigService } from '../config/application-config.service'; import { Account } from 'app/core/auth/account.model'; import { TrackerService } from '../tracker/tracker.service'; @Injectable({ providedIn: 'root' }) export class AccountService { private userIdentity: Account | null = null; private authenticationState = new ReplaySubject(1); private accountCache$?: Observable; constructor( private translateService: TranslateService, private sessionStorageService: SessionStorageService, private http: HttpClient, private trackerService: TrackerService, private stateStorageService: StateStorageService, private router: Router, private applicationConfigService: ApplicationConfigService ) {} save(account: Account): Observable<{}> { return this.http.post(this.applicationConfigService.getEndpointFor('api/account'), account); } authenticate(identity: Account | null): void { this.userIdentity = identity; this.authenticationState.next(this.userIdentity); if (identity) { this.trackerService.connect(); } else { this.trackerService.disconnect(); } } hasAnyAuthority(authorities: string[] | string): boolean { if (!this.userIdentity) { return false; } if (!Array.isArray(authorities)) { authorities = [authorities]; } return this.userIdentity.authorities.some((authority: string) => authorities.includes(authority)); } identity(force?: boolean): Observable { if (!this.accountCache$ || force || !this.isAuthenticated()) { this.accountCache$ = this.fetch().pipe( catchError(() => of(null)), tap((account: Account | null) => { this.authenticate(account); // After retrieve the account info, the language will be changed to // the user's preferred language configured in the account setting // unless user have choosed other language in the current session if (!this.sessionStorageService.retrieve('locale') && account) { this.translateService.use(account.langKey); } if (account) { this.navigateToStoredUrl(); } }), shareReplay() ); } return this.accountCache$; } isAuthenticated(): boolean { return this.userIdentity !== null; } getAuthenticationState(): Observable { return this.authenticationState.asObservable(); } private fetch(): Observable { return this.http.get(this.applicationConfigService.getEndpointFor('api/account')); } private navigateToStoredUrl(): void { // previousState can be set in the authExpiredInterceptor and in the userRouteAccessService // if login is successful, go to stored previousState and clear previousState const previousUrl = this.stateStorageService.getUrl(); if (previousUrl) { this.stateStorageService.clearUrl(); this.router.navigateByUrl(previousUrl); } } }