Skip to content

Commit

Permalink
feat(permission) more detailed error message when user has no access …
Browse files Browse the repository at this point in the history
…to a project or the project is not found. fixes #783

Signed-off-by: David Edler <[email protected]>
  • Loading branch information
edlerd committed Jun 3, 2024
1 parent 0e4de77 commit d1d2c30
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 5 deletions.
11 changes: 9 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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) {
Expand All @@ -93,7 +95,11 @@ const App: FC = () => {
path={path}
element={
<Navigate
to={`/ui/project/${defaultProject}/instances`}
to={
hasNoProjects
? "/ui/no-project"
: `/ui/project/${defaultProject}/instances`
}
replace={true}
/>
}
Expand Down Expand Up @@ -397,6 +403,7 @@ const App: FC = () => {
element={<CertificateGenerate />}
/>
<Route path="/ui/login/certificate-add" element={<CertificateAdd />} />
<Route path="ui/no-project" element={<NoProject />} />
<Route path="*" element={<NoMatch />} />
</Routes>
</Suspense>
Expand Down
37 changes: 37 additions & 0 deletions src/components/NoProject.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<CustomLayout mainClassName="no-match">
<Row>
<Col size={6} className="col-start-large-4">
<h1 className="p-heading--4">Project not found</h1>
<p>
The project <code>{project}</code> is missing or you do not have
access.
<br />
If you think this is an error in our product, please{" "}
<a
href="https://github.com/canonical/lxd-ui/issues/new"
target="_blank"
rel="noopener noreferrer"
title="Report a bug"
>
Report a bug
</a>
.
</p>
</Col>
</Row>
</CustomLayout>
);
};

export default NoProject;
5 changes: 4 additions & 1 deletion src/context/auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ interface ContextProps {
isOidc: boolean;
isRestricted: boolean;
defaultProject: string;
hasNoProjects: boolean;
}

const initialState: ContextProps = {
Expand All @@ -19,6 +20,7 @@ const initialState: ContextProps = {
isOidc: false,
isRestricted: false,
defaultProject: "default",
hasNoProjects: false,
};

export const AuthContext = createContext<ContextProps>(initialState);
Expand All @@ -30,7 +32,7 @@ interface ProviderProps {
export const AuthProvider: FC<ProviderProps> = ({ 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",
Expand Down Expand Up @@ -63,6 +65,7 @@ export const AuthProvider: FC<ProviderProps> = ({ children }) => {
isAuthLoading: isLoading,
isRestricted,
defaultProject,
hasNoProjects: projects.length === 0 && !isProjectsLoading,
}}
>
{children}
Expand Down
4 changes: 2 additions & 2 deletions src/pages/projects/ProjectLoader.tsx
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -14,7 +14,7 @@ const ProjectLoader = ({ outlet }: Props) => {
}

if (!project) {
return <NoMatch />;
return <NoProject />;
}

return outlet;
Expand Down

0 comments on commit d1d2c30

Please sign in to comment.