From acb90ee0f7e5843ce7bf8ff7c83e77d9ecaa2941 Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Tue, 18 Apr 2023 12:43:06 +0300 Subject: [PATCH] Add frontend migration support for existing project to be blind-indexed --- .../src/controllers/v2/secretsController.ts | 34 +++++-- .../controllers/v3/workspacesController.ts | 18 ++-- .../v1/secretSnapshotController.ts | 10 +- .../ee/controllers/v1/workspaceController.ts | 4 + backend/src/ee/models/secretVersion.ts | 5 + backend/src/routes/v3/workspaces.ts | 16 ++-- backend/src/types/secret/index.d.ts | 1 + .../utilities/secrets/encryptSecrets.ts | 2 + frontend/src/hooks/api/workspace/index.tsx | 6 +- frontend/src/hooks/api/workspace/queries.tsx | 53 +++++++++++ frontend/src/hooks/api/workspace/types.ts | 8 ++ frontend/src/pages/dashboard/[id].tsx | 2 + .../ProjectSettingsPage.tsx | 62 +++++++++++-- .../ProjectEncryptionModeSection.tsx | 93 ------------------- .../ProjectEncryptionModeSection/index.tsx | 1 - .../ProjectIndexSecretsSection.tsx | 32 +++++++ .../ProjectIndexSecretsSection/index.tsx | 1 + .../ProjectSettingsPage/components/index.tsx | 2 +- 18 files changed, 212 insertions(+), 138 deletions(-) delete mode 100644 frontend/src/views/Settings/ProjectSettingsPage/components/ProjectEncryptionModeSection/ProjectEncryptionModeSection.tsx delete mode 100644 frontend/src/views/Settings/ProjectSettingsPage/components/ProjectEncryptionModeSection/index.tsx create mode 100644 frontend/src/views/Settings/ProjectSettingsPage/components/ProjectIndexSecretsSection/ProjectIndexSecretsSection.tsx create mode 100644 frontend/src/views/Settings/ProjectSettingsPage/components/ProjectIndexSecretsSection/index.tsx diff --git a/backend/src/controllers/v2/secretsController.ts b/backend/src/controllers/v2/secretsController.ts index e05e758ed..89aa1d76e 100644 --- a/backend/src/controllers/v2/secretsController.ts +++ b/backend/src/controllers/v2/secretsController.ts @@ -15,7 +15,7 @@ import { UnauthorizedRequestError, ValidationError } from '../../utils/errors'; import { EventService } from '../../services'; import { eventPushSecrets } from '../../events'; import { EESecretService, EELogService } from '../../ee/services'; -import { TelemetryService } from '../../services'; +import { TelemetryService, SecretService } from '../../services'; import { getChannelFromUserAgent } from '../../utils/posthog'; import { PERMISSION_WRITE_SECRETS } from '../../variables'; import { userHasNoAbility, userHasWorkspaceAccess, userHasWriteOnlyAbility } from '../../ee/helpers/checkMembershipPermissions'; @@ -51,29 +51,47 @@ export const batchSecrets = async (req: Request, res: Response) => { const updateSecrets: BatchSecret[] = []; const deleteSecrets: Types.ObjectId[] = []; const actions: IAction[] = []; + + // get secret blind index salt + const salt = await SecretService.getSecretBlindIndexSalt({ + workspaceId: new Types.ObjectId(workspaceId) + }); - requests.forEach((request) => { + for await (const request of requests) { + let secretBlindIndex = ''; switch (request.method) { case 'POST': + secretBlindIndex = await SecretService.generateSecretBlindIndexWithSalt({ + secretName: request.secret.secretName, + salt + }); + createSecrets.push({ ...request.secret, version: 1, user: request.secret.type === SECRET_PERSONAL ? req.user : undefined, environment, - workspace: new Types.ObjectId(workspaceId) + workspace: new Types.ObjectId(workspaceId), + secretBlindIndex }); break; case 'PATCH': + secretBlindIndex = await SecretService.generateSecretBlindIndexWithSalt({ + secretName: request.secret.secretName, + salt + }); + updateSecrets.push({ ...request.secret, - _id: new Types.ObjectId(request.secret._id) + _id: new Types.ObjectId(request.secret._id), + secretBlindIndex }); break; case 'DELETE': deleteSecrets.push(new Types.ObjectId(request.secret._id)); break; } - }); + } // handle create secrets let createdSecrets: ISecret[] = []; @@ -134,7 +152,10 @@ export const batchSecrets = async (req: Request, res: Response) => { const updateOperations = updateSecrets.map((u) => ({ updateOne: { - filter: { _id: new Types.ObjectId(u._id) }, + filter: { + _id: new Types.ObjectId(u._id), + workspace: new Types.ObjectId(workspaceId) + }, update: { $inc: { version: 1 @@ -154,6 +175,7 @@ export const batchSecrets = async (req: Request, res: Response) => { type: listedSecretsObj[u._id.toString()].type, environment, isDeleted: false, + secretBlindIndex: u.secretBlindIndex, secretKeyCiphertext: u.secretKeyCiphertext, secretKeyIV: u.secretKeyIV, secretKeyTag: u.secretKeyTag, diff --git a/backend/src/controllers/v3/workspacesController.ts b/backend/src/controllers/v3/workspacesController.ts index 61079e6b4..aac6682d7 100644 --- a/backend/src/controllers/v3/workspacesController.ts +++ b/backend/src/controllers/v3/workspacesController.ts @@ -1,11 +1,7 @@ import { Request, Response } from 'express'; import { Types } from 'mongoose'; -import { Secret, Workspace, SecretBlindIndexData } from '../../models'; +import { Secret } from '../../models'; import { SecretService } from'../../services'; -import { BadRequestError } from '../../utils/errors'; -import { decryptSymmetric } from '../../utils/crypto'; -import { getEncryptionKey } from '../../config'; -import * as argon2 from 'argon2'; /** * Return whether or not all secrets in workspace with id [workspaceId] @@ -18,12 +14,13 @@ export const getWorkspaceBlindIndexStatus = async (req: Request, res: Response) const { workspaceId } = req.params; const secretsWithoutBlindIndex = await Secret.countDocuments({ - workspace: new Types.ObjectId(workspaceId) + workspace: new Types.ObjectId(workspaceId), + secretBlindIndex: { + $exists: false + } }); - const isBlindIndexed = secretsWithoutBlindIndex === 0; - - return res.status(200).send(isBlindIndexed); + return res.status(200).send(secretsWithoutBlindIndex === 0); } /** @@ -47,7 +44,6 @@ export const getWorkspaceSecrets = async (req: Request, res: Response) => { * @param res */ export const nameWorkspaceSecrets = async (req: Request, res: Response) => { - interface SecretToUpdate { secretName: string; _id: string; @@ -89,6 +85,6 @@ export const nameWorkspaceSecrets = async (req: Request, res: Response) => { await Secret.bulkWrite(operations); return res.status(200).send({ - operations + message: 'Successfully named workspace secrets' }); } \ No newline at end of file diff --git a/backend/src/ee/controllers/v1/secretSnapshotController.ts b/backend/src/ee/controllers/v1/secretSnapshotController.ts index ae3af7958..15b346f98 100644 --- a/backend/src/ee/controllers/v1/secretSnapshotController.ts +++ b/backend/src/ee/controllers/v1/secretSnapshotController.ts @@ -15,16 +15,10 @@ export const getSecretSnapshot = async (req: Request, res: Response) => { secretSnapshot = await SecretSnapshot .findById(secretSnapshotId) - .populate({ - path: 'secretVersions', - populate: { - path: 'tags', - model: 'Tag', - } - }); + .populate('secretVersions'); if (!secretSnapshot) throw new Error('Failed to find secret snapshot'); - + } catch (err) { Sentry.setUser({ email: req.user.email }); Sentry.captureException(err); diff --git a/backend/src/ee/controllers/v1/workspaceController.ts b/backend/src/ee/controllers/v1/workspaceController.ts index 3c4ad111d..9dd7a0ca6 100644 --- a/backend/src/ee/controllers/v1/workspaceController.ts +++ b/backend/src/ee/controllers/v1/workspaceController.ts @@ -222,6 +222,7 @@ export const rollbackWorkspaceSecretSnapshot = async (req: Request, res: Respons type, user, environment, + secretBlindIndex, secretKeyCiphertext, secretKeyIV, secretKeyTag, @@ -240,6 +241,7 @@ export const rollbackWorkspaceSecretSnapshot = async (req: Request, res: Respons type, user, environment, + secretBlindIndex: secretBlindIndex ?? undefined, secretKeyCiphertext, secretKeyIV, secretKeyTag, @@ -265,6 +267,7 @@ export const rollbackWorkspaceSecretSnapshot = async (req: Request, res: Respons type, user, environment, + secretBlindIndex, secretKeyCiphertext, secretKeyIV, secretKeyTag, @@ -282,6 +285,7 @@ export const rollbackWorkspaceSecretSnapshot = async (req: Request, res: Respons user, environment, isDeleted: false, + secretBlindIndex: secretBlindIndex ?? undefined, secretKeyCiphertext, secretKeyIV, secretKeyTag, diff --git a/backend/src/ee/models/secretVersion.ts b/backend/src/ee/models/secretVersion.ts index 63c7d936a..a430834a9 100644 --- a/backend/src/ee/models/secretVersion.ts +++ b/backend/src/ee/models/secretVersion.ts @@ -13,6 +13,7 @@ export interface ISecretVersion { user?: Types.ObjectId; // new environment: string; // new isDeleted: boolean; + secretBlindIndex?: string; secretKeyCiphertext: string; secretKeyIV: string; secretKeyTag: string; @@ -57,6 +58,10 @@ const secretVersionSchema = new Schema( default: false, required: true }, + secretBlindIndex: { + type: String, + select: false + }, secretKeyCiphertext: { type: String, required: true diff --git a/backend/src/routes/v3/workspaces.ts b/backend/src/routes/v3/workspaces.ts index ad02e9a4c..fdd734cf9 100644 --- a/backend/src/routes/v3/workspaces.ts +++ b/backend/src/routes/v3/workspaces.ts @@ -19,13 +19,13 @@ router.get( '/:workspaceId/secrets/blind-index-status', param('workspaceId').exists().isString().trim(), validateRequest, - // requireAuth({ - // acceptedAuthModes: [AUTH_MODE_JWT] - // }), - // requireWorkspaceAuth({ - // acceptedRoles: [ADMIN], - // locationWorkspaceId: 'params', - // }), + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN], + locationWorkspaceId: 'params', + }), workspacesController.getWorkspaceBlindIndexStatus ); @@ -52,7 +52,7 @@ router.post( // allow admins to name all workspace secrets (part of blind indice .withMessage('secretsToUpdate must be an array') .customSanitizer((value) => { return value.map((secret: any) => ({ - secretName: secret.name, + secretName: secret.secretName, _id: secret._id })); }), diff --git a/backend/src/types/secret/index.d.ts b/backend/src/types/secret/index.d.ts index 257038f60..7a6ec7a5a 100644 --- a/backend/src/types/secret/index.d.ts +++ b/backend/src/types/secret/index.d.ts @@ -24,6 +24,7 @@ export interface BatchSecretRequest { export interface BatchSecret { _id: string; type: 'shared' | 'personal', + secretBlindIndex: string; secretKeyCiphertext: string; secretKeyIV: string; secretKeyTag: string; diff --git a/frontend/src/components/utilities/secrets/encryptSecrets.ts b/frontend/src/components/utilities/secrets/encryptSecrets.ts index 7b678a494..afaf27ab5 100644 --- a/frontend/src/components/utilities/secrets/encryptSecrets.ts +++ b/frontend/src/components/utilities/secrets/encryptSecrets.ts @@ -10,6 +10,7 @@ interface EncryptedSecretProps { id: string; createdAt: string; environment: string; + secretName: string; secretCommentCiphertext: string; secretCommentIV: string; secretCommentTag: string; @@ -94,6 +95,7 @@ const encryptSecrets = async ({ id: secret.id, createdAt: '', environment: env, + secretName: secret.key, secretKeyCiphertext, secretKeyIV, secretKeyTag, diff --git a/frontend/src/hooks/api/workspace/index.tsx b/frontend/src/hooks/api/workspace/index.tsx index 622c5196c..3a9d8fd2f 100644 --- a/frontend/src/hooks/api/workspace/index.tsx +++ b/frontend/src/hooks/api/workspace/index.tsx @@ -7,7 +7,9 @@ export { useGetUserWorkspaces, useGetUserWsEnvironments, useGetWorkspaceById, + useGetWorkspaceIndexStatus, + useGetWorkspaceSecrets, + useNameWorkspaceSecrets, useRenameWorkspace, useToggleAutoCapitalization, - useUpdateWsEnvironment -} from './queries'; + useUpdateWsEnvironment} from './queries'; diff --git a/frontend/src/hooks/api/workspace/queries.tsx b/frontend/src/hooks/api/workspace/queries.tsx index 4736da076..d2d7a4cde 100644 --- a/frontend/src/hooks/api/workspace/queries.tsx +++ b/frontend/src/hooks/api/workspace/queries.tsx @@ -2,12 +2,16 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { apiRequest } from '@app/config/request'; +import { + EncryptedSecret +} from '../secrets/types'; import { CreateEnvironmentDTO, CreateWorkspaceDTO, DeleteEnvironmentDTO, DeleteWorkspaceDTO, GetWsEnvironmentDTO, + NameWorkspaceSecretsDTO, RenameWorkspaceDTO, ToggleAutoCapitalizationDTO, UpdateEnvironmentDTO, @@ -17,6 +21,8 @@ import { const workspaceKeys = { getWorkspaceById: (workspaceId: string) => [{ workspaceId }, 'workspace'] as const, + getWorkspaceSecrets: (workspaceId: string) => [{ workspaceId }, 'workspace-secrets'] as const, + getWorkspaceIndexStatus: (workspaceId: string) => [{ workspaceId}, 'workspace-index-status'] as const, getWorkspaceMemberships: (orgId: string) => [{ orgId }, 'workspace-memberships'], getAllUserWorkspace: ['workspaces'] as const, getUserWsEnvironments: (workspaceId: string) => ['workspace-env', { workspaceId }] as const @@ -26,14 +32,47 @@ const fetchWorkspaceById = async (workspaceId: string) => { const { data } = await apiRequest.get<{ workspace: Workspace }>( `/api/v1/workspace/${workspaceId}` ); + return data.workspace; }; +const fetchWorkspaceIndexStatus = async (workspaceId: string) => { + const { data } = await apiRequest.get( + `/api/v3/workspaces/${workspaceId}/secrets/blind-index-status` + ); + + return data; +} + +const fetchWorkspaceSecrets = async (workspaceId: string) => { + const { data: { secrets } } = await apiRequest.get<{ secrets: EncryptedSecret[] }>( + `/api/v3/workspaces/${workspaceId}/secrets` + ); + + return secrets; +} + const fetchUserWorkspaces = async () => { const { data } = await apiRequest.get<{ workspaces: Workspace[] }>('/api/v1/workspace'); return data.workspaces; }; +export const useGetWorkspaceIndexStatus = (workspaceId: string) => { + return useQuery({ + queryKey: workspaceKeys.getWorkspaceIndexStatus(workspaceId), + queryFn: () => fetchWorkspaceIndexStatus(workspaceId), + enabled: true + }); +} + +export const useGetWorkspaceSecrets = (workspaceId: string) => { + return useQuery({ + queryKey: workspaceKeys.getWorkspaceSecrets(workspaceId), + queryFn: () => fetchWorkspaceSecrets(workspaceId), + enabled: true + }) +} + export const useGetWorkspaceById = (workspaceId: string) => { return useQuery({ queryKey: workspaceKeys.getWorkspaceById(workspaceId), @@ -75,6 +114,20 @@ export const useGetUserWorkspaceMemberships = (orgId: string) => enabled: Boolean(orgId) }); +export const useNameWorkspaceSecrets = () => { + const queryClient = useQueryClient(); + + return useMutation<{}, {}, NameWorkspaceSecretsDTO>({ + mutationFn: async ({ workspaceId, secretsToUpdate }) => + apiRequest.post(`/api/v3/workspaces/${workspaceId}/secrets/names`, { + secretsToUpdate + }), + onSuccess: (_, variables) => { + queryClient.invalidateQueries(workspaceKeys.getWorkspaceIndexStatus(variables.workspaceId)); + } + }); +} + // mutation export const useCreateWorkspace = () => { const queryClient = useQueryClient(); diff --git a/frontend/src/hooks/api/workspace/types.ts b/frontend/src/hooks/api/workspace/types.ts index 44d4c4322..3f58f39b9 100644 --- a/frontend/src/hooks/api/workspace/types.ts +++ b/frontend/src/hooks/api/workspace/types.ts @@ -16,6 +16,14 @@ export type WorkspaceEnv = { export type WorkspaceTag = { _id: string; name: string; slug: string }; +export type NameWorkspaceSecretsDTO = { + workspaceId: string; + secretsToUpdate: { + secretName: string; + _id: string; + }[]; +} + // mutation dto export type CreateWorkspaceDTO = { workspaceName: string; diff --git a/frontend/src/pages/dashboard/[id].tsx b/frontend/src/pages/dashboard/[id].tsx index 8aa480c81..defd46f34 100644 --- a/frontend/src/pages/dashboard/[id].tsx +++ b/frontend/src/pages/dashboard/[id].tsx @@ -586,6 +586,7 @@ export default function Dashboard() { method: 'POST', secret: { type: secret.type, + secretName: secret.secretName, secretKeyCiphertext: secret.secretKeyCiphertext, secretKeyIV: secret.secretKeyIV, secretKeyTag: secret.secretKeyTag, @@ -614,6 +615,7 @@ export default function Dashboard() { secret: { _id: secret.id, type: secret.type, + secretName: secret.secretName, secretKeyCiphertext: secret.secretKeyCiphertext, secretKeyIV: secret.secretKeyIV, secretKeyTag: secret.secretKeyTag, diff --git a/frontend/src/views/Settings/ProjectSettingsPage/ProjectSettingsPage.tsx b/frontend/src/views/Settings/ProjectSettingsPage/ProjectSettingsPage.tsx index 1684f6c1a..3ba5bc956 100644 --- a/frontend/src/views/Settings/ProjectSettingsPage/ProjectSettingsPage.tsx +++ b/frontend/src/views/Settings/ProjectSettingsPage/ProjectSettingsPage.tsx @@ -9,8 +9,8 @@ import NavHeader from '@app/components/navigation/NavHeader'; // TODO(akhilmhdh):Refactor this into a better utility module package import { decryptAssymmetric, - encryptSymmetric -} from '@app/components/utilities/cryptography/crypto'; + decryptSymmetric, + encryptSymmetric} from '@app/components/utilities/cryptography/crypto'; import { Button, FormControl, Input } from '@app/components/v2'; import { plans } from '@app/const'; import { useSubscription, useWorkspace } from '@app/context'; @@ -25,11 +25,13 @@ import { useDeleteWsTag, useGetUserWsKey, useGetUserWsServiceTokens, + useGetWorkspaceIndexStatus, + useGetWorkspaceSecrets, useGetWsTags, + useNameWorkspaceSecrets, useRenameWorkspace, useToggleAutoCapitalization, - useUpdateWsEnvironment -} from '@app/hooks/api'; + useUpdateWsEnvironment} from '@app/hooks/api'; import { AutoCapitalizationSection } from './components/AutoCapitalizationSection/AutoCapitalizationSection'; import { SecretTagsSection } from './components/SecretTagsSection'; @@ -39,9 +41,10 @@ import { CreateUpdateEnvFormData, CreateWsTag, EnvironmentSection, - ProjectEncryptionModeSection, + ProjectIndexSecretsSection, ProjectNameChangeSection, - ServiceTokenSection} from './components'; + ServiceTokenSection +} from './components'; export const ProjectSettingsPage = () => { const { t } = useTranslation(); @@ -55,6 +58,7 @@ export const ProjectSettingsPage = () => { const [isDeleting, setIsDeleting] = useToggle(); const renameWorkspace = useRenameWorkspace(); + const nameWorkspaceSecrets = useNameWorkspaceSecrets(); const toggleAutoCapitalization = useToggleAutoCapitalization(); const deleteWorkspace = useDeleteWorkspace(); @@ -63,11 +67,16 @@ export const ProjectSettingsPage = () => { const updateWsEnv = useUpdateWsEnvironment(); const deleteWsEnv = useDeleteWsEnvironment(); + const { data: isBlindIndexed, isLoading: isBlindIndexedLoading } = useGetWorkspaceIndexStatus(workspaceID); + // service token const { data: serviceTokens, isLoading: isServiceTokenLoading } = useGetUserWsServiceTokens({ workspaceID: currentWorkspace?._id || '' }); + const { data: latestFileKey } = useGetUserWsKey(workspaceID); + const { data: encryptedSecrets } = useGetWorkspaceSecrets(workspaceID); + const createServiceToken = useCreateServiceToken(); const deleteServiceToken = useDeleteServiceToken(); @@ -207,14 +216,15 @@ export const ProjectSettingsPage = () => { // type guard if (!latestFileKey) return ''; try { - // crypo calculation to generate the key const key = decryptAssymmetric({ ciphertext: latestFileKey.encryptedKey, nonce: latestFileKey.nonce, publicKey: latestFileKey.sender.publicKey, privateKey: localStorage.getItem('PRIVATE_KEY') as string }); + const randomBytes = crypto.randomBytes(16).toString('hex'); + const { ciphertext, iv, tag } = encryptSymmetric({ plaintext: key, key: randomBytes @@ -303,6 +313,38 @@ export const ProjectSettingsPage = () => { } }; + const onEnableBlindIndices = async () => { + if (!currentWorkspace?._id) return; + if (!encryptedSecrets) return; + if (!latestFileKey) return; + + const key = decryptAssymmetric({ + ciphertext: latestFileKey.encryptedKey, + nonce: latestFileKey.nonce, + publicKey: latestFileKey.sender.publicKey, + privateKey: localStorage.getItem('PRIVATE_KEY') as string + }); + + const secretsToUpdate = encryptedSecrets.map((encryptedSecret) => { + const secretName = decryptSymmetric({ + ciphertext: encryptedSecret.secretKeyCiphertext, + iv: encryptedSecret.secretKeyIV, + tag: encryptedSecret.secretKeyTag, + key + }); + + return ({ + secretName, + _id: encryptedSecret._id + }); + }); + + await nameWorkspaceSecrets.mutateAsync({ + workspaceId: currentWorkspace._id, + secretsToUpdate + }); + } + return (
{/* TODO(akhilmhdh): Remove this right when layout is refactored */} @@ -349,7 +391,11 @@ export const ProjectSettingsPage = () => { workspaceAutoCapitalization={currentWorkspace?.autoCapitalization} onAutoCapitalizationChange={onAutoCapitalizationToggle} /> - + {!isBlindIndexedLoading && !isBlindIndexed && ( + + )}

{t('settings-project:danger-zone')}

{t('settings-project:danger-zone-note')}

diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectEncryptionModeSection/ProjectEncryptionModeSection.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectEncryptionModeSection/ProjectEncryptionModeSection.tsx deleted file mode 100644 index 47630effb..000000000 --- a/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectEncryptionModeSection/ProjectEncryptionModeSection.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { useEffect } from 'react'; -import { - Controller, - useForm -} from 'react-hook-form'; -import { faCheck } from '@fortawesome/free-solid-svg-icons'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { yupResolver } from '@hookform/resolvers/yup'; -import * as yup from 'yup'; - -import { - Button, - FormControl, - Select, - SelectItem -} from '@app/components/v2'; - -// TODO: modify in accordance with what was discussed with -// Maidul - -// Do with select for now them replace. - -const items = [ - { value: 'e2ee', label: 'E2EE' }, - { value: 'blind-indexed-e2ee', label: 'Blind Indexed E2EE' } -]; - -const formSchema = yup.object({ - mode: yup.string().required().label('Project Mode') -}); - -type FormData = yup.InferType; - -export const ProjectEncryptionModeSection = () => { - const { - handleSubmit, - control, - reset, - formState: { isDirty, isSubmitting } - } = useForm({ resolver: yupResolver(formSchema) }); - - useEffect(() => { - reset({ mode: 'blind-indexed-e2ee' }); - }, []); - - const onFormSubmit = async ({ mode }: FormData) => { - console.log('onFormSubmit'); - console.log('mode: ', mode); - }; - - return ( -
-

Encryption Mode

-
- { - console.log('field: ', field); - return ( - - - - ); - }} - control={control} - name="mode" - /> -
- -
- ); -} \ No newline at end of file diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectEncryptionModeSection/index.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectEncryptionModeSection/index.tsx deleted file mode 100644 index 981819f70..000000000 --- a/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectEncryptionModeSection/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { ProjectEncryptionModeSection } from './ProjectEncryptionModeSection'; \ No newline at end of file diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectIndexSecretsSection/ProjectIndexSecretsSection.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectIndexSecretsSection/ProjectIndexSecretsSection.tsx new file mode 100644 index 000000000..d1ca4f265 --- /dev/null +++ b/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectIndexSecretsSection/ProjectIndexSecretsSection.tsx @@ -0,0 +1,32 @@ +import { Button } from '@app/components/v2'; + +// TODO: add check so that this only shows up if user is +// an admin in the workspace + +type Props = { + onEnableBlindIndices: () => Promise; +} + +export const ProjectIndexSecretsSection = ({ + onEnableBlindIndices +}: Props) => { + return ( +
+

