Split 401

This commit is contained in:
Kilian Hofmann 2024-07-28 03:04:26 +02:00
parent 73c7dc1b5e
commit 96bdbfc62a
15 changed files with 77 additions and 75 deletions

1
exam/dist/assets/index-B93xlZhH.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,10 +5,10 @@
<link rel="icon" type="image/svg+xml" href="/phpCourse/exam/dist/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<script type="module" crossorigin src="/phpCourse/exam/dist/assets/index-tFNBNNKb.js"></script>
<script type="module" crossorigin src="/phpCourse/exam/dist/assets/index-B93xlZhH.js"></script>
<link rel="modulepreload" crossorigin href="/phpCourse/exam/dist/assets/react-C_FdcE2X.js">
<link rel="modulepreload" crossorigin href="/phpCourse/exam/dist/assets/mui-C4H8cxTH.js">
<link rel="modulepreload" crossorigin href="/phpCourse/exam/dist/assets/tanstack-Duf7jkFs.js">
<link rel="modulepreload" crossorigin href="/phpCourse/exam/dist/assets/tanstack-C0csOcmc.js">
<link rel="modulepreload" crossorigin href="/phpCourse/exam/dist/assets/i18n-DyW0LrNj.js">
<link rel="stylesheet" crossorigin href="/phpCourse/exam/dist/assets/mui-CKDNpdid.css">
<link rel="stylesheet" crossorigin href="/phpCourse/exam/dist/assets/index-D83Ey19k.css">

View File

