import { Injectable, OnDestroy, Inject, LOCALE_ID } from '@angular/core'; import { HttpClient, HttpParams } from '@angular/common/http'; import { Observable, of, throwError, Subscription } from 'rxjs'; import { exhaustMap } from 'rxjs/operators'; import { Utils } from '../../shared/utils'; import { RoleIds } from '../../shared/global'; import { Store } from '@ngrx/store'; import * as fromStore from '../../reducers'; import { UserModel } from '../../auth/models/user.model'; import { Authenticate } from '../../auth/models/auth.model'; @Injectable({ providedIn: 'root' }) export class AuthService implements OnDestroy { private _user: any; get user(): any { return this._user; } private _tk: any; get token(): any { return this._tk; } set token(newT) { this._tk = newT; //TODO: Consider to store the tokens into Cookie later sessionStorage.setItem('cT', JSON.stringify(this._tk)); } private _locale: string; /** * The app supported locale language in two characters */ get locale(): string { return this._locale; } private sub$: Subscription; private user$ = this.store.select(fromStore.selectAuthUser); constructor( @Inject(LOCALE_ID) private localeId: string, private readonly store: Store<{}>, private readonly http: HttpClient, ) { this._locale = Utils.getLang(this.localeId) || 'en'; this._tk = JSON.parse(sessionStorage.getItem('cT')); this.sub$ = this.user$.subscribe((user) => this._user = user); } get loggedIn(): boolean { return (this.user && this.token); } get isAdmin(): boolean { return this.hasRole([RoleIds.ADMIN]); } get isApplicator() { return this.hasRole([RoleIds.APP]); } get isClientUser() { return this.hasRole([RoleIds.CLIENT]); } get isPilotUser() { return this.hasRole([RoleIds.PILOT]); } get isInspector(): boolean { return this.hasRole([RoleIds.INSPECTOR]); } getAuthHeader(): string { return this.user && this.token ? 'Bearer ' + this.token.t : ''; } getRToken() { return this.token && this.token.rt || ''; } hasRole(roles: string[]): boolean { return this.loggedIn && (roles && Utils.containsAny(roles, this.user.roles)); } get isPlanner() { return this.hasRole([RoleIds.APP, RoleIds.APP_ADM, RoleIds.OFFICER]); } get isBillable(): boolean { return (this.user && this.user.billable); } /** * Parent user, to mange items under an applicator user */ get byPUserId(): string { return (this.loggedIn && this.user.parent) ? this.user.parent : ''; } /** * Premium user level: 0, 1, 2,.. */ get premium(): number { return this.user && this.user.pre ? +this.user.pre : 0; } // Other auth functionality, sign-in, token handling etc login(auth: Authenticate): Observable { return this.http.post('/users/login', { username: auth.username, password: auth.password, lang: this.locale, dev: 'web' }).pipe( exhaustMap(res => { // Login successful if there's a jwt token in the response if (!res['token'] || !res['roles'] || !res['pui']) throwError('invalid_account'); // Store username and jwt token in local storage to keep user logged in between page refreshes const user = { _id: res['_id'], username: auth.username, billable: res['billable'], roles: res['roles'], parent: (res['pui'] || ''), lang: res['lang'] || 'en', pre: res['pre'] }; this.token = { t: res['token'], rt: res['rt'] }; return of(user); }) ); } logout(gotoLogin: boolean = true): Observable { sessionStorage.clear(); this._user = null; this._tk = null; return of(true); } siteVerify(ops) { return this.http.post('/siteVer', ops); } clearTempData() { return this.http.post('/users/clearTempData', { params: new HttpParams().set('loader', 'false') }); } mailPwdReset(ops) { return this.http.post('/users/mailPwdReset', ops); } resetPassword(ops) { return this.http.get(`/users/resetPassword/${ops.id}/${ops.token}`); } changePassword(ops) { return this.http.post('/users/resetPassword', ops); } ngOnDestroy(): void { if (this.sub$) this.sub$.unsubscribe(); } }