diff --git a/frontend/src/hooks/api/secretSharing/queries.ts b/frontend/src/hooks/api/secretSharing/queries.ts index de9556a09..b697b92b4 100644 --- a/frontend/src/hooks/api/secretSharing/queries.ts +++ b/frontend/src/hooks/api/secretSharing/queries.ts @@ -56,6 +56,9 @@ export const useGetActiveSharedSecretById = ({ params } ); + + if (!data) return null; + return { encryptedValue: data.encryptedValue, password: data.password, @@ -68,7 +71,8 @@ export const useGetActiveSharedSecretById = ({ }); }; -export const fetchIsSecretPasswordValid = async ( +// returns a secret (secret or undefined if password doesn't match) +export const fetchSecretIfPasswordIsValid = async ( sharedSecretId: string, hashedHex: string, password: string, diff --git a/frontend/src/views/ShareSecretPublicPage/components/ShareSecretForm.tsx b/frontend/src/views/ShareSecretPublicPage/components/ShareSecretForm.tsx index f4a647fb2..1a850c07e 100644 --- a/frontend/src/views/ShareSecretPublicPage/components/ShareSecretForm.tsx +++ b/frontend/src/views/ShareSecretPublicPage/components/ShareSecretForm.tsx @@ -156,9 +156,10 @@ export const ShareSecretForm = ({ isPublic, value }: Props) => { name="password" render={({ field, fieldState: { error } }) => ( diff --git a/frontend/src/views/ViewSecretPublicPage/ViewSecretPublicPage.tsx b/frontend/src/views/ViewSecretPublicPage/ViewSecretPublicPage.tsx index 620195910..fecf72659 100644 --- a/frontend/src/views/ViewSecretPublicPage/ViewSecretPublicPage.tsx +++ b/frontend/src/views/ViewSecretPublicPage/ViewSecretPublicPage.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback } from 'react' +import { useState, useCallback, useEffect } from 'react' import Image from "next/image"; import Link from "next/link"; import { useRouter } from "next/router"; @@ -10,7 +10,7 @@ import { useGetActiveSharedSecretById } from "@app/hooks/api/secretSharing"; import { SecretContainer, SecretErrorContainer, PasswordContainer } from "./components"; export const ViewSecretPublicPage = () => { - const [passMatches, setPassMatch] = useState(false) + const [secret, setSecret] = useState(null) const router = useRouter(); const { id, key: urlEncodedPublicKey } = router.query; @@ -18,14 +18,18 @@ export const ViewSecretPublicPage = () => { ? urlEncodedPublicKey.toString().split("-") : ["", ""]; - const { data: secret, error } = useGetActiveSharedSecretById({ + const { data, error } = useGetActiveSharedSecretById({ sharedSecretId: id as string, hashedHex }); - const handlePassMatch = useCallback((val: boolean) => { - setPassMatch(val) - }, [setPassMatch]) + useEffect(() => { + if (data) setSecret(data) + }, [data]) + + const handleSecret = useCallback((val: any) => { + setSecret(val) + }, [setSecret]) return (
@@ -58,13 +62,12 @@ export const ViewSecretPublicPage = () => {

- {secret && ( - !passMatches && secret.password ? ( - + {!secret ? ( + ) : ( key && ) - )} + } {error && }
diff --git a/frontend/src/views/ViewSecretPublicPage/components/PasswordContainer.tsx b/frontend/src/views/ViewSecretPublicPage/components/PasswordContainer.tsx index d3316416e..3ff918f24 100644 --- a/frontend/src/views/ViewSecretPublicPage/components/PasswordContainer.tsx +++ b/frontend/src/views/ViewSecretPublicPage/components/PasswordContainer.tsx @@ -1,43 +1,52 @@ -import { useState, ChangeEvent } from "react"; +import { z } from "zod"; +import { Controller, useForm } from "react-hook-form"; import { faArrowRight, faSpinner } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { zodResolver } from "@hookform/resolvers/zod"; -import { Button, IconButton, Input } from "@app/components/v2"; -import { fetchIsSecretPasswordValid } from "@app/hooks/api/secretSharing"; +import { Button, FormControl, IconButton, Input } from "@app/components/v2"; +import { fetchSecretIfPasswordIsValid } from "@app/hooks/api/secretSharing"; import { createNotification } from "@app/components/notifications"; type Props = { secretId: string; hashedHex: string; - handlePassMatch: (val: boolean) => void; + handleSecret: (val: any) => void; }; -export const PasswordContainer = ({ secretId, hashedHex, handlePassMatch }: Props) => { - const [password, setPassword] = useState('') - const [isLoading, setLoading] = useState(false) +const formSchema = z.object({ + password: z.string() +}) - const handleChange = (e: ChangeEvent) => { - setPassword(e.target.value) - } +export type FormData = z.infer; - const validatePassword = async () => { - setLoading(true); +export const PasswordContainer = ({ secretId, hashedHex, handleSecret }: Props) => { + const { + control, + reset, + handleSubmit, + formState: { isSubmitting } + } = useForm({ + resolver: zodResolver(formSchema), + }); + const onFormSubmit = async ({ password }: FormData) => { try { - const data = await fetchIsSecretPasswordValid( + const secret = await fetchSecretIfPasswordIsValid( secretId, hashedHex, password, ) - if (data?.isValid === true) { - handlePassMatch(true); + if (secret) { + handleSecret(secret); } else { createNotification({ text: "Password is Invalid. Try again", type: "error" }) + reset(); } } catch (error) { console.error("Failed to validate password:", error); @@ -45,31 +54,43 @@ export const PasswordContainer = ({ secretId, hashedHex, handlePassMatch }: Prop text: "Failed to validate password", type: "error" }) - } finally { - setLoading(false); } - } + }; return (
-
- -
- { - validatePassword() - }} - > - - -
-
+
+ ( + +
+ +
+ + + +
+
+
+ )} + /> + +