misc: resolve shared secret within org and added login redirect

This commit is contained in:
Sheen Capadngan
2025-01-10 23:55:21 +08:00
parent 27abfa4fff
commit 502429d914
5 changed files with 79 additions and 7 deletions
@@ -1,10 +1,13 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import { Helmet } from "react-helmet";
import { faArrowRight } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useParams, useSearch } from "@tanstack/react-router";
import { useNavigate, useParams, useSearch } from "@tanstack/react-router";
import { AxiosError } from "axios";
import { addSeconds, formatISO } from "date-fns";
import { createNotification } from "@app/components/notifications";
import { SessionStorageKeys } from "@app/const";
import { ROUTE_PATHS } from "@app/const/routes";
import { useGetActiveSharedSecretById } from "@app/hooks/api/secretSharing";
@@ -36,7 +39,6 @@ export const ViewSharedSecretByIDPage = () => {
select: (el) => el.key
});
const [password, setPassword] = useState<string>();
const { hashedHex, key } = extractDetailsFromUrl(urlEncodedKey);
const {
@@ -50,10 +52,47 @@ export const ViewSharedSecretByIDPage = () => {
password
});
const navigate = useNavigate();
const isUnauthorized =
((error as AxiosError)?.response?.data as { statusCode: number })?.statusCode === 401;
const isForbidden =
((error as AxiosError)?.response?.data as { statusCode: number })?.statusCode === 403;
const isInvalidCredential =
((error as AxiosError)?.response?.data as { message: string })?.message ===
"Invalid credentials";
useEffect(() => {
if (isUnauthorized && !isInvalidCredential) {
// persist current URL in session storage so that we can come back to this after successful login
sessionStorage.setItem(
SessionStorageKeys.ORG_LOGIN_SUCCESS_REDIRECT_URL,
JSON.stringify({
expiry: formatISO(addSeconds(new Date(), 60)),
data: window.location.href
})
);
createNotification({
type: "info",
text: "Login is required in order to access the shared secret."
});
navigate({
to: "/login"
});
}
if (isForbidden) {
createNotification({
type: "error",
text: "You do not have access to this shared secret."
});
}
}, [error]);
const shouldShowPasswordPrompt =
isInvalidCredential || (fetchSecret?.isPasswordProtected && !fetchSecret.secret);
const isValidatingPassword = Boolean(password) && isFetching;
@@ -111,7 +150,7 @@ export const ViewSharedSecretByIDPage = () => {
{!error && fetchSecret?.secret && (
<SecretContainer secret={fetchSecret.secret} secretKey={key} />
)}
{error && !isInvalidCredential && <SecretErrorContainer />}
{error && !isInvalidCredential && !isUnauthorized && <SecretErrorContainer />}
</>
)}
<div className="m-auto my-8 flex w-full">
@@ -2,6 +2,8 @@ import { createFileRoute, stripSearchParams } from "@tanstack/react-router";
import { zodValidator } from "@tanstack/zod-adapter";
import { z } from "zod";
import { authKeys, fetchAuthToken } from "@app/hooks/api/auth/queries";
import { ViewSharedSecretByIDPage } from "./ViewSharedSecretByIDPage";
const SharedSecretByIDPageQuerySchema = z.object({
@@ -9,9 +11,18 @@ const SharedSecretByIDPageQuerySchema = z.object({
});
export const Route = createFileRoute("/shared/secret/$secretId")({
component: ViewSharedSecretByIDPage,
validateSearch: zodValidator(SharedSecretByIDPageQuerySchema),
component: ViewSharedSecretByIDPage,
search: {
middlewares: [stripSearchParams({ key: "" })]
},
beforeLoad: async ({ context }) => {
// we load the auth token because the view shared secret screen serves both public and authenticated users
await context.queryClient
.ensureQueryData({
queryKey: authKeys.getAuthToken,
queryFn: fetchAuthToken
})
.catch(() => undefined);
}
});