From a30e3874cdb11b90025b0ab0b8b19209aacb4cc7 Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Sat, 27 Jul 2024 07:31:30 -0700 Subject: [PATCH 1/2] Adjustments to secret sharing styling --- .../server/routes/v1/secret-sharing-router.ts | 8 +- .../secret-sharing/secret-sharing-service.ts | 5 +- .../secret-sharing/secret-sharing-types.ts | 4 +- frontend/src/hooks/api/secretSharing/types.ts | 4 +- .../components/AddShareSecretForm.tsx | 210 +++++++----------- .../components/AddShareSecretModal.tsx | 5 +- .../components/ShareSecretSection.tsx | 3 +- .../components/ShareSecretsRow.tsx | 112 +--------- .../components/ShareSecretsTable.tsx | 29 +-- .../ShareSecretPublicPage.tsx | 5 +- 10 files changed, 114 insertions(+), 271 deletions(-) diff --git a/backend/src/server/routes/v1/secret-sharing-router.ts b/backend/src/server/routes/v1/secret-sharing-router.ts index d5c6a9884..a53f879dd 100644 --- a/backend/src/server/routes/v1/secret-sharing-router.ts +++ b/backend/src/server/routes/v1/secret-sharing-router.ts @@ -95,7 +95,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) => tag: z.string(), hashedHex: z.string(), expiresAt: z.string(), - expiresAfterViews: z.number() + expiresAfterViews: z.number().optional() }), response: { 200: z.object({ @@ -110,7 +110,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) => iv, tag, hashedHex, - expiresAt: new Date(expiresAt), + expiresAt, expiresAfterViews, accessType: SecretSharingAccessType.Anyone }); @@ -131,7 +131,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) => tag: z.string(), hashedHex: z.string(), expiresAt: z.string(), - expiresAfterViews: z.number(), + expiresAfterViews: z.number().optional(), accessType: z.nativeEnum(SecretSharingAccessType).default(SecretSharingAccessType.Organization) }), response: { @@ -153,7 +153,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) => iv, tag, hashedHex, - expiresAt: new Date(expiresAt), + expiresAt, expiresAfterViews, accessType: req.body.accessType }); diff --git a/backend/src/services/secret-sharing/secret-sharing-service.ts b/backend/src/services/secret-sharing/secret-sharing-service.ts index ca6da24e1..da2f52534 100644 --- a/backend/src/services/secret-sharing/secret-sharing-service.ts +++ b/backend/src/services/secret-sharing/secret-sharing-service.ts @@ -64,12 +64,13 @@ export const secretSharingServiceFactory = ({ iv, tag, hashedHex, - expiresAt, + expiresAt: new Date(expiresAt), expiresAfterViews, userId: actorId, orgId, accessType }); + return { id: newSharedSecret.id }; }; @@ -97,7 +98,7 @@ export const secretSharingServiceFactory = ({ iv, tag, hashedHex, - expiresAt, + expiresAt: new Date(expiresAt), expiresAfterViews, accessType }); diff --git a/backend/src/services/secret-sharing/secret-sharing-types.ts b/backend/src/services/secret-sharing/secret-sharing-types.ts index a9c7dcbd9..bb0e19d5b 100644 --- a/backend/src/services/secret-sharing/secret-sharing-types.ts +++ b/backend/src/services/secret-sharing/secret-sharing-types.ts @@ -16,8 +16,8 @@ export type TCreatePublicSharedSecretDTO = { iv: string; tag: string; hashedHex: string; - expiresAt: Date; - expiresAfterViews: number; + expiresAt: string; + expiresAfterViews?: number; accessType: SecretSharingAccessType; }; diff --git a/frontend/src/hooks/api/secretSharing/types.ts b/frontend/src/hooks/api/secretSharing/types.ts index 69c0d9a65..3a9576e1e 100644 --- a/frontend/src/hooks/api/secretSharing/types.ts +++ b/frontend/src/hooks/api/secretSharing/types.ts @@ -12,7 +12,7 @@ export type TCreateSharedSecretRequest = { tag: string; hashedHex: string; expiresAt: Date; - expiresAfterViews: number; + expiresAfterViews?: number; accessType: SecretSharingAccessType; }; @@ -31,4 +31,4 @@ export type TDeleteSharedSecretRequest = { 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 47da21693..b94f52387 100644 --- a/frontend/src/views/ShareSecretPage/components/AddShareSecretForm.tsx +++ b/frontend/src/views/ShareSecretPage/components/AddShareSecretForm.tsx @@ -7,19 +7,38 @@ 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 { SecretSharingAccessType, useCreatePublicSharedSecret, useCreateSharedSecret } from "@app/hooks/api/secretSharing"; +import { Button, FormControl, ModalClose, Select, SelectItem } from "@app/components/v2"; +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"), + expiresAfterViews: yup.string().required().label("Expires After Views"), + expiresInValue: yup.string().min(1).required().label("Expiration Value"), accessType: yup.string().required().label("General Access") }); export type FormData = yup.InferType; +// values in ms +const expiresInOptions = [ + { label: "5 min", value: 5 * 60 * 1000 }, + { label: "30 min", value: 30 * 60 * 1000 }, + { label: "1 hour", value: 60 * 60 * 1000 }, + { label: "1 day", value: 24 * 60 * 60 * 1000 }, + { label: "7 days", value: 7 * 24 * 60 * 60 * 1000 }, + { label: "14 days", value: 14 * 24 * 60 * 60 * 1000 }, + { label: "30 days", value: 30 * 24 * 60 * 60 * 1000 } +]; + +const viewLimitOptions = [ + { label: "1", value: 1 }, + { label: "Unlimited", value: -1 } +]; + export const AddShareSecretForm = ({ isPublic, inModal, @@ -49,36 +68,15 @@ export const AddShareSecretForm = ({ const privateSharedSecretCreator = useCreateSharedSecret(); const createSharedSecret = isPublic ? publicSharedSecretCreator : privateSharedSecretCreator; - const expirationUnitsAndActions = [ - { - unit: "Minutes", - action: (expiresAt: Date, expiresInValue: number) => - expiresAt.setMinutes(expiresAt.getMinutes() + expiresInValue) - }, - { - unit: "Hours", - action: (expiresAt: Date, expiresInValue: number) => - expiresAt.setHours(expiresAt.getHours() + expiresInValue) - }, - { - unit: "Days", - action: (expiresAt: Date, expiresInValue: number) => - expiresAt.setDate(expiresAt.getDate() + expiresInValue) - }, - { - unit: "Weeks", - action: (expiresAt: Date, expiresInValue: number) => - expiresAt.setDate(expiresAt.getDate() + expiresInValue * 7) - } - ]; const onFormSubmit = async ({ value, expiresInValue, - expiresInUnit, - expiresAfterSingleView, + expiresAfterViews, accessType }: FormData) => { try { + const expiresAt = new Date(new Date().getTime() + Number(expiresInValue)); + const key = crypto.randomBytes(16).toString("hex"); const hashedHex = crypto.createHash("sha256").update(key).digest("hex"); const { ciphertext, iv, tag } = encryptSymmetric({ @@ -86,21 +84,13 @@ export const AddShareSecretForm = ({ key }); - const expiresAt = new Date(); - const updateExpiresAt = expirationUnitsAndActions.find( - (item) => item.unit === expiresInUnit - )?.action; - if (updateExpiresAt && expiresInValue) { - updateExpiresAt(expiresAt, expiresInValue); - } - const { id } = await createSharedSecret.mutateAsync({ encryptedValue: ciphertext, iv, tag, hashedHex, expiresAt, - expiresAfterViews: expiresAfterSingleView ? 1 : 1000, + expiresAfterViews: expiresAfterViews === "-1" ? undefined : Number(expiresAfterViews), accessType: accessType as SecretSharingAccessType }); @@ -132,9 +122,14 @@ export const AddShareSecretForm = ({ } }; return ( -
+
(
-
-
-
-
- ( - - - - )} - /> -
-
- ( - - - - )} - /> -
-
-
-
-

