Split 401
This commit is contained in:
parent
73c7dc1b5e
commit
96bdbfc62a
1
exam/dist/assets/index-B93xlZhH.js
vendored
Normal file
1
exam/dist/assets/index-B93xlZhH.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
exam/dist/assets/index-tFNBNNKb.js
vendored
1
exam/dist/assets/index-tFNBNNKb.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
exam/dist/index.html
vendored
4
exam/dist/index.html
vendored
@ -5,10 +5,10 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/phpCourse/exam/dist/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/phpCourse/exam/dist/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Vite + React + TS</title>
|
<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/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/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="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/mui-CKDNpdid.css">
|
||||||
<link rel="stylesheet" crossorigin href="/phpCourse/exam/dist/assets/index-D83Ey19k.css">
|
<link rel="stylesheet" crossorigin href="/phpCourse/exam/dist/assets/index-D83Ey19k.css">
|
||||||
|
|||||||
10
exam/dist/locales/de/translation.json
vendored
10
exam/dist/locales/de/translation.json
vendored
@ -1,23 +1,23 @@
|
|||||||
{
|
{
|
||||||
"Unauthorized": "Keine Berechtigung",
|
"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",
|
"NotFound_user:login": "Benutzer existiert nicht",
|
||||||
"MissingField_email:login": "E-Mail darf nicht leer sein",
|
"MissingField_email:login": "E-Mail darf nicht leer sein",
|
||||||
"MissingField_password:login": "Passwort 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",
|
"NotFound_post:deletePost": "Post nicht gefunden",
|
||||||
|
|
||||||
"Unauthorized_userUpdate": "Keine Berechtigung",
|
"NotAllowed_userUpdate": "Keine Berechtigung",
|
||||||
"NotFound_user:userUpdate": "Benutzer nicht gefunden",
|
"NotFound_user:userUpdate": "Benutzer nicht gefunden",
|
||||||
"FailedUpdate_Duplicate:username:userUpdate": "Ein Benutzer mit diesem Benutzernamen existiert schon",
|
"FailedUpdate_Duplicate:username:userUpdate": "Ein Benutzer mit diesem Benutzernamen existiert schon",
|
||||||
"FailedUpdate_Duplicate:email:userUpdate": "Ein Benutzer mit dieser E-Mail 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",
|
"MissingField_content:newPost": "Beitrag darf nicht leer sein",
|
||||||
|
|
||||||
"Unauthorized_postUpdate": "Keine Berechtigung",
|
"NotAllowed_postUpdate": "Keine Berechtigung",
|
||||||
"NotFound_post:postUpdate": "Post nicht gefunden",
|
"NotFound_post:postUpdate": "Post nicht gefunden",
|
||||||
|
|
||||||
"Duplicate_user:register": "Ein Benutzer mit diesem Benutzernamen oder E-Mail existiert schon",
|
"Duplicate_user:register": "Ein Benutzer mit diesem Benutzernamen oder E-Mail existiert schon",
|
||||||
|
|||||||
12
exam/dist/locales/en/translation.json
vendored
12
exam/dist/locales/en/translation.json
vendored
@ -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",
|
"NotFound_user:login": "User does not exist",
|
||||||
"MissingField_email:login": "E-Mail required",
|
"MissingField_email:login": "E-Mail required",
|
||||||
"MissingField_password:login": "Password required",
|
"MissingField_password:login": "Password required",
|
||||||
|
|
||||||
"Unauthorized_deletPost": "Unauthorized",
|
"NotAllowed_deletPost": "NotAllowed",
|
||||||
"NotFound_post:deletePost": "Post not found",
|
"NotFound_post:deletePost": "Post not found",
|
||||||
|
|
||||||
"Unauthorized_userUpdate": "Unauthorized",
|
"NotAllowed_userUpdate": "NotAllowed",
|
||||||
"NotFound_user:userUpdate": "User not found",
|
"NotFound_user:userUpdate": "User not found",
|
||||||
"FailedUpdate_Duplicate:userUpdate": "A user with this username already exists",
|
"FailedUpdate_Duplicate:userUpdate": "A user with this username already exists",
|
||||||
"FailedUpdate_Duplicate:email:userUpdate": "A user with this email already exists",
|
"FailedUpdate_Duplicate:email:userUpdate": "A user with this email already exists",
|
||||||
|
|
||||||
"Unauthorized_newPost": "Unauthorized",
|
"NotAllowed_newPost": "NotAllowed",
|
||||||
"MissingField_content:newPost": "Content required",
|
"MissingField_content:newPost": "Content required",
|
||||||
|
|
||||||
"Unauthorized_postUpdate": "Unauthorized",
|
"NotAllowed_postUpdate": "NotAllowed",
|
||||||
"NotFound_post:postUpdate": "Post not found",
|
"NotFound_post:postUpdate": "Post not found",
|
||||||
|
|
||||||
"Duplicate_user:register": "A user with this username or email already exists",
|
"Duplicate_user:register": "A user with this username or email already exists",
|
||||||
|
|||||||
2
exam/dist/stats.html
vendored
2
exam/dist/stats.html
vendored
File diff suppressed because one or more lines are too long
@ -1,23 +1,23 @@
|
|||||||
{
|
{
|
||||||
"Unauthorized": "Keine Berechtigung",
|
"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",
|
"NotFound_user:login": "Benutzer existiert nicht",
|
||||||
"MissingField_email:login": "E-Mail darf nicht leer sein",
|
"MissingField_email:login": "E-Mail darf nicht leer sein",
|
||||||
"MissingField_password:login": "Passwort 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",
|
"NotFound_post:deletePost": "Post nicht gefunden",
|
||||||
|
|
||||||
"Unauthorized_userUpdate": "Keine Berechtigung",
|
"NotAllowed_userUpdate": "Keine Berechtigung",
|
||||||
"NotFound_user:userUpdate": "Benutzer nicht gefunden",
|
"NotFound_user:userUpdate": "Benutzer nicht gefunden",
|
||||||
"FailedUpdate_Duplicate:username:userUpdate": "Ein Benutzer mit diesem Benutzernamen existiert schon",
|
"FailedUpdate_Duplicate:username:userUpdate": "Ein Benutzer mit diesem Benutzernamen existiert schon",
|
||||||
"FailedUpdate_Duplicate:email:userUpdate": "Ein Benutzer mit dieser E-Mail 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",
|
"MissingField_content:newPost": "Beitrag darf nicht leer sein",
|
||||||
|
|
||||||
"Unauthorized_postUpdate": "Keine Berechtigung",
|
"NotAllowed_postUpdate": "Keine Berechtigung",
|
||||||
"NotFound_post:postUpdate": "Post nicht gefunden",
|
"NotFound_post:postUpdate": "Post nicht gefunden",
|
||||||
|
|
||||||
"Duplicate_user:register": "Ein Benutzer mit diesem Benutzernamen oder E-Mail existiert schon",
|
"Duplicate_user:register": "Ein Benutzer mit diesem Benutzernamen oder E-Mail existiert schon",
|
||||||
|
|||||||
@ -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",
|
"NotFound_user:login": "User does not exist",
|
||||||
"MissingField_email:login": "E-Mail required",
|
"MissingField_email:login": "E-Mail required",
|
||||||
"MissingField_password:login": "Password required",
|
"MissingField_password:login": "Password required",
|
||||||
|
|
||||||
"Unauthorized_deletPost": "Unauthorized",
|
"NotAllowed_deletPost": "NotAllowed",
|
||||||
"NotFound_post:deletePost": "Post not found",
|
"NotFound_post:deletePost": "Post not found",
|
||||||
|
|
||||||
"Unauthorized_userUpdate": "Unauthorized",
|
"NotAllowed_userUpdate": "NotAllowed",
|
||||||
"NotFound_user:userUpdate": "User not found",
|
"NotFound_user:userUpdate": "User not found",
|
||||||
"FailedUpdate_Duplicate:userUpdate": "A user with this username already exists",
|
"FailedUpdate_Duplicate:userUpdate": "A user with this username already exists",
|
||||||
"FailedUpdate_Duplicate:email:userUpdate": "A user with this email already exists",
|
"FailedUpdate_Duplicate:email:userUpdate": "A user with this email already exists",
|
||||||
|
|
||||||
"Unauthorized_newPost": "Unauthorized",
|
"NotAllowed_newPost": "NotAllowed",
|
||||||
"MissingField_content:newPost": "Content required",
|
"MissingField_content:newPost": "Content required",
|
||||||
|
|
||||||
"Unauthorized_postUpdate": "Unauthorized",
|
"NotAllowed_postUpdate": "NotAllowed",
|
||||||
"NotFound_post:postUpdate": "Post not found",
|
"NotFound_post:postUpdate": "Post not found",
|
||||||
|
|
||||||
"Duplicate_user:register": "A user with this username or email already exists",
|
"Duplicate_user:register": "A user with this username or email already exists",
|
||||||
|
|||||||
@ -44,7 +44,8 @@ class ApiImpl {
|
|||||||
|
|
||||||
public logOut = async (): Promise<boolean> => {
|
public logOut = async (): Promise<boolean> => {
|
||||||
try {
|
try {
|
||||||
return await (await this.postAuth('logout')).json();
|
if (this.token) return await (await this.postAuth('logout')).json();
|
||||||
|
return true;
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@ -19,7 +19,7 @@ const ErrorComponent: FC<Props> = ({ error, context, color = 'error.main' }) =>
|
|||||||
switch (error.code) {
|
switch (error.code) {
|
||||||
case ERRORS.NOT_FOUND:
|
case ERRORS.NOT_FOUND:
|
||||||
return <Typography color={color}>{t(error.code, { context: `${error.entity}:${context}` })}</Typography>;
|
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>;
|
return <Typography color={color}>{t(error.code, { context })}</Typography>;
|
||||||
case ERRORS.FAILED_UPDATE:
|
case ERRORS.FAILED_UPDATE:
|
||||||
return error.fields.map((field: string, index: number) => (
|
return error.fields.map((field: string, index: number) => (
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
export enum ERRORS {
|
export enum ERRORS {
|
||||||
NOT_FOUND = 'NotFound',
|
NOT_FOUND = 'NotFound',
|
||||||
UNAUTHORIZED = 'Unauthorized',
|
UNAUTHORIZED = 'Unauthorized',
|
||||||
|
NOT_ALLOWED = 'NotAllowed',
|
||||||
FAILED_UPDATE = 'FailedUpdate',
|
FAILED_UPDATE = 'FailedUpdate',
|
||||||
MISSING_FIELD = 'MissingField',
|
MISSING_FIELD = 'MissingField',
|
||||||
DUPLICATE = 'Duplicate',
|
DUPLICATE = 'Duplicate',
|
||||||
|
|||||||
@ -71,11 +71,9 @@ const UserMenu: FC<Props> = ({ anchorEl, handleClose }) => {
|
|||||||
</MenuItem>,
|
</MenuItem>,
|
||||||
]
|
]
|
||||||
) : register ? (
|
) : register ? (
|
||||||
<>
|
<RegisterDialog open={register} onClose={() => setRegister(false)} />
|
||||||
<RegisterDialog open={register} onClose={() => setRegister(false)} />
|
|
||||||
</>
|
|
||||||
) : (
|
) : (
|
||||||
<>
|
<Box>
|
||||||
<LoginForm handleClose={_handleClose} />
|
<LoginForm handleClose={_handleClose} />
|
||||||
<Box sx={{ padding: 1 }}>
|
<Box sx={{ padding: 1 }}>
|
||||||
<Trans i18nKey="Register prompt">
|
<Trans i18nKey="Register prompt">
|
||||||
@ -92,7 +90,7 @@ const UserMenu: FC<Props> = ({ anchorEl, handleClose }) => {
|
|||||||
<Typography component="span" />
|
<Typography component="span" />
|
||||||
</Trans>
|
</Trans>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</Box>
|
||||||
)}
|
)}
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
import { QueryClient, QueryClientProvider, useQueryClient, useQueryErrorResetBoundary } from '@tanstack/react-query';
|
||||||
import { RouterProvider, createRouter } from '@tanstack/react-router';
|
import { ErrorRouteComponent, RouterProvider, createRouter, useRouter } from '@tanstack/react-router';
|
||||||
import { StrictMode } from 'react';
|
import { StrictMode, useEffect } from 'react';
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
|
import Api from './api/Api';
|
||||||
|
import { ERRORS } from './components/Error/Errors';
|
||||||
|
|
||||||
// Import the generated route tree
|
// Import the generated route tree
|
||||||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
||||||
@ -19,6 +21,40 @@ import '@fontsource/roboto/700.css';
|
|||||||
// Query Client
|
// Query Client
|
||||||
const queryClient = new QueryClient();
|
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
|
// Create a new router instance
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
routeTree,
|
routeTree,
|
||||||
@ -30,6 +66,7 @@ const router = createRouter({
|
|||||||
// This will ensure that the loader is always called when the route is preloaded or visited
|
// This will ensure that the loader is always called when the route is preloaded or visited
|
||||||
defaultPreloadStaleTime: 0,
|
defaultPreloadStaleTime: 0,
|
||||||
basepath: process.env.NODE_ENV === 'development' ? 'phpCourse/exam/dist' : '/phpCourse/exam',
|
basepath: process.env.NODE_ENV === 'development' ? 'phpCourse/exam/dist' : '/phpCourse/exam',
|
||||||
|
defaultErrorComponent: Error,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Register the router instance for type safety
|
// Register the router instance for type safety
|
||||||
@ -47,7 +84,7 @@ if (!rootElement.innerHTML) {
|
|||||||
<StrictMode>
|
<StrictMode>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
<ReactQueryDevtools initialIsOpen={false} />
|
{process.env.NODE_ENV === 'development' && <ReactQueryDevtools initialIsOpen={false} />}
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,16 +1,10 @@
|
|||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
import { QueryClient, useQueryErrorResetBoundary } from '@tanstack/react-query';
|
import { QueryClient } from '@tanstack/react-query';
|
||||||
import { createRootRouteWithContext, ErrorRouteComponent, Outlet, redirect, useRouter } from '@tanstack/react-router';
|
import { createRootRouteWithContext, Outlet } from '@tanstack/react-router';
|
||||||
import { TanStackRouterDevtools } from '@tanstack/router-devtools';
|
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 Header from '../components/Header/Header';
|
||||||
import { ROUTES } from '../types/Routes';
|
|
||||||
|
|
||||||
const Root = () => {
|
const Root = () => {
|
||||||
//TODO: REAUTH HERE
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header />
|
<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 }>()({
|
export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()({
|
||||||
component: Root,
|
component: Root,
|
||||||
errorComponent: Error,
|
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user