Blind Indices

+

+ Your project, created before the introduction of blind indexing, contains unindexed secrets. To access individual secrets by name through the SDK and public API, please enable blind indexing. +

+

+ Learn more about it here. +

+ +
+ ); +} \ No newline at end of file diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectIndexSecretsSection/index.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectIndexSecretsSection/index.tsx new file mode 100644 index 000000000..cd8252f7d --- /dev/null +++ b/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectIndexSecretsSection/index.tsx @@ -0,0 +1 @@ +export { ProjectIndexSecretsSection } from './ProjectIndexSecretsSection'; \ No newline at end of file diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/index.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/index.tsx index 83a4b3a95..a59111447 100644 --- a/frontend/src/views/Settings/ProjectSettingsPage/components/index.tsx +++ b/frontend/src/views/Settings/ProjectSettingsPage/components/index.tsx @@ -1,7 +1,7 @@ export { CopyProjectIDSection } from './CopyProjectIDSection'; export { EnvironmentSection } from './EnvironmentSection'; export type { CreateUpdateEnvFormData } from './EnvironmentSection/EnvironmentSection'; -export { ProjectEncryptionModeSection } from './ProjectEncryptionModeSection'; +export { ProjectIndexSecretsSection } from './ProjectIndexSecretsSection'; export { ProjectNameChangeSection } from './ProjectNameChangeSection'; export type { CreateWsTag } from './SecretTagsSection/SecretTagsSection'; export { ServiceTokenSection } from './ServiceTokenSection';