AND

-
-
- ( - - - - )} - /> -
- ( - - Can be viewed only 1 time - - )} - /> -
-
-
+ ( + + + + )} + /> + ( + + + + )} + /> {!isPublic && ( ( - onChange(e)} className="w-full"> People within your organization Anyone @@ -261,7 +211,7 @@ export const AddShareSecretForm = ({ )}
{inModal && ( diff --git a/frontend/src/views/ShareSecretPage/components/AddShareSecretModal.tsx b/frontend/src/views/ShareSecretPage/components/AddShareSecretModal.tsx index f8cfd1e8b..5410bbe4d 100644 --- a/frontend/src/views/ShareSecretPage/components/AddShareSecretModal.tsx +++ b/frontend/src/views/ShareSecretPage/components/AddShareSecretModal.tsx @@ -12,9 +12,8 @@ import { ViewAndCopySharedSecret } from "./ViewAndCopySharedSecret"; const schema = yup.object({ value: yup.string().max(10000).required().label("Shared Secret Value"), - expiresAfterViews: yup.number().min(1).required().label("Expires After Views"), - expiresInValue: yup.number().min(1).required().label("Expiration Value"), - expiresInUnit: yup.string().required().label("Expiration Unit") + expiresInValue: yup.string().required().label("Expiration Value"), + expiresAfterViews: yup.string().required().label("Expires After Views") }); export type FormData = yup.InferType; diff --git a/frontend/src/views/ShareSecretPage/components/ShareSecretSection.tsx b/frontend/src/views/ShareSecretPage/components/ShareSecretSection.tsx index a450d61f5..841a9667c 100644 --- a/frontend/src/views/ShareSecretPage/components/ShareSecretSection.tsx +++ b/frontend/src/views/ShareSecretPage/components/ShareSecretSection.tsx @@ -46,9 +46,8 @@ export const ShareSecretSection = () => { -
+

Shared Secrets

-