mgr/dashboard: Add ModuleStatusGuardService route guard
authorVolker Theile <vtheile@suse.com>
Mon, 14 May 2018 12:28:35 +0000 (14:28 +0200)
committerVolker Theile <vtheile@suse.com>
Mon, 14 May 2018 12:40:55 +0000 (14:40 +0200)
Signed-off-by: Volker Theile <vtheile@suse.com>
(cherry picked from commit f49e192dd56fb471961cebe71583c16b823e0bed)

src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/shared/services/services.module.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 (file)
index 0000000..e325d92
--- /dev/null
@@ -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/<apiPath>/status'. If the returned response
+ * states that the module is not available, then the user is redirected
+ * to the specified <redirectTo> 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);
+      });
+  }
+}
index 2a0156cca87ae7e0468ca60ab7a686041594ba96..6bdce286beb9b334dd9829235cb2c39c29ce3b47 100644 (file)
@@ -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