]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
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'; | |
11fdf7f2 TL |
20 | |
21 | @Injectable({ | |
81eedcae | 22 | providedIn: 'root' |
11fdf7f2 TL |
23 | }) |
24 | export 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 | } |