import {
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
} from '@angular/common/http';
import { Injectable, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { Store } from '@ngxs/store';
import { IAdminDTO } from '@namdorang/interface';
import {
Observable,
Subscription,
catchError,
of,
switchMap,
throwError,
} from 'rxjs';
import { AdminStore, SetAdmin } from '../store/auth.store';
import { HttpService } from '../services/http.service';
import { ToastService } from '@common/lib';
@Injectable({
providedIn: 'root',
})
export class HttpInterceptorImpl implements HttpInterceptor, OnDestroy {
sub?: Subscription;
constructor(
private readonly toastService: ToastService,
private readonly store: Store,
private readonly router: Router,
private readonly httpService: HttpService
) {}
ngOnDestroy(): void {
this.sub?.unsubscribe;
}
intercept(
req: HttpRequest<any>,
httpHandler: HttpHandler
): Observable<HttpEvent<any>> {
const accessToken = localStorage.getItem('accessToken');
const request = req.clone(
accessToken
? {
setHeaders: {
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
},
}
: {}
);
return httpHandler.handle(request).pipe(
catchError((e) => {
const status: number = e.status;
if (status === 498) {
this.store.reset(AdminStore);
this.httpService
.get<{ accessToken: string }>('auth/refresh', {
headers: {
RefreshToken: `Bearer ${localStorage.getItem('refreshToken')}`,
},
})
.pipe(
switchMap(({ accessToken }) => {
localStorage.setItem('accessToken', accessToken);
return this.httpService.get<IAdminDTO>('auth');
}),
catchError(() => {
this.toastService.show('로그인 후 이용 가능합니다.', 'primary');
this.router.navigateByUrl('login');
return of(null);
})
)
.subscribe((admin) => {
if (admin) {
this.store.dispatch(new SetAdmin(admin));
}
});
} else if (status === 401) {
this.store.reset(AdminStore);
this.toastService.show(e.error.message, 'danger');
this.router.navigateByUrl('login');
} else if (status !== 500) {
this.toastService.show(e.error.message, 'danger');
}
return throwError(() => new Error(e));
})
);
}
}