refactor: rework hooks usage

This commit is contained in:
Stavros
2025-09-01 16:41:12 +03:00
parent 3873bb279c
commit 4ef5eef167
8 changed files with 100 additions and 80 deletions

View File

@@ -1,7 +1,7 @@
import { useAppContext } from "@/context/app-context";
import { LanguageSelector } from "../language/language";
import { Outlet } from "react-router";
import { useState } from "react";
import { useCallback, useState } from "react";
import { DomainWarning } from "../domain-warning/domain-warning";
const BaseLayout = ({ children }: { children: React.ReactNode }) => {
@@ -24,20 +24,17 @@ const BaseLayout = ({ children }: { children: React.ReactNode }) => {
export const Layout = () => {
const { appUrl } = useAppContext();
const [ignoreDomainWarning, setIgnoreDomainWarning] = useState(false);
const [ignoreDomainWarning, setIgnoreDomainWarning] = useState(() => {
return window.sessionStorage.getItem("ignoreDomainWarning") === "true";
});
const currentUrl = window.location.origin;
const sessionIgnore = window.sessionStorage.getItem("ignoreDomainWarning");
const handleIgnore = () => {
const handleIgnore = useCallback(() => {
window.sessionStorage.setItem("ignoreDomainWarning", "true");
setIgnoreDomainWarning(true);
};
}, [setIgnoreDomainWarning]);
if (
!ignoreDomainWarning &&
appUrl !== currentUrl &&
sessionIgnore !== "true"
) {
if (!ignoreDomainWarning && appUrl !== currentUrl) {
return (
<BaseLayout>
<DomainWarning

View File

@@ -14,6 +14,7 @@
"loginOauthFailSubtitle": "Failed to get OAuth URL",
"loginOauthSuccessTitle": "Redirecting",
"loginOauthSuccessSubtitle": "Redirecting to your OAuth provider",
"continueTitle": "Continue",
"continueRedirectingTitle": "Redirecting...",
"continueRedirectingSubtitle": "You should be redirected to the app soon",
"continueRedirectManually": "Redirect me manually",

View File

@@ -14,6 +14,7 @@
"loginOauthFailSubtitle": "Failed to get OAuth URL",
"loginOauthSuccessTitle": "Redirecting",
"loginOauthSuccessSubtitle": "Redirecting to your OAuth provider",
"continueTitle": "Continue",
"continueRedirectingTitle": "Redirecting...",
"continueRedirectingSubtitle": "You should be redirected to the app soon",
"continueRedirectManually": "Redirect me manually",

View File

@@ -15,42 +15,68 @@ import DOMPurify from "dompurify";
import { useEffect, useState } from "react";
export const ContinuePage = () => {
const { rootDomain } = useAppContext();
const { isLoggedIn } = useUserContext();
const { search } = useLocation();
const { t } = useTranslation();
const navigate = useNavigate();
const [loading, setLoading] = useState(false);
const [showRedirectButton, setShowRedirectButton] = useState(false);
const searchParams = new URLSearchParams(search);
const redirectUri = searchParams.get("redirect_uri");
const isValidRedirectUri =
redirectUri !== null ? isValidUrl(DOMPurify.sanitize(redirectUri)) : false;
const redirectUriObj = isValidRedirectUri
? new URL(redirectUri as string)
: null;
const isTrustedRedirectUri =
redirectUriObj !== null
? redirectUriObj.hostname === rootDomain ||
redirectUriObj.hostname.endsWith(`.${rootDomain}`)
: false;
const isHttpsDowngrade =
redirectUriObj !== null
? redirectUriObj.protocol === "http:" &&
window.location.protocol === "https:"
: false;
const handleRedirect = () => {
setLoading(true);
window.location.replace(DOMPurify.sanitize(redirectUriObj!.toString()));
};
useEffect(() => {
if (
!isLoggedIn ||
!isValidRedirectUri ||
!isTrustedRedirectUri ||
isHttpsDowngrade
) {
return;
}
setTimeout(() => {
handleRedirect();
}, 100);
setTimeout(() => {
setLoading(false);
setShowRedirectButton(true);
}, 1000);
}, []);
if (!isLoggedIn) {
return <Navigate to="/login" />;
}
const { rootDomain } = useAppContext();
const { search } = useLocation();
const [loading, setLoading] = useState(false);
const [showRedirectButton, setShowRedirectButton] = useState(false);
const searchParams = new URLSearchParams(search);
const redirectURI = searchParams.get("redirect_uri");
if (!redirectURI) {
if (!isValidRedirectUri) {
return <Navigate to="/logout" />;
}
if (!isValidUrl(DOMPurify.sanitize(redirectURI))) {
return <Navigate to="/logout" />;
}
const { t } = useTranslation();
const navigate = useNavigate();
const handleRedirect = () => {
setLoading(true);
window.location.href = DOMPurify.sanitize(redirectURI);
};
const redirectURLObj = new URL(redirectURI);
if (
!(redirectURLObj.hostname == rootDomain) &&
!redirectURLObj.hostname.endsWith(`.${rootDomain}`)
) {
if (!isTrustedRedirectUri) {
return (
<Card className="min-w-xs sm:min-w-sm">
<CardHeader>
@@ -88,10 +114,7 @@ export const ContinuePage = () => {
);
}
if (
redirectURLObj.protocol === "http:" &&
window.location.protocol === "https:"
) {
if (isHttpsDowngrade) {
return (
<Card className="min-w-xs sm:min-w-sm">
<CardHeader>
@@ -124,16 +147,6 @@ export const ContinuePage = () => {
);
}
useEffect(() => {
setTimeout(() => {
handleRedirect();
}, 100);
setTimeout(() => {
setLoading(false);
setShowRedirectButton(true);
}, 1000);
}, []);
return (
<Card className="min-w-xs sm:min-w-sm">
<CardHeader>

View File

@@ -24,12 +24,8 @@ import { toast } from "sonner";
export const LoginPage = () => {
const { isLoggedIn } = useUserContext();
if (isLoggedIn) {
return <Navigate to="/logout" />;
}
const { configuredProviders, title, oauthAutoRedirect, genericName } = useAppContext();
const { configuredProviders, title, oauthAutoRedirect, genericName } =
useAppContext();
const { search } = useLocation();
const { t } = useTranslation();
const isMounted = useIsMounted();
@@ -54,7 +50,7 @@ export const LoginPage = () => {
});
setTimeout(() => {
window.location.href = data.data.url;
window.location.replace(data.data.url);
}, 500);
},
onError: () => {
@@ -100,6 +96,7 @@ export const LoginPage = () => {
if (
oauthConfigured &&
configuredProviders.includes(oauthAutoRedirect) &&
!isLoggedIn &&
redirectUri
) {
oauthMutation.mutate(oauthAutoRedirect);
@@ -107,6 +104,10 @@ export const LoginPage = () => {
}
}, []);
if (isLoggedIn) {
return <Navigate to="/logout" />;
}
return (
<Card className="min-w-xs sm:min-w-sm">
<CardHeader>
@@ -126,7 +127,10 @@ export const LoginPage = () => {
icon={<GoogleIcon />}
className="w-full"
onClick={() => oauthMutation.mutate("google")}
loading={oauthMutation.isPending && oauthMutation.variables === "google"}
loading={
oauthMutation.isPending &&
oauthMutation.variables === "google"
}
disabled={oauthMutation.isPending || loginMutation.isPending}
/>
)}
@@ -136,7 +140,10 @@ export const LoginPage = () => {
icon={<GithubIcon />}
className="w-full"
onClick={() => oauthMutation.mutate("github")}
loading={oauthMutation.isPending && oauthMutation.variables === "github"}
loading={
oauthMutation.isPending &&
oauthMutation.variables === "github"
}
disabled={oauthMutation.isPending || loginMutation.isPending}
/>
)}
@@ -146,7 +153,10 @@ export const LoginPage = () => {
icon={<GenericIcon />}
className="w-full"
onClick={() => oauthMutation.mutate("generic")}
loading={oauthMutation.isPending && oauthMutation.variables === "generic"}
loading={
oauthMutation.isPending &&
oauthMutation.variables === "generic"
}
disabled={oauthMutation.isPending || loginMutation.isPending}
/>
)}

View File

@@ -17,11 +17,6 @@ import { toast } from "sonner";
export const LogoutPage = () => {
const { provider, username, isLoggedIn, email } = useUserContext();
if (!isLoggedIn) {
return <Navigate to="/login" />;
}
const { genericName } = useAppContext();
const { t } = useTranslation();
@@ -33,7 +28,7 @@ export const LogoutPage = () => {
description: t("logoutSuccessSubtitle"),
});
setTimeout(async () => {
setTimeout(() => {
window.location.replace("/login");
}, 500);
},
@@ -44,6 +39,10 @@ export const LogoutPage = () => {
},
});
if (!isLoggedIn) {
return <Navigate to="/login" />;
}
return (
<Card className="min-w-xs sm:min-w-sm">
<CardHeader>

View File

@@ -19,11 +19,6 @@ import { toast } from "sonner";
export const TotpPage = () => {
const { totpPending } = useUserContext();
if (!totpPending) {
return <Navigate to="/" />;
}
const { t } = useTranslation();
const { search } = useLocation();
const formId = useId();
@@ -52,6 +47,10 @@ export const TotpPage = () => {
},
});
if (!totpPending) {
return <Navigate to="/" />;
}
return (
<Card className="min-w-xs sm:min-w-sm">
<CardHeader>

View File

@@ -12,6 +12,10 @@ import { Navigate, useLocation, useNavigate } from "react-router";
export const UnauthorizedPage = () => {
const { search } = useLocation();
const { t } = useTranslation();
const navigate = useNavigate();
const [loading, setLoading] = useState(false);
const searchParams = new URLSearchParams(search);
const username = searchParams.get("username");
@@ -19,19 +23,15 @@ export const UnauthorizedPage = () => {
const groupErr = searchParams.get("groupErr");
const ip = searchParams.get("ip");
if (!username && !ip) {
return <Navigate to="/" />;
}
const { t } = useTranslation();
const navigate = useNavigate();
const [loading, setLoading] = useState(false);
const handleRedirect = () => {
setLoading(true);
navigate("/login");
};
if (!username && !ip) {
return <Navigate to="/" />;
}
let i18nKey = "unauthorizedLoginSubtitle";
if (resource) {