From f49e192dd56fb471961cebe71583c16b823e0bed Mon Sep 17 00:00:00 2001 From: Volker Theile Date: Mon, 7 May 2018 16:49:55 +0200 Subject: [PATCH] mgr/dashboard: Add ModuleStatusGuardService route guard Signed-off-by: Volker Theile --- .../services/module-status-guard.service.ts | 67 +++++++++++++++++++ .../app/shared/services/services.module.ts | 2 + 2 files changed, 69 insertions(+) create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.ts diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.ts new file mode 100644 index 0000000000000..e325d92702a25 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.ts @@ -0,0 +1,67 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { + ActivatedRouteSnapshot, + CanActivate, + CanActivateChild, + Router, + RouterStateSnapshot +} from '@angular/router'; + +import 'rxjs/add/observable/of'; +import { Observable } from 'rxjs/Observable'; + +/** + * This service checks if a route can be activated by executing a + * REST API call to '/api//status'. If the returned response + * states that the module is not available, then the user is redirected + * to the specified URL path. + * + * A controller implementing this endpoint should return an object of + * the following form: + * {'available': true|false, 'message': null|string}. + * + * The configuration of this guard should look like this: + * const routes: Routes = [ + * { + * path: 'rgw/bucket', + * component: RgwBucketListComponent, + * canActivate: [AuthGuardService, ModuleStatusGuardService], + * data: { + * moduleStatusGuardConfig: { + * apiPath: 'rgw', + * redirectTo: 'rgw/501' + * } + * } + * }, + * ... + */ +@Injectable() +export class ModuleStatusGuardService implements CanActivate, CanActivateChild { + + constructor(private http: HttpClient, + private router: Router) {} + + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + return this.doCheck(route); + } + + canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + return this.doCheck(childRoute); + } + + private doCheck(route: ActivatedRouteSnapshot) { + const config = route.data['moduleStatusGuardConfig']; + return this.http.get(`/api/${config.apiPath}/status`) + .map((resp: any) => { + if (!resp.available) { + this.router.navigate([config.redirectTo, resp.message || '']); + } + return resp.available; + }) + .catch(() => { + this.router.navigate([config.redirectTo]); + return Observable.of(false); + }); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/services.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/services.module.ts index 2a0156cca87ae..6bdce286beb9b 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/services.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/services.module.ts @@ -4,6 +4,7 @@ import { NgModule } from '@angular/core'; import { AuthGuardService } from './auth-guard.service'; import { AuthStorageService } from './auth-storage.service'; import { FormatterService } from './formatter.service'; +import { ModuleStatusGuardService } from './module-status-guard.service'; import { NotificationService } from './notification.service'; import { SummaryService } from './summary.service'; import { TaskManagerMessageService } from './task-manager-message.service'; @@ -17,6 +18,7 @@ import { TaskManagerService } from './task-manager.service'; AuthStorageService, FormatterService, SummaryService, + ModuleStatusGuardService, NotificationService, TaskManagerService, TaskManagerMessageService -- 2.39.5