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