]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.ts
update source to Ceph Pacific 16.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
f67539c2 11import _ from 'lodash';
11fdf7f2
TL
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 20
9f95a23c
TL
21export class CdHttpErrorResponse extends HttpErrorResponse {
22 preventDefault: Function;
23 ignoreStatusCode: Function;
24}
25
11fdf7f2 26@Injectable({
81eedcae 27 providedIn: 'root'
11fdf7f2
TL
28})
29export class ApiInterceptorService implements HttpInterceptor {
30 constructor(
31 private router: Router,
32 private authStorageService: AuthStorageService,
33 public notificationService: NotificationService
34 ) {}
35
36 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
f67539c2
TL
37 const defaultVersion = '1.0';
38 const acceptHeader = request.headers.get('Accept');
39 let reqWithVersion: HttpRequest<any>;
40 if (acceptHeader && acceptHeader.startsWith('application/vnd.ceph.api.v')) {
41 reqWithVersion = request.clone();
42 } else {
43 reqWithVersion = request.clone({
44 setHeaders: {
45 Accept: `application/vnd.ceph.api.v${defaultVersion}+json`
46 }
47 });
48 }
49 return next.handle(reqWithVersion).pipe(
9f95a23c 50 catchError((resp: CdHttpErrorResponse) => {
11fdf7f2
TL
51 if (resp instanceof HttpErrorResponse) {
52 let timeoutId: number;
53 switch (resp.status) {
54 case 400:
55 const finishedTask = new FinishedTask();
56
57 const task = resp.error.task;
58 if (_.isPlainObject(task)) {
59 task.metadata.component = task.metadata.component || resp.error.component;
60
61 finishedTask.name = task.name;
62 finishedTask.metadata = task.metadata;
63 } else {
64 finishedTask.metadata = resp.error;
65 }
66
67 finishedTask.success = false;
68 finishedTask.exception = resp.error;
69 timeoutId = this.notificationService.notifyTask(finishedTask);
70 break;
71 case 401:
72 this.authStorageService.remove();
73 this.router.navigate(['/login']);
74 break;
75 case 403:
f67539c2
TL
76 this.router.navigate(['error'], {
77 state: {
78 message: $localize`Sorry, you don’t have permission to view this page or resource.`,
79 header: $localize`Access Denied`,
80 icon: 'fa fa-lock',
81 source: 'forbidden'
82 }
83 });
11fdf7f2
TL
84 break;
85 default:
86 timeoutId = this.prepareNotification(resp);
87 }
88
89 /**
90 * Decorated preventDefault method (in case error previously had
91 * preventDefault method defined). If called, it will prevent a
92 * notification to be shown.
93 */
9f95a23c 94 resp.preventDefault = () => {
11fdf7f2
TL
95 this.notificationService.cancel(timeoutId);
96 };
97
98 /**
99 * If called, it will prevent a notification for the specific status code.
100 * @param {number} status The status code to be ignored.
101 */
e306af50 102 resp.ignoreStatusCode = function (status: number) {
11fdf7f2
TL
103 if (this.status === status) {
104 this.preventDefault();
105 }
106 };
107 }
108 // Return the error to the method that called it.
109 return observableThrowError(resp);
110 })
111 );
112 }
113
9f95a23c 114 private prepareNotification(resp: any): number {
11fdf7f2
TL
115 return this.notificationService.show(() => {
116 let message = '';
117 if (_.isPlainObject(resp.error) && _.isString(resp.error.detail)) {
118 message = resp.error.detail; // Error was triggered by the backend.
119 } else if (_.isString(resp.error)) {
120 message = resp.error;
121 } else if (_.isString(resp.message)) {
122 message = resp.message;
123 }
124 return new CdNotificationConfig(
125 NotificationType.error,
126 `${resp.status} - ${resp.statusText}`,
127 message,
128 undefined,
129 resp['application']
130 );
131 });
132 }
133}