redirect to login on 401, display error variants in 404 component
This commit is contained in:
parent
6939cbac48
commit
ab398a05e9
|
@ -50,7 +50,7 @@ export class AccountsComponent implements OnInit, OnDestroy {
|
|||
switchMap(accountId => this.accountService.getAccount(accountId)),
|
||||
tap(account => this.onAccount(account)),
|
||||
switchMap(account => this.videoChannelService.listAccountVideoChannels(account)),
|
||||
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [
|
||||
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, 'other', [
|
||||
HttpStatusCode.BAD_REQUEST_400,
|
||||
HttpStatusCode.NOT_FOUND_404
|
||||
]))
|
||||
|
|
|
@ -1,23 +1,32 @@
|
|||
<div class="root">
|
||||
<div *ngIf="status === 404" class="box">
|
||||
<div *ngIf="status !== 403 && status !== 418" class="box">
|
||||
<strong>{{ status }}.</strong>
|
||||
<span class="ml-1 text-muted" i18n>That's an error.</span>
|
||||
|
||||
<div class="text mt-4" i18n>
|
||||
We couldn't find any ressource tied to the URL {{ pathname }} you were looking for.
|
||||
We couldn't find any {{ getRessourceName() }} tied to the URL {{ pathname }} you were looking for.
|
||||
</div>
|
||||
|
||||
<div class="text-muted mt-4">
|
||||
<span i18n="Possible reasons preceding a list of reasons a `Not Found` error page may occur">Possible reasons:</span>
|
||||
|
||||
<ul>
|
||||
<li i18n>The page may have been moved or deleted</li>
|
||||
<li i18n>You may have used an outdated or broken link</li>
|
||||
<li i18n>The {{ getRessourceName() }} may have been moved or deleted</li>
|
||||
<li i18n>You may have typed the address or URL incorrectly</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="status === 403" class="box">
|
||||
<strong>{{ status }}.</strong>
|
||||
<span class="ml-1 text-muted" i18n>You are not authorized here.</span>
|
||||
|
||||
<div class="text mt-4" i18n>
|
||||
You might need to check your account is allowed by the {{ getRessourceName() }} or instance owner.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="status === 418" class="box">
|
||||
<strong>{{ status }}.</strong>
|
||||
<span class="ml-1 text-muted">I'm a teapot.</span>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Component, OnInit } from '@angular/core'
|
||||
import { Title } from '@angular/platform-browser'
|
||||
import { Router } from '@angular/router'
|
||||
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||
|
||||
@Component({
|
||||
|
@ -9,10 +10,16 @@ import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
|||
})
|
||||
export class PageNotFoundComponent implements OnInit {
|
||||
status = HttpStatusCode.NOT_FOUND_404
|
||||
type: string
|
||||
|
||||
public constructor (
|
||||
private titleService: Title
|
||||
) {}
|
||||
private titleService: Title,
|
||||
private router: Router
|
||||
) {
|
||||
const state = this.router.getCurrentNavigation()?.extras.state
|
||||
this.type = state?.type || this.type
|
||||
this.status = state?.obj.status || this.status
|
||||
}
|
||||
|
||||
ngOnInit () {
|
||||
if (this.pathname.includes('teapot')) {
|
||||
|
@ -25,10 +32,21 @@ export class PageNotFoundComponent implements OnInit {
|
|||
return window.location.pathname
|
||||
}
|
||||
|
||||
getRessourceName () {
|
||||
switch (this.type) {
|
||||
case 'video':
|
||||
return $localize`video`
|
||||
default:
|
||||
return $localize`ressource`
|
||||
}
|
||||
}
|
||||
|
||||
getMascotName () {
|
||||
switch (this.status) {
|
||||
case HttpStatusCode.I_AM_A_TEAPOT_418:
|
||||
return 'happy'
|
||||
case HttpStatusCode.FORBIDDEN_403:
|
||||
return 'arguing'
|
||||
case HttpStatusCode.NOT_FOUND_404:
|
||||
default:
|
||||
return 'defeated'
|
||||
|
|
|
@ -38,7 +38,7 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
|
|||
map(params => params[ 'videoChannelName' ]),
|
||||
distinctUntilChanged(),
|
||||
switchMap(videoChannelName => this.videoChannelService.getVideoChannel(videoChannelName)),
|
||||
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [
|
||||
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, 'other', [
|
||||
HttpStatusCode.BAD_REQUEST_400,
|
||||
HttpStatusCode.NOT_FOUND_404
|
||||
]))
|
||||
|
|
|
@ -404,7 +404,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
this.videoCaptionService.listCaptions(videoId)
|
||||
])
|
||||
.pipe(
|
||||
// If 401, the video is private or blocked so redirect to 404
|
||||
// If 400, 403 or 404, the video is private or blocked so redirect to 404
|
||||
catchError(err => {
|
||||
if (err.body.errorCode === ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS && err.body.originUrl) {
|
||||
const search = window.location.search
|
||||
|
@ -416,9 +416,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
$localize`Redirection`
|
||||
).then(res => {
|
||||
if (res === false) {
|
||||
return this.restExtractor.redirectTo404IfNotFound(err, [
|
||||
return this.restExtractor.redirectTo404IfNotFound(err, 'video', [
|
||||
HttpStatusCode.BAD_REQUEST_400,
|
||||
HttpStatusCode.UNAUTHORIZED_401,
|
||||
HttpStatusCode.FORBIDDEN_403,
|
||||
HttpStatusCode.NOT_FOUND_404
|
||||
])
|
||||
|
@ -428,9 +427,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
})
|
||||
}
|
||||
|
||||
return this.restExtractor.redirectTo404IfNotFound(err, [
|
||||
return this.restExtractor.redirectTo404IfNotFound(err, 'video', [
|
||||
HttpStatusCode.BAD_REQUEST_400,
|
||||
HttpStatusCode.UNAUTHORIZED_401,
|
||||
HttpStatusCode.FORBIDDEN_403,
|
||||
HttpStatusCode.NOT_FOUND_404
|
||||
])
|
||||
|
@ -464,10 +462,9 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
|
||||
this.playlistService.getVideoPlaylist(playlistId)
|
||||
.pipe(
|
||||
// If 401, the video is private or blocked so redirect to 404
|
||||
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [
|
||||
// If 400 or 403, the video is private or blocked so redirect to 404
|
||||
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, 'video', [
|
||||
HttpStatusCode.BAD_REQUEST_400,
|
||||
HttpStatusCode.UNAUTHORIZED_401,
|
||||
HttpStatusCode.FORBIDDEN_403,
|
||||
HttpStatusCode.NOT_FOUND_404
|
||||
]))
|
||||
|
|
|
@ -93,10 +93,10 @@ export class RestExtractor {
|
|||
return observableThrowError(errorObj)
|
||||
}
|
||||
|
||||
redirectTo404IfNotFound (obj: { status: number }, status = [ HttpStatusCode.NOT_FOUND_404 ]) {
|
||||
redirectTo404IfNotFound (obj: { status: number }, type: 'video' | 'other', status = [ HttpStatusCode.NOT_FOUND_404 ]) {
|
||||
if (obj && obj.status && status.indexOf(obj.status) !== -1) {
|
||||
// Do not use redirectService to avoid circular dependencies
|
||||
this.router.navigate([ '/404' ], { skipLocationChange: true })
|
||||
this.router.navigate([ '/404' ], { state: { type, obj }, skipLocationChange: true })
|
||||
}
|
||||
|
||||
return observableThrowError(obj)
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
import { Observable, throwError as observableThrowError } from 'rxjs'
|
||||
import { Observable, of, throwError as observableThrowError } from 'rxjs'
|
||||
import { catchError, switchMap } from 'rxjs/operators'
|
||||
import { HTTP_INTERCEPTORS, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'
|
||||
import { HTTP_INTERCEPTORS, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpErrorResponse } from '@angular/common/http'
|
||||
import { Injectable, Injector } from '@angular/core'
|
||||
import { AuthService } from '@app/core/auth/auth.service'
|
||||
import { Router } from '@angular/router'
|
||||
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||
|
||||
@Injectable()
|
||||
export class AuthInterceptor implements HttpInterceptor {
|
||||
private authService: AuthService
|
||||
|
||||
// https://github.com/angular/angular/issues/18224#issuecomment-316957213
|
||||
constructor (private injector: Injector) {}
|
||||
constructor (private injector: Injector, private router: Router) {}
|
||||
|
||||
intercept (req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
if (this.authService === undefined) {
|
||||
|
@ -22,9 +24,11 @@ export class AuthInterceptor implements HttpInterceptor {
|
|||
// Catch 401 errors (refresh token expired)
|
||||
return next.handle(authReq)
|
||||
.pipe(
|
||||
catchError(err => {
|
||||
if (err.status === 401 && err.error && err.error.code === 'invalid_token') {
|
||||
catchError((err: HttpErrorResponse) => {
|
||||
if (err.status === HttpStatusCode.UNAUTHORIZED_401 && err.error && err.error.code === 'invalid_token') {
|
||||
return this.handleTokenExpired(req, next)
|
||||
} else if (err.status === HttpStatusCode.UNAUTHORIZED_401) {
|
||||
return this.handleNotAuthenticated(err)
|
||||
}
|
||||
|
||||
return observableThrowError(err)
|
||||
|
@ -51,6 +55,11 @@ export class AuthInterceptor implements HttpInterceptor {
|
|||
// Clone the request to add the new header
|
||||
return req.clone({ headers: req.headers.set('Authorization', authHeaderValue) })
|
||||
}
|
||||
|
||||
private handleNotAuthenticated (err: HttpErrorResponse, path = '/login'): Observable<any> {
|
||||
this.router.navigateByUrl(path)
|
||||
return of(err.message)
|
||||
}
|
||||
}
|
||||
|
||||
export const AUTH_INTERCEPTOR_PROVIDER = {
|
||||
|
|
Loading…
Reference in New Issue