From d1d2c30bafe3c0d1acbd80f885ca9ab7a45f1839 Mon Sep 17 00:00:00 2001 From: David Edler Date: Tue, 28 May 2024 09:36:08 +0200 Subject: [PATCH] feat(permission) more detailed error message when user has no access to a project or the project is not found. fixes #783 Signed-off-by: David Edler --- src/App.tsx | 11 +++++++-- src/components/NoProject.tsx | 37 ++++++++++++++++++++++++++++ src/context/auth.tsx | 5 +++- src/pages/projects/ProjectLoader.tsx | 4 +-- 4 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 src/components/NoProject.tsx diff --git a/src/App.tsx b/src/App.tsx index aeb63d68e..8060b35d4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -9,6 +9,7 @@ import { setTitle } from "util/title"; import CustomLayout from "components/CustomLayout"; import NoMatch from "components/NoMatch"; import { logout } from "util/helpers"; +import NoProject from "components/NoProject"; const CertificateAdd = lazy(() => import("pages/login/CertificateAdd")); const CertificateGenerate = lazy( @@ -67,7 +68,8 @@ const PermissionIdpGroups = lazy( const HOME_REDIRECT_PATHS = ["/", "/ui", "/ui/project"]; const App: FC = () => { - const { defaultProject, isAuthLoading, isAuthenticated } = useAuth(); + const { defaultProject, hasNoProjects, isAuthLoading, isAuthenticated } = + useAuth(); setTitle(); if (isAuthLoading) { @@ -93,7 +95,11 @@ const App: FC = () => { path={path} element={ } @@ -397,6 +403,7 @@ const App: FC = () => { element={} /> } /> + } /> } /> diff --git a/src/components/NoProject.tsx b/src/components/NoProject.tsx new file mode 100644 index 000000000..f2e4dddea --- /dev/null +++ b/src/components/NoProject.tsx @@ -0,0 +1,37 @@ +import { FC } from "react"; +import { Row, Col } from "@canonical/react-components"; +import CustomLayout from "./CustomLayout"; + +const NoProject: FC = () => { + const url = location.pathname; + const project = url.startsWith("/ui/project/") + ? url.split("/")[3] + : "default"; + + return ( + + + +

Project not found

+

+ The project {project} is missing or you do not have + access. +
+ If you think this is an error in our product, please{" "} + + Report a bug + + . +

+ +
+
+ ); +}; + +export default NoProject; diff --git a/src/context/auth.tsx b/src/context/auth.tsx index 312b2d1e3..675e1c0fa 100644 --- a/src/context/auth.tsx +++ b/src/context/auth.tsx @@ -11,6 +11,7 @@ interface ContextProps { isOidc: boolean; isRestricted: boolean; defaultProject: string; + hasNoProjects: boolean; } const initialState: ContextProps = { @@ -19,6 +20,7 @@ const initialState: ContextProps = { isOidc: false, isRestricted: false, defaultProject: "default", + hasNoProjects: false, }; export const AuthContext = createContext(initialState); @@ -30,7 +32,7 @@ interface ProviderProps { export const AuthProvider: FC = ({ children }) => { const { data: settings, isLoading } = useSettings(); - const { data: projects = [] } = useQuery({ + const { data: projects = [], isLoading: isProjectsLoading } = useQuery({ queryKey: [queryKeys.projects], queryFn: fetchProjects, enabled: settings?.auth === "trusted", @@ -63,6 +65,7 @@ export const AuthProvider: FC = ({ children }) => { isAuthLoading: isLoading, isRestricted, defaultProject, + hasNoProjects: projects.length === 0 && !isProjectsLoading, }} > {children} diff --git a/src/pages/projects/ProjectLoader.tsx b/src/pages/projects/ProjectLoader.tsx index 21b2d1395..98a6cea0a 100644 --- a/src/pages/projects/ProjectLoader.tsx +++ b/src/pages/projects/ProjectLoader.tsx @@ -1,6 +1,6 @@ import Loader from "components/Loader"; -import NoMatch from "components/NoMatch"; import { useProject } from "context/project"; +import NoProject from "components/NoProject"; interface Props { outlet: JSX.Element; @@ -14,7 +14,7 @@ const ProjectLoader = ({ outlet }: Props) => { } if (!project) { - return ; + return ; } return outlet;