]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.ts
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / shared / services / api-interceptor.service.ts
1 import {
2 HttpErrorResponse,
3 HttpEvent,
4 HttpHandler,
5 HttpInterceptor,
6 HttpRequest
7 } from '@angular/common/http';
8 import { Injectable } from '@angular/core';
9 import { Router } from '@angular/router';
10
11 import * as _ from 'lodash';
12 import { Observable, throwError as observableThrowError } from 'rxjs';
13 import { catchError } from 'rxjs/operators';
14
15 import { NotificationType } from '../enum/notification-type.enum';
16 import { CdNotificationConfig } from '../models/cd-notification';
17 import { FinishedTask } from '../models/finished-task';
18 import { AuthStorageService } from './auth-storage.service';
19 import { NotificationService } from './notification.service';
20 import { ServicesModule } from './services.module';
21
22 @Injectable({
23 providedIn: ServicesModule
24 })
25 export class ApiInterceptorService implements HttpInterceptor {
26 constructor(
27 private router: Router,
28 private authStorageService: AuthStorageService,
29 public notificationService: NotificationService
30 ) {}
31
32 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
33 return next.handle(request).pipe(
34 catchError((resp) => {
35 if (resp instanceof HttpErrorResponse) {
36 let timeoutId: number;
37 switch (resp.status) {
38 case 400:
39 const finishedTask = new FinishedTask();
40
41 const task = resp.error.task;
42 if (_.isPlainObject(task)) {
43 task.metadata.component = task.metadata.component || resp.error.component;
44
45 finishedTask.name = task.name;
46 finishedTask.metadata = task.metadata;
47 } else {
48 finishedTask.metadata = resp.error;
49 }
50
51 finishedTask.success = false;
52 finishedTask.exception = resp.error;
53 timeoutId = this.notificationService.notifyTask(finishedTask);
54 break;
55 case 401:
56 this.authStorageService.remove();
57 this.router.navigate(['/login']);
58 break;
59 case 403:
60 this.router.navigate(['/403']);
61 break;
62 default:
63 timeoutId = this.prepareNotification(resp);
64 }
65
66 /**
67 * Decorated preventDefault method (in case error previously had
68 * preventDefault method defined). If called, it will prevent a
69 * notification to be shown.
70 */
71 resp['preventDefault'] = () => {
72 this.notificationService.cancel(timeoutId);
73 };
74
75 /**
76 * If called, it will prevent a notification for the specific status code.
77 * @param {number} status The status code to be ignored.
78 */
79 resp['ignoreStatusCode'] = function(status: number) {
80 if (this.status === status) {
81 this.preventDefault();
82 }
83 };
84 }
85 // Return the error to the method that called it.
86 return observableThrowError(resp);
87 })
88 );
89 }
90
91 private prepareNotification(resp): number {
92 return this.notificationService.show(() => {
93 let message = '';
94 if (_.isPlainObject(resp.error) && _.isString(resp.error.detail)) {
95 message = resp.error.detail; // Error was triggered by the backend.
96 } else if (_.isString(resp.error)) {
97 message = resp.error;
98 } else if (_.isString(resp.message)) {
99 message = resp.message;
100 }
101 return new CdNotificationConfig(
102 NotificationType.error,
103 `${resp.status} - ${resp.statusText}`,
104 message,
105 undefined,
106 resp['application']
107 );
108 });
109 }
110 }