import { Injectable } from '@angular/core'; import { Store, select } from '@ngrx/store'; import { filter, map, switchMap, take, catchError } from 'rxjs/operators'; import { Observable, of } from 'rxjs'; import { EventTypes, LoginResponse, OidcSecurityService, PublicEventsService, } from 'angular-auth-oidc-client'; import { NavigationStart, Router } from '@angular/router'; import { CustomParams } from '../models/custom-params.model'; import { CompanyViewModel } from '../models'; import * as oidcActions from '../@store/oidc.actions'; import { OIDCEffects } from '../@store/oidc.effects'; import * as userReducers from '../@store/user.reducer'; import * as userActions from '../@store/user.actions'; @Injectable({ providedIn: 'root' }) export class MwAuthService { private authChecked = false; oidcConfigLoaded$ = this.eventService.registerForEvents().pipe( filter((value) => value.type === EventTypes.ConfigLoaded), take(1) ); get userData$(): Observable { return this.oidcService.userData$.pipe(map(({ userData }) => userData)); } get loggedIn$(): Observable { return this.oidcService.isAuthenticated$.pipe( map((result) => result.isAuthenticated) ); } get activeCompany$(): Observable { return this.store.select(userReducers.companyDataIsReady).pipe( filter((isReady) => isReady), switchMap(() => this.store.pipe(select(userReducers.getActiveCompany))) ); } constructor( private readonly store: Store, private readonly oidcService: OidcSecurityService, private readonly eventService: PublicEventsService, private readonly router: Router ) { this.checkAuthOnRouteChange(); } logout(): void { this.store.dispatch(userActions.logOut()); } logoffLocal(): void { this.oidcService.logoffLocal(); } loginByGuid({ guid, language }: { guid: string; language: string }): void { this.store.dispatch( userActions.logInByGuid({ guid, language, }) ); } checkAuth(): Observable { return this.oidcService.checkAuth().pipe( catchError((err) => { console.error(err); this.oidcService.logoffLocal(); localStorage.clear(); this.router.navigate(['/']); const value: LoginResponse = { isAuthenticated: false, userData: null, accessToken: '', idToken: '', configId: '', }; return of(value); }) ); } authorize(redirectUrl?: string): void { if (redirectUrl) { OIDCEffects.saveStoredRedirectRoute(redirectUrl); } this.oidcService.authorize(undefined, { customParams: this.getCustomParams(), }); } changeCompany( selectedCompanyId?: number, opts?: { ignoreCompanySelector?: boolean; isSaveCurrentRoute?: boolean; } ): void { if (opts?.isSaveCurrentRoute) { this.saveCurrentRoute(); } const customParams = { selectedCompanyId: selectedCompanyId ?? 0, changeCompany: true, ignoreCompanySelector: false, }; if (opts?.ignoreCompanySelector) { customParams.ignoreCompanySelector = true; } this.oidcService.authorize(undefined, { customParams, }); } authorizeByGuid(guid: string): void { this.oidcService.authorize(undefined, { customParams: { autoLoginToken: guid, autoLoginCallback: true, }, }); } authorizeUsingPassword(data: { userName: string; password: string; companyId?: number; ignoreCompanySelector?: boolean; isSaveCurrentRoute?: boolean; }): void { const customParams: any = { login_hint: data.userName || '', password: data.password || '', }; const companyId = data.companyId || 0; if (data.isSaveCurrentRoute) { this.saveCurrentRoute(); } if (companyId > 0) { customParams.companyId = companyId; } if (data.ignoreCompanySelector) { customParams.ignoreCompanySelector = data.ignoreCompanySelector; } this.oidcService.authorize(undefined, { customParams, }); } private saveCurrentRoute(): void { const url = (this.router as any).location._platformLocation._doc.URL; OIDCEffects.saveStoredRedirectRoute(url.split('#')[1] || ''); } private checkAuthOnRouteChange(): void { this.router.events .pipe( map((e) => e as NavigationStart), filter((e) => !!e && !this.authChecked) ) .subscribe((e: NavigationStart) => { this.authChecked = true; this.store.dispatch(oidcActions.checkAuth()); }); } private getCustomParams(): CustomParams { const urlParams = new URLSearchParams(window.location.search); const params: CustomParams = {}; urlParams.forEach((value, key) => { params[key] = value; }); return params; } }