mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2025-11-05 16:45:44 +00:00
feat: finalize pages
This commit is contained in:
22
frontend/src/components/ui/code.tsx
Normal file
22
frontend/src/components/ui/code.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
|
interface CodeProps extends React.ComponentPropsWithoutRef<"code"> {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Code({ children, className, ...props }: CodeProps) {
|
||||||
|
return (
|
||||||
|
<code
|
||||||
|
className={twMerge(
|
||||||
|
"relative rounded bg-muted px-[0.2rem] py-[0.1rem] font-mono text-sm font-semibold",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</code>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Code };
|
||||||
@@ -16,7 +16,7 @@ export const OAuthButton = (props: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
className={twMerge("rounded-full", className)}
|
className={twMerge("rounded-md", className)}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"loginTitle": "Welcome back, login with",
|
"loginTitle": "Welcome back, login with",
|
||||||
"loginTitleSimple": "Welcome back, please login",
|
"loginTitleSimple": "Welcome back, please login",
|
||||||
"loginDivider": "Or continue with password",
|
"loginDivider": "Or",
|
||||||
"loginUsername": "Username",
|
"loginUsername": "Username",
|
||||||
"loginPassword": "Password",
|
"loginPassword": "Password",
|
||||||
"loginSubmit": "Login",
|
"loginSubmit": "Login",
|
||||||
"loginFailTitle": "Failed to log in",
|
"loginFailTitle": "Failed to log in",
|
||||||
"loginFailSubtitle": "Please check your username and password",
|
"loginFailSubtitle": "Please check your username and password",
|
||||||
"loginFailRateLimit": "You failed to login too many times, please try again later",
|
"loginFailRateLimit": "You failed to login too many times. Please try again later",
|
||||||
"loginSuccessTitle": "Logged in",
|
"loginSuccessTitle": "Logged in",
|
||||||
"loginSuccessSubtitle": "Welcome back!",
|
"loginSuccessSubtitle": "Welcome back!",
|
||||||
"loginOauthFailTitle": "Internal error",
|
"loginOauthFailTitle": "An error occurred",
|
||||||
"loginOauthFailSubtitle": "Failed to get OAuth URL",
|
"loginOauthFailSubtitle": "Failed to get OAuth URL",
|
||||||
"loginOauthSuccessTitle": "Redirecting",
|
"loginOauthSuccessTitle": "Redirecting",
|
||||||
"loginOauthSuccessSubtitle": "Redirecting to your OAuth provider",
|
"loginOauthSuccessSubtitle": "Redirecting to your OAuth provider",
|
||||||
@@ -19,19 +19,19 @@
|
|||||||
"continueInvalidRedirectTitle": "Invalid redirect",
|
"continueInvalidRedirectTitle": "Invalid redirect",
|
||||||
"continueInvalidRedirectSubtitle": "The redirect URL is invalid",
|
"continueInvalidRedirectSubtitle": "The redirect URL is invalid",
|
||||||
"continueInsecureRedirectTitle": "Insecure redirect",
|
"continueInsecureRedirectTitle": "Insecure redirect",
|
||||||
"continueInsecureRedirectSubtitle": "You are trying to redirect from <code>https</code> to <code>http</code>, are you sure you want to continue?",
|
"continueInsecureRedirectSubtitle": "You are trying to redirect from <code>https</code> to <code>http</code> which is not secure. Are you sure you want to continue?",
|
||||||
"continueTitle": "Continue",
|
"continueTitle": "Continue",
|
||||||
"continueSubtitle": "Click the button to continue to your app.",
|
"continueSubtitle": "Click the button to continue to your app.",
|
||||||
"internalErrorTitle": "Internal Server Error",
|
"internalErrorTitle": "An error occurred",
|
||||||
"internalErrorSubtitle": "An error occurred on the server and it currently cannot serve your request.",
|
"internalErrorSubtitle": "An error occurred in the server and it currently cannot serve your request.",
|
||||||
"internalErrorButton": "Try again",
|
"internalErrorButton": "Try again",
|
||||||
"logoutFailTitle": "Failed to log out",
|
"logoutFailTitle": "Failed to log out",
|
||||||
"logoutFailSubtitle": "Please try again",
|
"logoutFailSubtitle": "Please try again",
|
||||||
"logoutSuccessTitle": "Logged out",
|
"logoutSuccessTitle": "Logged out",
|
||||||
"logoutSuccessSubtitle": "You have been logged out",
|
"logoutSuccessSubtitle": "You have been logged out",
|
||||||
"logoutTitle": "Logout",
|
"logoutTitle": "Logout",
|
||||||
"logoutUsernameSubtitle": "You are currently logged in as <code>{{username}}</code>, click the button below to logout.",
|
"logoutUsernameSubtitle": "You are currently logged in as <code>{{username}}</code>. Click the button below to logout.",
|
||||||
"logoutOauthSubtitle": "You are currently logged in as <code>{{username}}</code> using the {{provider}} OAuth provider, click the button below to logout.",
|
"logoutOauthSubtitle": "You are currently logged in as <code>{{username}}</code> using the {{provider}} OAuth provider. Click the button below to logout.",
|
||||||
"notFoundTitle": "Page not found",
|
"notFoundTitle": "Page not found",
|
||||||
"notFoundSubtitle": "The page you are looking for does not exist.",
|
"notFoundSubtitle": "The page you are looking for does not exist.",
|
||||||
"notFoundButton": "Go home",
|
"notFoundButton": "Go home",
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"loginTitle": "Welcome back, login with",
|
"loginTitle": "Welcome back, login with",
|
||||||
"loginTitleSimple": "Welcome back, please login",
|
"loginTitleSimple": "Welcome back, please login",
|
||||||
"loginDivider": "Or continue with password",
|
"loginDivider": "Or",
|
||||||
"loginUsername": "Username",
|
"loginUsername": "Username",
|
||||||
"loginPassword": "Password",
|
"loginPassword": "Password",
|
||||||
"loginSubmit": "Login",
|
"loginSubmit": "Login",
|
||||||
"loginFailTitle": "Failed to log in",
|
"loginFailTitle": "Failed to log in",
|
||||||
"loginFailSubtitle": "Please check your username and password",
|
"loginFailSubtitle": "Please check your username and password",
|
||||||
"loginFailRateLimit": "You failed to login too many times, please try again later",
|
"loginFailRateLimit": "You failed to login too many times. Please try again later",
|
||||||
"loginSuccessTitle": "Logged in",
|
"loginSuccessTitle": "Logged in",
|
||||||
"loginSuccessSubtitle": "Welcome back!",
|
"loginSuccessSubtitle": "Welcome back!",
|
||||||
"loginOauthFailTitle": "Internal error",
|
"loginOauthFailTitle": "An error occurred",
|
||||||
"loginOauthFailSubtitle": "Failed to get OAuth URL",
|
"loginOauthFailSubtitle": "Failed to get OAuth URL",
|
||||||
"loginOauthSuccessTitle": "Redirecting",
|
"loginOauthSuccessTitle": "Redirecting",
|
||||||
"loginOauthSuccessSubtitle": "Redirecting to your OAuth provider",
|
"loginOauthSuccessSubtitle": "Redirecting to your OAuth provider",
|
||||||
@@ -19,19 +19,19 @@
|
|||||||
"continueInvalidRedirectTitle": "Invalid redirect",
|
"continueInvalidRedirectTitle": "Invalid redirect",
|
||||||
"continueInvalidRedirectSubtitle": "The redirect URL is invalid",
|
"continueInvalidRedirectSubtitle": "The redirect URL is invalid",
|
||||||
"continueInsecureRedirectTitle": "Insecure redirect",
|
"continueInsecureRedirectTitle": "Insecure redirect",
|
||||||
"continueInsecureRedirectSubtitle": "You are trying to redirect from <code>https</code> to <code>http</code>, are you sure you want to continue?",
|
"continueInsecureRedirectSubtitle": "You are trying to redirect from <code>https</code> to <code>http</code> which is not secure. Are you sure you want to continue?",
|
||||||
"continueTitle": "Continue",
|
"continueTitle": "Continue",
|
||||||
"continueSubtitle": "Click the button to continue to your app.",
|
"continueSubtitle": "Click the button to continue to your app.",
|
||||||
"internalErrorTitle": "Internal Server Error",
|
"internalErrorTitle": "An error occurred",
|
||||||
"internalErrorSubtitle": "An error occurred on the server and it currently cannot serve your request.",
|
"internalErrorSubtitle": "An error occurred in the server and it currently cannot serve your request.",
|
||||||
"internalErrorButton": "Try again",
|
"internalErrorButton": "Try again",
|
||||||
"logoutFailTitle": "Failed to log out",
|
"logoutFailTitle": "Failed to log out",
|
||||||
"logoutFailSubtitle": "Please try again",
|
"logoutFailSubtitle": "Please try again",
|
||||||
"logoutSuccessTitle": "Logged out",
|
"logoutSuccessTitle": "Logged out",
|
||||||
"logoutSuccessSubtitle": "You have been logged out",
|
"logoutSuccessSubtitle": "You have been logged out",
|
||||||
"logoutTitle": "Logout",
|
"logoutTitle": "Logout",
|
||||||
"logoutUsernameSubtitle": "You are currently logged in as <code>{{username}}</code>, click the button below to logout.",
|
"logoutUsernameSubtitle": "You are currently logged in as <code>{{username}}</code>. Click the button below to logout.",
|
||||||
"logoutOauthSubtitle": "You are currently logged in as <code>{{username}}</code> using the {{provider}} OAuth provider, click the button below to logout.",
|
"logoutOauthSubtitle": "You are currently logged in as <code>{{username}}</code> using the {{provider}} OAuth provider. Click the button below to logout.",
|
||||||
"notFoundTitle": "Page not found",
|
"notFoundTitle": "Page not found",
|
||||||
"notFoundSubtitle": "The page you are looking for does not exist.",
|
"notFoundSubtitle": "The page you are looking for does not exist.",
|
||||||
"notFoundButton": "Go home",
|
"notFoundButton": "Go home",
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ import { ErrorPage } from "./pages/error-page.tsx";
|
|||||||
import { NotFoundPage } from "./pages/not-found-page.tsx";
|
import { NotFoundPage } from "./pages/not-found-page.tsx";
|
||||||
import { ContinuePage } from "./pages/continue-page.tsx";
|
import { ContinuePage } from "./pages/continue-page.tsx";
|
||||||
import { TotpPage } from "./pages/totp-page.tsx";
|
import { TotpPage } from "./pages/totp-page.tsx";
|
||||||
import { ForgotPasswordPage } from "./pages/forgot-password.tsx";
|
import { ForgotPasswordPage } from "./pages/forgot-password-page.tsx";
|
||||||
|
import { LogoutPage } from "./pages/logout-page.tsx";
|
||||||
|
import { UnauthorizedPage } from "./pages/unauthorized-page.tsx";
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
@@ -22,6 +24,11 @@ const router = createBrowserRouter([
|
|||||||
element: <LoginPage />,
|
element: <LoginPage />,
|
||||||
errorElement: <ErrorPage />,
|
errorElement: <ErrorPage />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/logout",
|
||||||
|
element: <LogoutPage />,
|
||||||
|
errorElement: <ErrorPage />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/continue",
|
path: "/continue",
|
||||||
element: <ContinuePage />,
|
element: <ContinuePage />,
|
||||||
@@ -37,6 +44,11 @@ const router = createBrowserRouter([
|
|||||||
element: <ForgotPasswordPage />,
|
element: <ForgotPasswordPage />,
|
||||||
errorElement: <ErrorPage />,
|
errorElement: <ErrorPage />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/unauthorized",
|
||||||
|
element: <UnauthorizedPage />,
|
||||||
|
errorElement: <ErrorPage />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "*",
|
path: "*",
|
||||||
element: <NotFoundPage />,
|
element: <NotFoundPage />,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/ui/card";
|
||||||
|
import { Code } from "@/components/ui/code";
|
||||||
import { isValidUrl } from "@/lib/utils";
|
import { isValidUrl } from "@/lib/utils";
|
||||||
import { Trans, useTranslation } from "react-i18next";
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
import { Navigate, useNavigate } from "react-router";
|
import { Navigate, useNavigate } from "react-router";
|
||||||
@@ -47,9 +48,7 @@ export const ContinuePage = () => {
|
|||||||
i18nKey="untrustedRedirectSubtitle"
|
i18nKey="untrustedRedirectSubtitle"
|
||||||
t={t}
|
t={t}
|
||||||
components={{
|
components={{
|
||||||
code: (
|
code: <Code />,
|
||||||
<code className="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold" />
|
|
||||||
),
|
|
||||||
}}
|
}}
|
||||||
values={{ domain }}
|
values={{ domain }}
|
||||||
/>
|
/>
|
||||||
@@ -82,9 +81,7 @@ export const ContinuePage = () => {
|
|||||||
i18nKey="continueInsecureRedirectSubtitle"
|
i18nKey="continueInsecureRedirectSubtitle"
|
||||||
t={t}
|
t={t}
|
||||||
components={{
|
components={{
|
||||||
code: (
|
code: <Code />,
|
||||||
<code className="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold" />
|
|
||||||
),
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
@@ -105,7 +102,7 @@ export const ContinuePage = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="min-w-xs md:max-w-sm">
|
<Card className="min-w-xs sm:min-w-sm">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-3xl">{t("continueTitle")}</CardTitle>
|
<CardTitle className="text-3xl">{t("continueTitle")}</CardTitle>
|
||||||
<CardDescription>{t("continueSubtitle")}</CardDescription>
|
<CardDescription>{t("continueSubtitle")}</CardDescription>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const ErrorPage = () => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="min-w-xs md:max-w-sm">
|
<Card className="min-w-xs sm:min-w-sm">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-3xl">{t("errorTitle")}</CardTitle>
|
<CardTitle className="text-3xl">{t("errorTitle")}</CardTitle>
|
||||||
<CardDescription>{t("errorSubtitle")}</CardDescription>
|
<CardDescription>{t("errorSubtitle")}</CardDescription>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const ForgotPasswordPage = () => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="min-w-xs md:max-w-sm">
|
<Card className="min-w-xs sm:min-w-sm">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-3xl">{t("forgotPasswordTitle")}</CardTitle>
|
<CardTitle className="text-3xl">{t("forgotPasswordTitle")}</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
@@ -24,7 +24,7 @@ export const LoginPage = () => {
|
|||||||
const userAuthConfigured = configuredProviders.includes("username");
|
const userAuthConfigured = configuredProviders.includes("username");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="max-w-xs md:max-w-sm">
|
<Card className="min-w-xs sm:min-w-sm">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-center text-3xl">{title}</CardTitle>
|
<CardTitle className="text-center text-3xl">{title}</CardTitle>
|
||||||
{configuredProviders.length > 0 && (
|
{configuredProviders.length > 0 && (
|
||||||
@@ -33,17 +33,29 @@ export const LoginPage = () => {
|
|||||||
</CardDescription>
|
</CardDescription>
|
||||||
)}
|
)}
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex flex-col gap-5">
|
<CardContent className="flex flex-col gap-4">
|
||||||
{oauthConfigured && (
|
{oauthConfigured && (
|
||||||
<div className="flex flex-row flex-wrap gap-3 items-center justify-center">
|
<div className="flex flex-col gap-2 items-center justify-center">
|
||||||
{configuredProviders.includes("google") && (
|
{configuredProviders.includes("google") && (
|
||||||
<OAuthButton title="Google" icon={<GoogleIcon />} />
|
<OAuthButton
|
||||||
|
title="Google"
|
||||||
|
icon={<GoogleIcon />}
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{configuredProviders.includes("github") && (
|
{configuredProviders.includes("github") && (
|
||||||
<OAuthButton title="Github" icon={<GithubIcon />} />
|
<OAuthButton
|
||||||
|
title="Github"
|
||||||
|
icon={<GithubIcon />}
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{configuredProviders.includes("generic") && (
|
{configuredProviders.includes("generic") && (
|
||||||
<OAuthButton title="Generic" icon={<GenericIcon />} />
|
<OAuthButton
|
||||||
|
title="Generic"
|
||||||
|
icon={<GenericIcon />}
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
58
frontend/src/pages/logout-page.tsx
Normal file
58
frontend/src/pages/logout-page.tsx
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
|
import { Code } from "@/components/ui/code";
|
||||||
|
import { capitalize } from "@/utils/utils";
|
||||||
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
export const LogoutPage = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const provider = "google";
|
||||||
|
const genericName = "generic";
|
||||||
|
const username = "username";
|
||||||
|
const email = "smbd@example.com";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="min-w-xs sm:min-w-sm">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="text-3xl">{t("logoutTitle")}</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
{provider !== "username" ? (
|
||||||
|
<Trans
|
||||||
|
i18nKey="logoutOauthSubtitle"
|
||||||
|
t={t}
|
||||||
|
components={{
|
||||||
|
code: <Code />,
|
||||||
|
}}
|
||||||
|
values={{
|
||||||
|
username: email,
|
||||||
|
provider:
|
||||||
|
provider === "generic" ? genericName : capitalize(provider),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Trans
|
||||||
|
i18nKey="logoutUsernameSubtitle"
|
||||||
|
t={t}
|
||||||
|
components={{
|
||||||
|
code: <Code />,
|
||||||
|
}}
|
||||||
|
values={{
|
||||||
|
username: username,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardFooter className="flex flex-col items-stretch">
|
||||||
|
<Button>{t("logoutTitle")}</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -14,7 +14,7 @@ export const NotFoundPage = () => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="min-w-xs md:max-w-sm">
|
<Card className="min-w-xs sm:min-w-sm">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-3xl">{t("notFoundTitle")}</CardTitle>
|
<CardTitle className="text-3xl">{t("notFoundTitle")}</CardTitle>
|
||||||
<CardDescription>{t("notFoundSubtitle")}</CardDescription>
|
<CardDescription>{t("notFoundSubtitle")}</CardDescription>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export const TotpPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="min-w-xs md:max-w-sm">
|
<Card className="min-w-xs sm:min-w-sm">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-3xl">{t("totpTitle")}</CardTitle>
|
<CardTitle className="text-3xl">{t("totpTitle")}</CardTitle>
|
||||||
<CardDescription>{t("totpSubtitle")}</CardDescription>
|
<CardDescription>{t("totpSubtitle")}</CardDescription>
|
||||||
|
|||||||
60
frontend/src/pages/unauthorized-page.tsx
Normal file
60
frontend/src/pages/unauthorized-page.tsx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
|
import { Code } from "@/components/ui/code";
|
||||||
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
|
import { Navigate } from "react-router";
|
||||||
|
|
||||||
|
export const UnauthorizedPage = () => {
|
||||||
|
const searchParams = new URLSearchParams(window.location.search);
|
||||||
|
const username = searchParams.get("username");
|
||||||
|
const resource = searchParams.get("resource");
|
||||||
|
const groupErr = searchParams.get("groupErr");
|
||||||
|
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
if (!username) {
|
||||||
|
return <Navigate to="/" />;
|
||||||
|
}
|
||||||
|
|
||||||
|
let i18nKey = "unaothorizedLoginSubtitle";
|
||||||
|
|
||||||
|
if (resource) {
|
||||||
|
i18nKey = "unauthorizedResourceSubtitle";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupErr === "true") {
|
||||||
|
i18nKey = "unauthorizedGroupsSubtitle";
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="min-w-xs sm:min-w-sm">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="text-3xl">{t("unauthorizedTitle")}</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
<Trans
|
||||||
|
i18nKey={i18nKey}
|
||||||
|
t={t}
|
||||||
|
components={{
|
||||||
|
code: <Code />,
|
||||||
|
}}
|
||||||
|
values={{
|
||||||
|
username: username,
|
||||||
|
resource: resource,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardFooter className="flex flex-col items-stretch">
|
||||||
|
<Button onClick={() => window.location.replace("/")}>
|
||||||
|
{t("unauthorizedButton")}
|
||||||
|
</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
3
frontend/src/utils/utils.ts
Normal file
3
frontend/src/utils/utils.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export const capitalize = (str: string) => {
|
||||||
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user