diff --git a/backend/src/ee/controllers/v1/roleController.ts b/backend/src/ee/controllers/v1/roleController.ts index d80ef2817..edc31273a 100644 --- a/backend/src/ee/controllers/v1/roleController.ts +++ b/backend/src/ee/controllers/v1/roleController.ts @@ -212,12 +212,13 @@ export const getUserPermissions = async (req: Request, res: Response) => { const { params: { orgId } } = await validateRequest(GetUserPermission, req); - - const { permission } = await getUserOrgPermissions(req.user._id, orgId); + + const { permission, membership } = await getUserOrgPermissions(req.user._id, orgId); res.status(200).json({ data: { - permissions: packRules(permission.rules) + permissions: packRules(permission.rules), + membership } }); }; @@ -226,11 +227,12 @@ export const getUserWorkspacePermissions = async (req: Request, res: Response) = const { params: { workspaceId } } = await validateRequest(GetUserProjectPermission, req); - const { permission } = await getUserProjectPermissions(req.user._id, workspaceId); + const { permission, membership } = await getUserProjectPermissions(req.user._id, workspaceId); res.status(200).json({ data: { - permissions: packRules(permission.rules) + permissions: packRules(permission.rules), + membership } }); }; diff --git a/docs/documentation/platform/secret-rotation/overview.mdx b/docs/documentation/platform/secret-rotation/overview.mdx index a11142106..284375401 100644 --- a/docs/documentation/platform/secret-rotation/overview.mdx +++ b/docs/documentation/platform/secret-rotation/overview.mdx @@ -1,37 +1,44 @@ ---- -title: "Secret Rotation Overview" -description: "Keep your credentials safe by rotation" ---- +# Secret Rotation Overview -Secret rotation is the process of periodically changing the values of secrets. This is done to reduce the risk of secrets being compromised and used to gain unauthorized access to systems or data. +## Introduction -Rotated secrets can be -1. API key for an external service -2. Database credentials +Secret rotation is a process that involves updating secret credentials periodically to minimize the risk of their compromise. +Rotating secrets helps prevent unauthorized access to systems and sensitive data by ensuring that old credentials are replaced with new ones regularly. -## How does the rotation happen? +Rotated secrets may include, but are not limited to: -There are four phases in secret rotation and its triggered periodically in an internval. +1. API keys for external services +2. Database credentials for various platforms -1. Creation +## Rotation Process -System will create secret by calling an external service like an API call, or randomly generate a value. -Now there exist three valid secrets. +The practice of rotating secrets is a systematic and interval-based operation, carried out in four fundamental phases. -2. Test +### 1. Creation -Test the new secret key by some check to ensure its working one. Thus only two will be considered active and the other is considered inactive. +The system initiates the rotation process by either making an API call to an external service or generating a new secret value internally. +Upon successful creation, the system will temporarily have three versions of the secret: -3. Deletion +- **Current active secret**: The one currently in use. +- **Future active secret (pending)**: The newly created secret, awaiting validation. +- **Previous active secret**: The old secret, soon to be retired. -System will remove the inactive secret and now there exist two valid secrets +### 2. Testing -4. Finish +The newly generated secret is subjected to a verification process to ensure its validity and functionality. +This involves conducting checks or tests that simulate actual operations the secret would perform. +Only the current active and the future active (pending) secrets are considered operational at this stage, while the previous active secret remains in standby mode. -System will switch the secret value from the rotated ones and trigger side effects like webhooks and events. +### 3. Deletion + +Post-verification, the system deactivates and deletes the previous active secret, leaving only the current and future active (pending) secrets in the system. + +### 4. Activation + +Finally, the system promotes the future active (pending) secret to be the new current active secret. It then triggers necessary side effects, such as invoking webhooks and generating events, to notify other services of the change. ## Infisical Secret Rotation Strategies -1. [SendGrid](./sendgrid) -2. [PostgreSQL/CockroachDB](./postgres) -3. [MySQL/MariaDB](./mysql) +1. [SendGrid Integration](./sendgrid) +2. [PostgreSQL/CockroachDB Implementation](./postgres) +3. [MySQL/MariaDB Configuration](./mysql) diff --git a/frontend/src/components/permissions/OrgPermissionCan.tsx b/frontend/src/components/permissions/OrgPermissionCan.tsx index 4366110a9..006d43232 100644 --- a/frontend/src/components/permissions/OrgPermissionCan.tsx +++ b/frontend/src/components/permissions/OrgPermissionCan.tsx @@ -21,7 +21,7 @@ export const OrgPermissionCan: FunctionComponent = ({ allowedLabel, ...props }) => { - const permission = useOrgPermission(); + const { permission } = useOrgPermission(); return ( diff --git a/frontend/src/context/OrgPermissionContext/OrgPermissionContext.tsx b/frontend/src/context/OrgPermissionContext/OrgPermissionContext.tsx index 5320ece6d..312ae0437 100644 --- a/frontend/src/context/OrgPermissionContext/OrgPermissionContext.tsx +++ b/frontend/src/context/OrgPermissionContext/OrgPermissionContext.tsx @@ -1,6 +1,7 @@ import { createContext, ReactNode, useContext } from "react"; import { useGetUserOrgPermissions } from "@app/hooks/api"; +import { OrgUser } from "@app/hooks/api/types"; import { useOrganization } from "../OrganizationContext"; import { TOrgPermission } from "./types"; @@ -9,7 +10,10 @@ type Props = { children: ReactNode; }; -const OrgPermissionContext = createContext(null); +const OrgPermissionContext = createContext(null); export const OrgPermissionProvider = ({ children }: Props): JSX.Element => { const { currentOrg } = useOrganization(); diff --git a/frontend/src/hoc/withPermission/withPermission.tsx b/frontend/src/hoc/withPermission/withPermission.tsx index e0c402af3..389d8509c 100644 --- a/frontend/src/hoc/withPermission/withPermission.tsx +++ b/frontend/src/hoc/withPermission/withPermission.tsx @@ -21,7 +21,7 @@ export const withPermission = ( { action, subject, className, containerClassName }: Props["abilities"]> ) => { const HOC = (hocProps: T) => { - const permission = useOrgPermission(); + const { permission } = useOrgPermission(); // akhilmhdh: Set as any due to casl/react ts type bug // REASON: casl due to its type checking can't seem to union even if union intersection is applied diff --git a/frontend/src/hooks/api/roles/queries.tsx b/frontend/src/hooks/api/roles/queries.tsx index 3e68aa57d..5694ccfd6 100644 --- a/frontend/src/hooks/api/roles/queries.tsx +++ b/frontend/src/hooks/api/roles/queries.tsx @@ -8,6 +8,7 @@ import { apiRequest } from "@app/config/request"; import { OrgPermissionSet } from "@app/context/OrgPermissionContext/types"; import { ProjectPermissionSet } from "@app/context/ProjectPermissionContext/types"; +import { OrgUser } from "../users/types"; import { TGetRolesDTO, TGetUserOrgPermissionsDTO, @@ -63,13 +64,16 @@ export const useGetRoles = ({ orgId, workspaceId }: TGetRolesDTO) => }); const getUserOrgPermissions = async ({ orgId }: TGetUserOrgPermissionsDTO) => { - if (orgId === "") return []; + if (orgId === "") return { permissions: [], membership: null }; const { data } = await apiRequest.get<{ - data: { permissions: PackRule>>[] }; - }>(`/api/v1/roles/organization/${orgId}/permissions`, {}); - - return data.data.permissions; + data: { + permissions: PackRule>>[]; + membership: OrgUser; + }; + }>(`/api/v1/roles/organization/${orgId}/permissions`); + + return data.data; }; export const useGetUserOrgPermissions = ({ orgId }: TGetUserOrgPermissionsDTO) => @@ -78,9 +82,9 @@ export const useGetUserOrgPermissions = ({ orgId }: TGetUserOrgPermissionsDTO) = queryFn: () => getUserOrgPermissions({ orgId }), // enabled: Boolean(orgId), select: (data) => { - const rule = unpackRules>>(data); + const rule = unpackRules>>(data.permissions); const ability = createMongoAbility(rule, { conditionsMatcher }); - return ability; + return { permission: ability, membership: data.membership }; } }); diff --git a/frontend/src/hooks/api/workspace/queries.tsx b/frontend/src/hooks/api/workspace/queries.tsx index e3136fae3..5b185b97a 100644 --- a/frontend/src/hooks/api/workspace/queries.tsx +++ b/frontend/src/hooks/api/workspace/queries.tsx @@ -34,7 +34,8 @@ export const workspaceKeys = { getUserWsEnvironments: (workspaceId: string) => ["workspace-env", { workspaceId }] as const, getWorkspaceAuditLogs: (workspaceId: string) => [{ workspaceId }] as const, getWorkspaceUsers: (workspaceId: string) => [{ workspaceId }] as const, - getWorkspaceServiceTokenDataV3: (workspaceId: string) => [{ workspaceId }, "workspace-service-token-data-v3"] as const + getWorkspaceServiceTokenDataV3: (workspaceId: string) => + [{ workspaceId }, "workspace-service-token-data-v3"] as const }; const fetchWorkspaceById = async (workspaceId: string) => { @@ -53,7 +54,7 @@ const fetchWorkspaceIndexStatus = async (workspaceId: string) => { return data; }; -const fetchWorkspaceSecrets = async (workspaceId: string) => { +export const fetchWorkspaceSecrets = async (workspaceId: string) => { const { data: { secrets } } = await apiRequest.get<{ secrets: EncryptedSecret[] }>( @@ -253,9 +254,18 @@ export const useReorderWsEnvironment = () => { const queryClient = useQueryClient(); return useMutation<{}, {}, ReorderEnvironmentsDTO>({ - mutationFn: ({ workspaceID, environmentSlug, environmentName, otherEnvironmentSlug, otherEnvironmentName}) => { + mutationFn: ({ + workspaceID, + environmentSlug, + environmentName, + otherEnvironmentSlug, + otherEnvironmentName + }) => { return apiRequest.patch(`/api/v2/workspace/${workspaceID}/environments`, { - environmentSlug, environmentName, otherEnvironmentSlug, otherEnvironmentName + environmentSlug, + environmentName, + otherEnvironmentSlug, + otherEnvironmentName }); }, onSuccess: () => { @@ -378,4 +388,4 @@ export const useGetWorkspaceServiceTokenDataV3 = (workspaceId: string) => { }, enabled: true }); -}; \ No newline at end of file +}; diff --git a/frontend/src/views/IntegrationsPage/components/IntegrationsSection/IntegrationsSection.tsx b/frontend/src/views/IntegrationsPage/components/IntegrationsSection/IntegrationsSection.tsx index 34d28ec14..37fe8c59d 100644 --- a/frontend/src/views/IntegrationsPage/components/IntegrationsSection/IntegrationsSection.tsx +++ b/frontend/src/views/IntegrationsPage/components/IntegrationsSection/IntegrationsSection.tsx @@ -54,7 +54,7 @@ export const IntegrationsSection = ({ )} - {!isBotActive && ( + {!isBotActive && Boolean(integrations.length) && (
@@ -119,7 +119,7 @@ export const IntegrationsSection = ({ {integrationSlugNameMapping[integration.integration]}
- {(integration.integration === "qovery") && ( + {integration.integration === "qovery" && (
diff --git a/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx b/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx index 7667eaeb6..0cb590631 100644 --- a/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx +++ b/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx @@ -41,6 +41,7 @@ import { } from "@app/hooks/api"; import { FolderBreadCrumbs } from "./components/FolderBreadCrumbs"; +import { ProjectIndexSecretsSection } from "./components/ProjectIndexSecretsSection"; import { SecretOverviewFolderRow } from "./components/SecretOverviewFolderRow"; import { SecretOverviewTableRow } from "./components/SecretOverviewTableRow"; @@ -259,6 +260,7 @@ export const SecretOverviewPage = () => { return (
+
diff --git a/frontend/src/views/SecretOverviewPage/components/ProjectIndexSecretsSection/ProjectIndexSecretsSection.tsx b/frontend/src/views/SecretOverviewPage/components/ProjectIndexSecretsSection/ProjectIndexSecretsSection.tsx new file mode 100644 index 000000000..23cfa750d --- /dev/null +++ b/frontend/src/views/SecretOverviewPage/components/ProjectIndexSecretsSection/ProjectIndexSecretsSection.tsx @@ -0,0 +1,98 @@ +import { ProjectPermissionCan } from "@app/components/permissions"; +import { + decryptAssymmetric, + decryptSymmetric +} from "@app/components/utilities/cryptography/crypto"; +import { Button, Spinner } from "@app/components/v2"; +import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context"; +import { useToggle } from "@app/hooks"; +import { useGetWorkspaceIndexStatus, useNameWorkspaceSecrets } from "@app/hooks/api"; +import { UserWsKeyPair } from "@app/hooks/api/types"; +import { fetchWorkspaceSecrets } from "@app/hooks/api/workspace/queries"; + +// TODO: add check so that this only shows up if user is +// an admin in the workspace +type Props = { + decryptFileKey: UserWsKeyPair; +}; + +export const ProjectIndexSecretsSection = ({ decryptFileKey }: Props) => { + const { currentWorkspace } = useWorkspace(); + const { data: isBlindIndexed, isLoading: isBlindIndexedLoading } = useGetWorkspaceIndexStatus( + currentWorkspace?._id ?? "" + ); + const [isIndexing, setIsIndexing] = useToggle(); + const nameWorkspaceSecrets = useNameWorkspaceSecrets(); + + const onEnableBlindIndices = async () => { + if (!currentWorkspace?._id) return; + setIsIndexing.on(); + try { + const encryptedSecrets = await fetchWorkspaceSecrets(currentWorkspace._id); + + const key = decryptAssymmetric({ + ciphertext: decryptFileKey.encryptedKey, + nonce: decryptFileKey.nonce, + publicKey: decryptFileKey.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 + }); + } catch (err) { + console.log(err); + } finally { + setIsIndexing.off(); + } + }; + + return !isBlindIndexedLoading && !isBlindIndexed ? ( +
+ {isIndexing && ( +
+ +
+
Please wait
+ Re-indexing your secrets... +
+
+ )} +

Enable Blind Indices

+

+ Your project was created before the introduction of blind indexing. + To continue accessing secrets by name through the SDK, public API and web dashboard, please enable blind + indexing. This is a one time process. +

+ + {(isAllowed) => ( + + )} + +
+ ) : ( +
+ ); +}; diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectIndexSecretsSection/index.tsx b/frontend/src/views/SecretOverviewPage/components/ProjectIndexSecretsSection/index.tsx similarity index 100% rename from frontend/src/views/Settings/ProjectSettingsPage/components/ProjectIndexSecretsSection/index.tsx rename to frontend/src/views/SecretOverviewPage/components/ProjectIndexSecretsSection/index.tsx diff --git a/frontend/src/views/SecretRotationPage/components/CreateRotationForm/CreateRotationForm.tsx b/frontend/src/views/SecretRotationPage/components/CreateRotationForm/CreateRotationForm.tsx index 3576cc0f9..5d4ed8073 100644 --- a/frontend/src/views/SecretRotationPage/components/CreateRotationForm/CreateRotationForm.tsx +++ b/frontend/src/views/SecretRotationPage/components/CreateRotationForm/CreateRotationForm.tsx @@ -1,12 +1,11 @@ import { useRef, useState } from "react"; import { AnimatePresence, motion } from "framer-motion"; +import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { Modal, ModalContent, Step, Stepper } from "@app/components/v2"; import { useCreateSecretRotation } from "@app/hooks/api"; import { TSecretRotationProvider } from "@app/hooks/api/types"; -import { useNotificationContext } from "~/components/context/Notifications/NotificationProvider"; - import { RotationInputForm } from "./steps/RotationInputForm"; import { RotationOutputForm, diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgDeleteSection/OrgDeleteSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgDeleteSection/OrgDeleteSection.tsx index dd810f1ac..a336355db 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgDeleteSection/OrgDeleteSection.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgDeleteSection/OrgDeleteSection.tsx @@ -1,81 +1,70 @@ import { useRouter } from "next/router"; import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; -import { - Button, - DeleteActionModal -} from "@app/components/v2"; -import { useOrganization, useUser } from "@app/context"; -import { - useDeleteOrgById, - useGetOrgUsers -} from "@app/hooks/api"; +import { Button, DeleteActionModal } from "@app/components/v2"; +import { useOrganization, useOrgPermission } from "@app/context"; +import { useDeleteOrgById } from "@app/hooks/api"; import { usePopUp } from "@app/hooks/usePopUp"; import { navigateUserToOrg } from "@app/views/Login/Login.utils"; export const OrgDeleteSection = () => { - const router = useRouter(); - const { currentOrg } = useOrganization(); - const { user } = useUser(); - const { createNotification } = useNotificationContext(); - const { data: members } = useGetOrgUsers(currentOrg?._id ?? ""); - - const membershipOrg = members?.find((member) => member.user._id === user._id); + const router = useRouter(); + const { currentOrg } = useOrganization(); + const { createNotification } = useNotificationContext(); + const { membership } = useOrgPermission(); - const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ - "deleteOrg" - ] as const); + const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ + "deleteOrg" + ] as const); - const { mutateAsync, isLoading } = useDeleteOrgById(); - - const handleDeleteOrgSubmit = async () => { - try { - if (!currentOrg?._id) return; - - await mutateAsync({ - organizationId: currentOrg?._id - }); - - createNotification({ - text: "Successfully deleted organization", - type: "success" - }); + const { mutateAsync, isLoading } = useDeleteOrgById(); - await navigateUserToOrg(router); - - handlePopUpClose("deleteOrg"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete organization", - type: "error" - }); - } + const handleDeleteOrgSubmit = async () => { + try { + if (!currentOrg?._id) return; + + await mutateAsync({ + organizationId: currentOrg?._id + }); + + createNotification({ + text: "Successfully deleted organization", + type: "success" + }); + + await navigateUserToOrg(router); + + handlePopUpClose("deleteOrg"); + } catch (err) { + console.error(err); + createNotification({ + text: "Failed to delete organization", + type: "error" + }); } + }; - return ( -
-

- Danger Zone -

- - handlePopUpToggle("deleteOrg", isOpen)} - deleteKey="confirm" - onDeleteApproved={handleDeleteOrgSubmit} - /> -
- ); -} \ No newline at end of file + return ( +
+

Danger Zone

+ + handlePopUpToggle("deleteOrg", isOpen)} + deleteKey="confirm" + onDeleteApproved={handleDeleteOrgSubmit} + /> +
+ ); +}; diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgGeneralTab/OrgGeneralTab.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgGeneralTab/OrgGeneralTab.tsx index d8e48966d..9c8279caf 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgGeneralTab/OrgGeneralTab.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgGeneralTab/OrgGeneralTab.tsx @@ -1,24 +1,17 @@ -import { useOrganization, useUser } from "@app/context"; -import { useGetOrgUsers } from "@app/hooks/api"; +import { useOrgPermission } from "@app/context"; import { OrgDeleteSection } from "../OrgDeleteSection"; import { OrgIncidentContactsSection } from "../OrgIncidentContactsSection"; import { OrgNameChangeSection } from "../OrgNameChangeSection"; export const OrgGeneralTab = () => { - const { currentOrg } = useOrganization(); - const { user } = useUser(); - const { data: members } = useGetOrgUsers(currentOrg?._id ?? ""); - - const membershipOrg = members?.find((member) => member.user._id === user?._id); + const { membership } = useOrgPermission(); return (
- {(membershipOrg && membershipOrg.role === "admin") && ( - - )} + {membership && membership.role === "admin" && }
); }; diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgIncidentContactsSection/OrgIncidentContactsSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgIncidentContactsSection/OrgIncidentContactsSection.tsx index bc2547528..fbb4987a7 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgIncidentContactsSection/OrgIncidentContactsSection.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgIncidentContactsSection/OrgIncidentContactsSection.tsx @@ -15,7 +15,7 @@ export const OrgIncidentContactsSection = () => { const { handlePopUpToggle, popUp, handlePopUpOpen, handlePopUpClose } = usePopUp([ "addContact" ] as const); - const permission = useOrgPermission(); + const { permission } = useOrgPermission(); return (
diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectGeneralTab/ProjectGeneralTab.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectGeneralTab/ProjectGeneralTab.tsx index cacfda8bb..bbd8e78d4 100644 --- a/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectGeneralTab/ProjectGeneralTab.tsx +++ b/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectGeneralTab/ProjectGeneralTab.tsx @@ -2,20 +2,18 @@ import { AutoCapitalizationSection } from "../AutoCapitalizationSection"; import { DeleteProjectSection } from "../DeleteProjectSection"; import { E2EESection } from "../E2EESection"; import { EnvironmentSection } from "../EnvironmentSection"; -import { ProjectIndexSecretsSection } from "../ProjectIndexSecretsSection"; import { ProjectNameChangeSection } from "../ProjectNameChangeSection"; import { SecretTagsSection } from "../SecretTagsSection"; export const ProjectGeneralTab = () => { - return ( -
- - - - - - - -
- ); -} \ No newline at end of file + return ( +
+ + + + + + +
+ ); +}; diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectIndexSecretsSection/ProjectIndexSecretsSection.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectIndexSecretsSection/ProjectIndexSecretsSection.tsx deleted file mode 100644 index ca2e14eb9..000000000 --- a/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectIndexSecretsSection/ProjectIndexSecretsSection.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { ProjectPermissionCan } from "@app/components/permissions"; -import { - decryptAssymmetric, - decryptSymmetric -} from "@app/components/utilities/cryptography/crypto"; -import { Button } from "@app/components/v2"; -import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context"; -import { - useGetUserWsKey, - useGetWorkspaceIndexStatus, - useGetWorkspaceSecrets, - useNameWorkspaceSecrets -} from "@app/hooks/api"; - -// TODO: add check so that this only shows up if user is -// an admin in the workspace - -export const ProjectIndexSecretsSection = () => { - const { currentWorkspace } = useWorkspace(); - const { data: isBlindIndexed, isLoading: isBlindIndexedLoading } = useGetWorkspaceIndexStatus( - currentWorkspace?._id ?? "" - ); - const { data: latestFileKey } = useGetUserWsKey(currentWorkspace?._id ?? ""); - const { data: encryptedSecrets } = useGetWorkspaceSecrets(currentWorkspace?._id ?? ""); - const nameWorkspaceSecrets = useNameWorkspaceSecrets(); - - 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 !isBlindIndexedLoading && !isBlindIndexed ? ( -
-

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. -

- - {(isAllowed) => ( - - )} - -
- ) : ( -
- ); -}; diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/index.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/index.tsx index 5f9e1013b..757dfc6b2 100644 --- a/frontend/src/views/Settings/ProjectSettingsPage/components/index.tsx +++ b/frontend/src/views/Settings/ProjectSettingsPage/components/index.tsx @@ -2,7 +2,6 @@ export { AutoCapitalizationSection } from "./AutoCapitalizationSection"; export { DeleteProjectSection } from "./DeleteProjectSection"; export { E2EESection } from "./E2EESection"; export { EnvironmentSection } from "./EnvironmentSection"; -export { ProjectIndexSecretsSection } from "./ProjectIndexSecretsSection"; export { ProjectNameChangeSection } from "./ProjectNameChangeSection"; export { SecretTagsSection } from "./SecretTagsSection"; export { ServiceTokenSection } from "./ServiceTokenSection"; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index d5a16121a..42ea0e773 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -2,15 +2,16 @@ "compilerOptions": { "baseUrl": ".", "paths": { - "~/components/*": ["./src/components/*"], - "~/hooks/*": ["./src/hooks/*"], - "~/utilities/*": ["./src/components/utilities/*"], - "~/*": ["./src/const"], - "~/pages/*": ["./src/pages/*"], - "@app/*": ["./src/*"] + "@app/*": [ + "./src/*" + ] }, "target": "ESNext", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -25,6 +26,14 @@ "jsx": "preserve", "incremental": true }, - "include": ["next-i18next.config.js", "next-env.d.ts", "./src/**/*.ts", "./src/**/*.tsx", "./.eslintrc.js"], - "exclude": ["node_modules"] + "include": [ + "next-i18next.config.js", + "next-env.d.ts", + "./src/**/*.ts", + "./src/**/*.tsx", + "./.eslintrc.js" + ], + "exclude": [ + "node_modules" + ] }