diff --git a/src/app/core/app.module.ts b/src/app/core/app.module.ts index 3d4050fb2..fd1b132a3 100644 --- a/src/app/core/app.module.ts +++ b/src/app/core/app.module.ts @@ -117,6 +117,8 @@ import { ElementLabelDisplayModule } from './utils/element-label-display.module' import { UserQueryListDialogComponent } from '@gsrs-core/bulk-search/user-query-list-dialog/user-query-list-dialog.component'; import { ListCreateDialogComponent } from '@gsrs-core/substances-browse/list-create-dialog/list-create-dialog.component'; import { PrivacyStatementModule } from './privacy-statement/privacy-statement.module'; +import { SessionCheckerComponent } from './auth/session-checker.component'; +import { Location, LocationStrategy, PathLocationStrategy } from '@angular/common'; @NgModule({ declarations: [ @@ -154,7 +156,8 @@ import { PrivacyStatementModule } from './privacy-statement/privacy-statement.mo RegisterComponent, PwdRecoveryComponent, UserQueryListDialogComponent, - ListCreateDialogComponent + ListCreateDialogComponent, + SessionCheckerComponent ], imports: [ BrowserModule.withServerTransition({ appId: 'gsrs' }), @@ -226,6 +229,9 @@ import { PrivacyStatementModule } from './privacy-statement/privacy-statement.mo ElementLabelDisplayModule, PrivacyStatementModule ], + + + providers: [ { provide: ErrorHandler, @@ -243,7 +249,7 @@ import { PrivacyStatementModule } from './privacy-statement/privacy-statement.mo { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }, {provide: WidgetRegistry, useClass: MyWidgetRegistry} ], - bootstrap: [AppComponent], + bootstrap: [AppComponent, Location], entryComponents: [ HighlightedSearchActionComponent, ExportDialogComponent, diff --git a/src/app/core/auth/session-checker.component.html b/src/app/core/auth/session-checker.component.html new file mode 100644 index 000000000..766c4642e --- /dev/null +++ b/src/app/core/auth/session-checker.component.html @@ -0,0 +1 @@ +
here I am in session checker 2
\ No newline at end of file diff --git a/src/app/core/auth/session-checker.component.scss b/src/app/core/auth/session-checker.component.scss new file mode 100644 index 000000000..14f207164 --- /dev/null +++ b/src/app/core/auth/session-checker.component.scss @@ -0,0 +1,5 @@ + + +div { + +} \ No newline at end of file diff --git a/src/app/core/auth/session-checker.component.ts b/src/app/core/auth/session-checker.component.ts new file mode 100644 index 000000000..b783ffc33 --- /dev/null +++ b/src/app/core/auth/session-checker.component.ts @@ -0,0 +1,107 @@ +import { Component, Input, OnDestroy, OnInit, Output } from "@angular/core"; +import { HttpClient } from '@angular/common/http'; +import { of, Subscription, timer } from "rxjs"; +import { catchError, filter, switchMap } from "rxjs/operators"; +import { ConfigService } from '../config/config.service'; +import { Router, ActivatedRoute, UrlSegment, NavigationEnd } from '@angular/router'; +import {Location} from '@angular/common'; + +/* + Example configuration: + "sessionChecker": { + "check": false, # does nothing if false + "redirectUrl": "", # first priority handler action taken if not blank or undefined + "redirectToLogin": false, # 2nd priority handler, action take if true + "alertMessage": "" # 3rd priority handler, action taken if not blank or undefined + }, +*/ + +@Component({ + selector: "app-session-checker", + templateUrl: "./session-checker.component.html", + styleUrls: ["./session-checker.component.scss"] +}) +export class SessionCheckerComponent implements OnInit, OnDestroy { + @Output() data: any; + apiUrl: string; + subscription: Subscription; + + constructor( + private http: HttpClient, + public configService: ConfigService, + private router: Router, + private activatedRoute: ActivatedRoute, + private location: Location + ) {} + + ngOnInit() { + const config = this.configService?.configData; + const check = config?.sessionChecker?.check; + const interval: number = config?.sessionChecker?.interval||30; + const milliseconds: number= interval * 60 * 1000; + this.apiUrl =`${(config?.apiBaseUrl) || '/'}api/v1/whoami`; + + if (config!==undefined && check && check===true) { + const path = this.location?.path(); + console.log("here path "+ path); + if (path!==undefined && !(path=='/login' || path.match('^\/login\?'))) { + + this.subscription = timer(0, milliseconds) + .pipe( + switchMap(() => { + return this.getData() + .pipe(catchError(err => { + this.handler(); + console.error(err); + return of(undefined); + })); + }), + filter(data => data !== undefined) + ) + .subscribe(data => { + this.data = data; + }); + } // login path + } // config && check + } + + ngOnDestroy() { + if(this.subscription!==undefined) { + this.subscription.unsubscribe(); + } + } + + handler() { + let actionTaken = false; + const redirectUrl = this.configService.configData?.sessionChecker?.redirectUrl||''; + + if(redirectUrl) { + actionTaken = true; + window.location.href = this.configService.configData.sessionChecker.redirectUrl; + } + if (!actionTaken) { + // tried to make this more general but got infinite loops in some cases. + const redirectToLogin = this.configService.configData?.sessionChecker?.redirectToLogin||''; + if (redirectToLogin) { + actionTaken = true; + this.router.navigate(['/login']); + } + } + + if(!actionTaken) { + const alertMessage = this.configService.configData?.sessionChecker?.alertMessage||''; + if (alertMessage) { + actionTaken = true; + alert(alertMessage) + } + } + if (!actionTaken) { + console.log("Session expired but session checker handler took no action. Check configration options."); + } + + } + + getData() { + return this.http.get(this.apiUrl); + } +} \ No newline at end of file diff --git a/src/app/core/base/base.component.html b/src/app/core/base/base.component.html index ece895904..21a42b0a2 100644 --- a/src/app/core/base/base.component.html +++ b/src/app/core/base/base.component.html @@ -213,4 +213,5 @@ - \ No newline at end of file +
+ diff --git a/src/app/core/base/base.component.ts b/src/app/core/base/base.component.ts index 4b249783e..868adc206 100644 --- a/src/app/core/base/base.component.ts +++ b/src/app/core/base/base.component.ts @@ -59,6 +59,7 @@ export class BaseComponent implements OnInit, OnDestroy { private wildCardText: string; private classicLinkQueryParams = {}; showHeaderBar = 'true'; + sessionChecker = false; constructor( private router: Router, @@ -145,6 +146,7 @@ export class BaseComponent implements OnInit, OnDestroy { this.classicLinkQueryParamsString = ''; this.contactEmail = this.configService.configData.contactEmail || null; this.navItems = this.configService.configData.navItems || null; + this.sessionChecker = this.configService.configData.sessionChecker?.check || null let notempty = false; if (this.loadedComponents) { diff --git a/src/app/core/config/config.model.ts b/src/app/core/config/config.model.ts index 9c9c290e2..99492ce2f 100644 --- a/src/app/core/config/config.model.ts +++ b/src/app/core/config/config.model.ts @@ -4,6 +4,7 @@ export interface Config { apiSSG4mBaseUrl?: string; apiUrlDomain?: string; logoutRedirectUrl?: string; + sessionChecker?: any; googleAnalyticsId?: string; version?: string; buildDateTime?: string; @@ -55,7 +56,16 @@ export interface Config { bulkSearch?: any useDataUrl?: any; } +export interface SessionChecker { + check?: boolean; + redirectUrl?: string; + redirectToLogin?: boolean; + alertMessage?: string; + interval?: number; + + +} export interface LoadedComponents { applications?: boolean; products?: boolean;