diff --git a/packages/admin/admin/src/error/errordialog/createErrorDialogApolloLink.tsx b/packages/admin/admin/src/error/errordialog/createErrorDialogApolloLink.tsx index b0d59f68a3..2708037aaf 100644 --- a/packages/admin/admin/src/error/errordialog/createErrorDialogApolloLink.tsx +++ b/packages/admin/admin/src/error/errordialog/createErrorDialogApolloLink.tsx @@ -23,11 +23,15 @@ export const createErrorDialogApolloLink = () => { let title: React.ReactNode | undefined; let userMessage: React.ReactNode | undefined; let httpStatus: string | undefined; + let isUnauthenticated = false; if (graphQLErrors) { error = graphQLErrors.map(({ message }) => message); errorType = "graphql"; title = ; + isUnauthenticated = graphQLErrors.some( + (e) => e.extensions?.exception?.status === StatusCodes.UNAUTHORIZED || e.extensions?.code === "UNAUTHENTICATED", + ); } if (networkError) { @@ -41,23 +45,24 @@ export const createErrorDialogApolloLink = () => { if (isServerError(networkError)) { const { statusCode } = networkError; httpStatus = `${statusCode} ${getReasonPhrase(statusCode)}`; - - if (statusCode === StatusCodes.UNAUTHORIZED) { - title = ; - userMessage = ( - <> - - - - - - ); - } + isUnauthenticated = statusCode === StatusCodes.UNAUTHORIZED; } } + if (!isUnauthenticated) { + title = ; + userMessage = ( + <> + + + + + + ); + } + errorDialogVar({ title, error: error ?? "Unknown error", diff --git a/packages/admin/cms-admin/src/userPermissions/hooks/currentUser.tsx b/packages/admin/cms-admin/src/userPermissions/hooks/currentUser.tsx index 5899480eef..08c20b9bc7 100644 --- a/packages/admin/cms-admin/src/userPermissions/hooks/currentUser.tsx +++ b/packages/admin/cms-admin/src/userPermissions/hooks/currentUser.tsx @@ -1,5 +1,6 @@ import { gql, useQuery } from "@apollo/client"; import { Loading } from "@comet/admin"; +import { Button, Typography } from "@mui/material"; import React from "react"; import { ContentScopeInterface } from "../../contentScope/Provider"; @@ -34,7 +35,25 @@ export const CurrentUserProvider: React.FC<{ } `); - if (error) throw error.message; + // As this Provider is very high up in the tree, don't rely on ErrorBoundary or a configured intl-Provider here + if (error) { + const isUnauthenticated = error.graphQLErrors.some( + (e) => e.extensions?.exception?.status === 401 || e.extensions?.code === "UNAUTHENTICATED", + ); + return ( + <> + {isUnauthenticated ? "Your access-token is invalid. Re-login might help." : error.message} + {isUnauthenticated && ( + + )} + + ); + } if (!data) return ; diff --git a/packages/api/cms-api/src/auth/guards/comet.guard.ts b/packages/api/cms-api/src/auth/guards/comet.guard.ts index 621fb735fd..c78e4cc03d 100644 --- a/packages/api/cms-api/src/auth/guards/comet.guard.ts +++ b/packages/api/cms-api/src/auth/guards/comet.guard.ts @@ -1,4 +1,4 @@ -import { CanActivate, ExecutionContext, HttpException, Injectable, mixin } from "@nestjs/common"; +import { CanActivate, ExecutionContext, Injectable, mixin, UnauthorizedException } from "@nestjs/common"; import { Reflector } from "@nestjs/core"; import { GqlExecutionContext } from "@nestjs/graphql"; import { AuthGuard, IAuthGuard, Type } from "@nestjs/passport"; @@ -19,14 +19,14 @@ export function createCometAuthGuard(type?: string | string[]): Type } // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any - handleRequest(err: unknown, user: any): CurrentUserInterface { + handleRequest(err: unknown, user: any, info: any): CurrentUserInterface { if (err) { throw err; } if (user) { return user; } - throw new HttpException("UserNotAuthenticated", 200); + throw new UnauthorizedException(info[0]?.message); } async canActivate(context: ExecutionContext): Promise {