]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
redirect to login on 401, display error variants in 404 component
authorRigel Kent <sendmemail@rigelk.eu>
Sun, 24 Jan 2021 02:02:04 +0000 (03:02 +0100)
committerChocobozzz <chocobozzz@cpy.re>
Mon, 25 Jan 2021 14:37:26 +0000 (15:37 +0100)
client/src/app/+accounts/accounts.component.ts
client/src/app/+page-not-found/page-not-found.component.html
client/src/app/+page-not-found/page-not-found.component.ts
client/src/app/+video-channels/video-channels.component.ts
client/src/app/+videos/+video-watch/video-watch.component.ts
client/src/app/core/rest/rest-extractor.service.ts
client/src/app/shared/shared-main/auth/auth-interceptor.service.ts

index 1458ea59c40acc24fcc379bf9abfe0dec380af84..e6a5a5d5ec2f3a7337fbddef15a0d065549b6d3e 100644 (file)
@@ -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
                           ]))
index aa57b07e8afba0f511b665eacaf7da0e488939bc..efd3cc9f985b76ef3dfb0abb7459a7978263f26c 100644 (file)
@@ -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>
index 81830d4152644fb0c4060fb424f0fef3bb6ff2a6..9302201ea477fdee75131384c7866a889e77b835 100644 (file)
@@ -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'
index d2fd265c4a7d300ede2e794296458217b2afac62..bb601e22725989edde949275c4dc0577df67a70f 100644 (file)
@@ -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
                           ]))
index c757a5e9370413595d7564dea7a3d588981fb880..b698d554f8ef92788839f2a0a782daa6d7d8083d 100644 (file)
@@ -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
         ]))
index 84d9ed074d4580b1348b6b2a262f6a9dba9af6cb..b8a95cca63d1a6e22c9c4f965ab3a3c8e8618f67 100644 (file)
@@ -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)
index 68a4acdb5242466766ad566a5005e04e532bcd36..3ddaffbdf35f2cc8b51e70fa532309326332b71d 100644 (file)
@@ -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 = {