diff --git a/frontend/src/components/v2/EmptyState/EmptyState.tsx b/frontend/src/components/v2/EmptyState/EmptyState.tsx index e285500c1..9816a3fe2 100644 --- a/frontend/src/components/v2/EmptyState/EmptyState.tsx +++ b/frontend/src/components/v2/EmptyState/EmptyState.tsx @@ -21,7 +21,7 @@ export const EmptyState = ({ }: Props) => (
diff --git a/frontend/src/hooks/api/secretSharing/queries.ts b/frontend/src/hooks/api/secretSharing/queries.ts index 886b0a82e..44b2c3193 100644 --- a/frontend/src/hooks/api/secretSharing/queries.ts +++ b/frontend/src/hooks/api/secretSharing/queries.ts @@ -2,7 +2,7 @@ import { useQuery } from "@tanstack/react-query"; import { apiRequest } from "@app/config/request"; -import { TSharedSecret, TViewSharedSecretResponse } from "./types"; +import { SecretSharingAccessType, TSharedSecret, TViewSharedSecretResponse } from "./types"; export const useGetSharedSecrets = () => { return useQuery({ @@ -17,7 +17,7 @@ export const useGetSharedSecrets = () => { export const useGetActiveSharedSecretByIdAndHashedHex = (id: string, hashedHex: string) => { return useQuery({ queryFn: async () => { - if(!id || !hashedHex) return Promise.resolve({ encryptedValue: "", iv: "", tag: "" }); + if(!id || !hashedHex) return Promise.resolve({ encryptedValue: "", iv: "", tag: "", accessType: SecretSharingAccessType.Organization, orgName: "" }); const { data } = await apiRequest.get( `/api/v1/secret-sharing/public/${id}?hashedHex=${hashedHex}` ); @@ -25,6 +25,8 @@ export const useGetActiveSharedSecretByIdAndHashedHex = (id: string, hashedHex: encryptedValue: data.encryptedValue, iv: data.iv, tag: data.tag, + accessType: data.accessType, + orgName: data.orgName }; } }); diff --git a/frontend/src/hooks/api/secretSharing/types.ts b/frontend/src/hooks/api/secretSharing/types.ts index 424e3525c..69c0d9a65 100644 --- a/frontend/src/hooks/api/secretSharing/types.ts +++ b/frontend/src/hooks/api/secretSharing/types.ts @@ -13,14 +13,22 @@ export type TCreateSharedSecretRequest = { hashedHex: string; expiresAt: Date; expiresAfterViews: number; + accessType: SecretSharingAccessType; }; export type TViewSharedSecretResponse = { encryptedValue: string; iv: string; tag: string; + accessType: SecretSharingAccessType; + orgName?: string; }; export type TDeleteSharedSecretRequest = { sharedSecretId: string; }; + +export enum SecretSharingAccessType { + Anyone = "anyone", + Organization = "organization" +} \ No newline at end of file diff --git a/frontend/src/views/ShareSecretPage/components/AddShareSecretForm.tsx b/frontend/src/views/ShareSecretPage/components/AddShareSecretForm.tsx index 4e950dc3f..bbc896460 100644 --- a/frontend/src/views/ShareSecretPage/components/AddShareSecretForm.tsx +++ b/frontend/src/views/ShareSecretPage/components/AddShareSecretForm.tsx @@ -7,13 +7,14 @@ import * as yup from "yup"; import { createNotification } from "@app/components/notifications"; import { encryptSymmetric } from "@app/components/utilities/cryptography/crypto"; import { Button, Checkbox, FormControl, Input, ModalClose, Select, SelectItem } from "@app/components/v2"; -import { useCreatePublicSharedSecret, useCreateSharedSecret } from "@app/hooks/api/secretSharing"; +import { SecretSharingAccessType, useCreatePublicSharedSecret, useCreateSharedSecret } from "@app/hooks/api/secretSharing"; const schema = yup.object({ value: yup.string().max(10000).required().label("Shared Secret Value"), expiresAfterSingleView: yup.boolean().required().label("Expires After Views"), expiresInValue: yup.number().min(1).required().label("Expiration Value"), - expiresInUnit: yup.string().required().label("Expiration Unit") + expiresInUnit: yup.string().required().label("Expiration Unit"), + accessType: yup.string().required().label("General Access") }); export type FormData = yup.InferType; @@ -65,7 +66,8 @@ export const AddShareSecretForm = ({ value, expiresInValue, expiresInUnit, - expiresAfterSingleView + expiresAfterSingleView, + accessType }: FormData) => { try { const key = crypto.randomBytes(16).toString("hex"); @@ -89,7 +91,8 @@ export const AddShareSecretForm = ({ tag, hashedHex, expiresAt, - expiresAfterViews: expiresAfterSingleView ? 1 : 1000 + expiresAfterViews: expiresAfterSingleView ? 1 : 1000, + accessType: accessType as SecretSharingAccessType }); setNewSharedSecret( `${window.location.origin}/shared/secret/${id}?key=${encodeURIComponent( @@ -143,7 +146,7 @@ export const AddShareSecretForm = ({ )} />
-
+
@@ -188,8 +191,8 @@ export const AddShareSecretForm = ({
-
-

AND

+
+

AND

-
+ ( + + + + )} + /> +
diff --git a/frontend/src/views/ShareSecretPublicPage/ShareSecretPublicPage.tsx b/frontend/src/views/ShareSecretPublicPage/ShareSecretPublicPage.tsx index 2f468e2b9..bff190389 100644 --- a/frontend/src/views/ShareSecretPublicPage/ShareSecretPublicPage.tsx +++ b/frontend/src/views/ShareSecretPublicPage/ShareSecretPublicPage.tsx @@ -20,12 +20,15 @@ export const ShareSecretPublicPage = ({ isNewSession }: { isNewSession: boolean const [hashedHex, key] = urlEncodedPublicKey ? urlEncodedPublicKey.toString().split("-") : ["", ""]; - + const publicKey = decodeURIComponent(urlEncodedPublicKey as string); const { isLoading, data } = useGetActiveSharedSecretByIdAndHashedHex( id as string, hashedHex as string ); + console.log(data); + const accessType = data?.accessType; + const orgName = data?.orgName; const decryptedSecret = useMemo(() => { if (data && data.encryptedValue && publicKey) { @@ -87,6 +90,8 @@ export const ShareSecretPublicPage = ({ isNewSession }: { isNewSession: boolean decryptedSecret={decryptedSecret} isUrlCopied={isUrlCopied} copyUrlToClipboard={copyUrlToClipboard} + accessType={accessType} + orgName={orgName} /> )}
diff --git a/frontend/src/views/ShareSecretPublicPage/components/SecretTable.tsx b/frontend/src/views/ShareSecretPublicPage/components/SecretTable.tsx index f33f958af..ae5a4faae 100644 --- a/frontend/src/views/ShareSecretPublicPage/components/SecretTable.tsx +++ b/frontend/src/views/ShareSecretPublicPage/components/SecretTable.tsx @@ -1,14 +1,17 @@ -import { faCheck, faCopy, faEye, faEyeSlash, faKey } from "@fortawesome/free-solid-svg-icons"; +import { faArrowRight, faCheck, faCopy, faEye, faEyeSlash, faKey } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { EmptyState, IconButton, Td, Tr } from "@app/components/v2"; +import { Button, EmptyState, IconButton, Td, Tr } from "@app/components/v2"; import { useToggle } from "@app/hooks"; +import { SecretSharingAccessType } from "@app/hooks/api/secretSharing/types"; type Props = { isLoading: boolean; decryptedSecret: string; isUrlCopied: boolean; copyUrlToClipboard: () => void; + accessType?: SecretSharingAccessType; + orgName?: string; }; const replaceContentWithDot = (str: string) => { @@ -24,20 +27,47 @@ export const SecretTable = ({ isLoading, decryptedSecret, isUrlCopied, - copyUrlToClipboard + copyUrlToClipboard, + accessType, + orgName }: Props) => { const [isVisible, setIsVisible] = useToggle(false); + const title = (

You need to be logged into {orgName} to access this secret

); return (
{isLoading &&
Loading...
} - {!isLoading && !decryptedSecret && ( + {!isLoading && !decryptedSecret && accessType !== SecretSharingAccessType.Organization && ( )} + {!isLoading && !decryptedSecret && accessType === SecretSharingAccessType.Organization && ( + + + + + + + + )} {!isLoading && decryptedSecret && (