@ -1,23 +1,23 @@
{
"Unauthorized": "Keine Berechtigung",
"Unauthorized_login": "Ungültige E-Mail oder Passwort",
"NotAllowed_login": "Ungültige E-Mail oder Passwort",
"NotFound_user:login": "Benutzer existiert nicht",
"MissingField_email:login": "E-Mail darf nicht leer sein",
"MissingField_password:login": "Passwort darf nicht leer sein",
"Unauthorized_deletePost": "Keine Berechtigung",
"NotAllowed_deletePost": "Keine Berechtigung",
"NotFound_post:deletePost": "Post nicht gefunden",
"Unauthorized_userUpdate": "Keine Berechtigung",
"NotAllowed_userUpdate": "Keine Berechtigung",
"NotFound_user:userUpdate": "Benutzer nicht gefunden",
"FailedUpdate_Duplicate:username:userUpdate": "Ein Benutzer mit diesem Benutzernamen existiert schon",
"FailedUpdate_Duplicate:email:userUpdate": "Ein Benutzer mit dieser E-Mail existiert schon",
"Unauthorized_newPost": "Keine Berechtigung",
"NotAllowed_newPost": "Keine Berechtigung",
"MissingField_content:newPost": "Beitrag darf nicht leer sein",
"Unauthorized_postUpdate": "Keine Berechtigung",
"NotAllowed_postUpdate": "Keine Berechtigung",
"NotFound_post:postUpdate": "Post nicht gefunden",
"Duplicate_user:register": "Ein Benutzer mit diesem Benutzernamen oder E-Mail existiert schon",

View File

@ -1,23 +1,23 @@
{
"Unauthorized": "Unauthorized",
"Unauthorized": "NotAllowed",
"Unauthorized_login": "Invalid email or password",
"NotAllowed_login": "Invalid email or password",
"NotFound_user:login": "User does not exist",
"MissingField_email:login": "E-Mail required",
"MissingField_password:login": "Password required",
"Unauthorized_deletPost": "Unauthorized",
"NotAllowed_deletPost": "NotAllowed",
"NotFound_post:deletePost": "Post not found",
"Unauthorized_userUpdate": "Unauthorized",
"NotAllowed_userUpdate": "NotAllowed",
"NotFound_user:userUpdate": "User not found",
"FailedUpdate_Duplicate:userUpdate": "A user with this username already exists",
"FailedUpdate_Duplicate:email:userUpdate": "A user with this email already exists",
"Unauthorized_newPost": "Unauthorized",
"NotAllowed_newPost": "NotAllowed",
"MissingField_content:newPost": "Content required",
"Unauthorized_postUpdate": "Unauthorized",
"NotAllowed_postUpdate": "NotAllowed",
"NotFound_post:postUpdate": "Post not found",
"Duplicate_user:register": "A user with this username or email already exists",

File diff suppressed because one or more lines are too long

View File

@ -1,23 +1,23 @@
{
"Unauthorized": "Keine Berechtigung",
"Unauthorized_login": "Ungültige E-Mail oder Passwort",
"NotAllowed_login": "Ungültige E-Mail oder Passwort",
"NotFound_user:login": "Benutzer existiert nicht",
"MissingField_email:login": "E-Mail darf nicht leer sein",
"MissingField_password:login": "Passwort darf nicht leer sein",
"Unauthorized_deletePost": "Keine Berechtigung",
"NotAllowed_deletePost": "Keine Berechtigung",
"NotFound_post:deletePost": "Post nicht gefunden",
"Unauthorized_userUpdate": "Keine Berechtigung",
"NotAllowed_userUpdate": "Keine Berechtigung",
"NotFound_user:userUpdate": "Benutzer nicht gefunden",
"FailedUpdate_Duplicate:username:userUpdate": "Ein Benutzer mit diesem Benutzernamen existiert schon",
"FailedUpdate_Duplicate:email:userUpdate": "Ein Benutzer mit dieser E-Mail existiert schon",
"Unauthorized_newPost": "Keine Berechtigung",
"NotAllowed_newPost": "Keine Berechtigung",
"MissingField_content:newPost": "Beitrag darf nicht leer sein",
"Unauthorized_postUpdate": "Keine Berechtigung",
"NotAllowed_postUpdate": "Keine Berechtigung",
"NotFound_post:postUpdate": "Post nicht gefunden",
"Duplicate_user:register": "Ein Benutzer mit diesem Benutzernamen oder E-Mail existiert schon",

View File

@ -1,23 +1,23 @@
{
"Unauthorized": "Unauthorized",
"Unauthorized": "NotAllowed",
"Unauthorized_login": "Invalid email or password",
"NotAllowed_login": "Invalid email or password",
"NotFound_user:login": "User does not exist",
"MissingField_email:login": "E-Mail required",
"MissingField_password:login": "Password required",
"Unauthorized_deletPost": "Unauthorized",
"NotAllowed_deletPost": "NotAllowed",
"NotFound_post:deletePost": "Post not found",
"Unauthorized_userUpdate": "Unauthorized",
"NotAllowed_userUpdate": "NotAllowed",
"NotFound_user:userUpdate": "User not found",
"FailedUpdate_Duplicate:userUpdate": "A user with this username already exists",
"FailedUpdate_Duplicate:email:userUpdate": "A user with this email already exists",
"Unauthorized_newPost": "Unauthorized",
"NotAllowed_newPost": "NotAllowed",
"MissingField_content:newPost": "Content required",
"Unauthorized_postUpdate": "Unauthorized",
"NotAllowed_postUpdate": "NotAllowed",
"NotFound_post:postUpdate": "Post not found",
"Duplicate_user:register": "A user with this username or email already exists",

View File

@ -44,7 +44,8 @@ class ApiImpl {
public logOut = async (): Promise<boolean> => {
try {
return await (await this.postAuth('logout')).json();
if (this.token) return await (await this.postAuth('logout')).json();
return true;
} catch {
return false;
} finally {

View File

@ -19,7 +19,7 @@ const ErrorComponent: FC<Props> = ({ error, context, color = 'error.main' }) =>
switch (error.code) {
case ERRORS.NOT_FOUND:
return <Typography color={color}>{t(error.code, { context: `${error.entity}:${context}` })}</Typography>;
case ERRORS.UNAUTHORIZED:
case ERRORS.NOT_ALLOWED:
return <Typography color={color}>{t(error.code, { context })}</Typography>;
case ERRORS.FAILED_UPDATE:
return error.fields.map((field: string, index: number) => (

View File

@ -1,6 +1,7 @@
export enum ERRORS {
NOT_FOUND = 'NotFound',
UNAUTHORIZED = 'Unauthorized',
NOT_ALLOWED = 'NotAllowed',
FAILED_UPDATE = 'FailedUpdate',
MISSING_FIELD = 'MissingField',
DUPLICATE = 'Duplicate',

View File

@ -71,11 +71,9 @@ const UserMenu: FC<Props> = ({ anchorEl, handleClose }) => {
</MenuItem>,
]
) : register ? (
<>
<RegisterDialog open={register} onClose={() => setRegister(false)} />
</>
<RegisterDialog open={register} onClose={() => setRegister(false)} />
) : (
<>
<Box>
<LoginForm handleClose={_handleClose} />
<Box sx={{ padding: 1 }}>
<Trans i18nKey="Register prompt">
@ -92,7 +90,7 @@ const UserMenu: FC<Props> = ({ anchorEl, handleClose }) => {
<Typography component="span" />
</Trans>
</Box>
</>
</Box>
)}
</Menu>
);

View File

@ -1,7 +1,9 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { RouterProvider, createRouter } from '@tanstack/react-router';
import { StrictMode } from 'react';
import { QueryClient, QueryClientProvider, useQueryClient, useQueryErrorResetBoundary } from '@tanstack/react-query';
import { ErrorRouteComponent, RouterProvider, createRouter, useRouter } from '@tanstack/react-router';
import { StrictMode, useEffect } from 'react';
import ReactDOM from 'react-dom/client';
import Api from './api/Api';
import { ERRORS } from './components/Error/Errors';
// Import the generated route tree
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
@ -19,6 +21,40 @@ import '@fontsource/roboto/700.css';
// Query Client
const queryClient = new QueryClient();
//TODO: REAUTH HERE
//TODO: Make nice
export const Error: ErrorRouteComponent = ({ error }) => {
const router = useRouter();
const queryErrorResetBoundary = useQueryErrorResetBoundary();
const queryClient = useQueryClient();
useEffect(() => {
// Reset the query error boundary
queryErrorResetBoundary.reset();
}, [queryErrorResetBoundary]);
//TODO: Split display, show something went wrong with retry on all, show session expired and back to main on auth
if ('code' in error && error.code === ERRORS.NOT_ALLOWED) {
Api.logOut().finally(() => {
queryClient.clear();
router.invalidate();
});
}
return (
<div>
{error.message}
<button
onClick={() => {
router.invalidate();
}}
>
retry
</button>
</div>
);
};
// Create a new router instance
const router = createRouter({
routeTree,
@ -30,6 +66,7 @@ const router = createRouter({
// This will ensure that the loader is always called when the route is preloaded or visited
defaultPreloadStaleTime: 0,
basepath: process.env.NODE_ENV === 'development' ? 'phpCourse/exam/dist' : '/phpCourse/exam',
defaultErrorComponent: Error,
});
// Register the router instance for type safety
@ -47,7 +84,7 @@ if (!rootElement.innerHTML) {
<StrictMode>
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
<ReactQueryDevtools initialIsOpen={false} />
{process.env.NODE_ENV === 'development' && <ReactQueryDevtools initialIsOpen={false} />}
</QueryClientProvider>
</StrictMode>
);

View File

@ -1,16 +1,10 @@
import { Box } from '@mui/material';
import { QueryClient, useQueryErrorResetBoundary } from '@tanstack/react-query';
import { createRootRouteWithContext, ErrorRouteComponent, Outlet, redirect, useRouter } from '@tanstack/react-router';
import { QueryClient } from '@tanstack/react-query';
import { createRootRouteWithContext, Outlet } from '@tanstack/react-router';
import { TanStackRouterDevtools } from '@tanstack/router-devtools';
import { useEffect } from 'react';
import Api from '../api/Api';
import { ERRORS } from '../components/Error/Errors';
import Header from '../components/Header/Header';
import { ROUTES } from '../types/Routes';
const Root = () => {
//TODO: REAUTH HERE
return (
<>
<Header />
@ -24,35 +18,6 @@ const Root = () => {
);
};
//TODO: Make nice
const Error: ErrorRouteComponent = ({ error }) => {
const router = useRouter();
const queryErrorResetBoundary = useQueryErrorResetBoundary();
useEffect(() => {
// Reset the query error boundary
queryErrorResetBoundary.reset();
}, [queryErrorResetBoundary]);
if ('code' in error && error.code === ERRORS.UNAUTHORIZED) {
Api.logOut();
redirect({ to: ROUTES.INDEX });
}
return (
<div>
{error.message}
<button
onClick={() => {
router.invalidate();
}}
>
retry
</button>
</div>
);
};
export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()({
component: Root,
errorComponent: Error,
});