mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-15 07:35:09 +00:00
checkpoint
This commit is contained in:
@@ -2,7 +2,8 @@ export {
|
||||
useAddGroupToWorkspace,
|
||||
useDeleteGroupFromWorkspace,
|
||||
useLeaveProject,
|
||||
useUpdateGroupWorkspaceRole
|
||||
useUpdateGroupWorkspaceRole,
|
||||
useMigrateProjectToV3
|
||||
} from "./mutations";
|
||||
export {
|
||||
useAddIdentityToWorkspace,
|
||||
|
||||
@@ -74,3 +74,15 @@ export const useLeaveProject = () => {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useMigrateProjectToV3 = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<{}, {}, { workspaceId: string }>({
|
||||
mutationFn: ({ workspaceId }) => {
|
||||
return apiRequest.delete(`/api/v1/workspace/${workspaceId}/migrate-v3`);
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries(workspaceKeys.getAllUserWorkspace);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -150,11 +150,15 @@ export const useGetWorkspaceSecrets = (workspaceId: string) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetWorkspaceById = (workspaceId: string) => {
|
||||
export const useGetWorkspaceById = (
|
||||
workspaceId: string,
|
||||
dto?: { refetchInterval?: number | false }
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: workspaceKeys.getWorkspaceById(workspaceId),
|
||||
queryFn: () => fetchWorkspaceById(workspaceId),
|
||||
enabled: Boolean(workspaceId)
|
||||
enabled: Boolean(workspaceId),
|
||||
refetchInterval: dto?.refetchInterval
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export enum ProjectVersion {
|
||||
V1 = 1,
|
||||
V2 = 2
|
||||
V2 = 2,
|
||||
V3 = 3
|
||||
}
|
||||
|
||||
export enum ProjectUserMembershipTemporaryMode {
|
||||
|
||||
@@ -55,7 +55,6 @@ import {
|
||||
SelectItem,
|
||||
UpgradePlanModal
|
||||
} from "@app/components/v2";
|
||||
import { UpgradeOverlay } from "@app/components/v2/UpgradeOverlay";
|
||||
import {
|
||||
OrgPermissionActions,
|
||||
OrgPermissionSubjects,
|
||||
@@ -335,7 +334,6 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
||||
<aside className="dark w-full border-r border-mineshaft-600 bg-gradient-to-tr from-mineshaft-700 via-mineshaft-800 to-mineshaft-900 md:w-60">
|
||||
<nav className="items-between flex h-full flex-col justify-between overflow-y-auto dark:[color-scheme:dark]">
|
||||
<div>
|
||||
<UpgradeOverlay />
|
||||
{!router.asPath.includes("personal") && (
|
||||
<div className="flex h-12 cursor-default items-center px-3 pt-6">
|
||||
{(router.asPath.includes("project") ||
|
||||
|
||||
@@ -59,7 +59,6 @@ import {
|
||||
useGetFoldersByEnv,
|
||||
useGetImportedSecretsAllEnvs,
|
||||
useGetProjectSecretsAllEnv,
|
||||
useGetUserWsKey,
|
||||
useUpdateSecretV3
|
||||
} from "@app/hooks/api";
|
||||
import { useUpdateFolderBatch } from "@app/hooks/api/secretFolders/queries";
|
||||
@@ -70,7 +69,7 @@ import { ProjectVersion } from "@app/hooks/api/workspace/types";
|
||||
import { FolderForm } from "../SecretMainPage/components/ActionBar/FolderForm";
|
||||
import { CreateSecretForm } from "./components/CreateSecretForm";
|
||||
import { FolderBreadCrumbs } from "./components/FolderBreadCrumbs";
|
||||
import { ProjectIndexSecretsSection } from "./components/ProjectIndexSecretsSection";
|
||||
import { SecretV2MigrationSection } from "./components/SecretV2MigrationSection";
|
||||
import { SecretOverviewDynamicSecretRow } from "./components/SecretOverviewDynamicSecretRow";
|
||||
import { SecretOverviewFolderRow } from "./components/SecretOverviewFolderRow";
|
||||
import { SecretOverviewTableRow } from "./components/SecretOverviewTableRow";
|
||||
@@ -103,7 +102,6 @@ export const SecretOverviewPage = () => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const workspaceId = currentWorkspace?.id as string;
|
||||
const projectSlug = currentWorkspace?.slug as string;
|
||||
const { data: latestFileKey } = useGetUserWsKey(workspaceId);
|
||||
const [searchFilter, setSearchFilter] = useState("");
|
||||
const secretPath = (router.query?.secretPath as string) || "/";
|
||||
|
||||
@@ -475,7 +473,7 @@ export const SecretOverviewPage = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="container mx-auto px-6 text-mineshaft-50 dark:[color-scheme:dark]">
|
||||
<ProjectIndexSecretsSection decryptFileKey={latestFileKey!} />
|
||||
<SecretV2MigrationSection />
|
||||
<div className="relative right-5 ml-4">
|
||||
<NavHeader pageName={t("dashboard.title")} isProjectRelated />
|
||||
</div>
|
||||
|
||||
-109
@@ -1,109 +0,0 @@
|
||||
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,
|
||||
useProjectPermission,
|
||||
useWorkspace
|
||||
} from "@app/context";
|
||||
import { useToggle } from "@app/hooks";
|
||||
import { useGetWorkspaceIndexStatus, useNameWorkspaceSecrets } from "@app/hooks/api";
|
||||
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||
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 { membership } = useProjectPermission();
|
||||
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,
|
||||
secretId: encryptedSecret.id
|
||||
};
|
||||
});
|
||||
await nameWorkspaceSecrets.mutateAsync({
|
||||
workspaceId: currentWorkspace.id,
|
||||
secretsToUpdate
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
} finally {
|
||||
setIsIndexing.off();
|
||||
}
|
||||
};
|
||||
|
||||
// for non admin this would throw an error
|
||||
// so no need to render
|
||||
return !isBlindIndexedLoading && typeof isBlindIndexed === "boolean" && !isBlindIndexed ? (
|
||||
<div className="mt-4 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
{isIndexing && (
|
||||
<div className="absolute top-0 left-0 z-50 flex h-screen w-screen items-center justify-center bg-bunker-500 bg-opacity-80">
|
||||
<Spinner size="lg" className="text-primary" />
|
||||
<div className="ml-4 flex flex-col space-y-1">
|
||||
<div className="text-3xl font-medium">Please wait</div>
|
||||
<span className="inline-block">Re-indexing your secrets...</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<p className="mb-2 text-lg font-semibold">Action Required</p>
|
||||
<p className="mb-4 leading-7 text-gray-400">
|
||||
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.{" "}
|
||||
<b>
|
||||
{membership.role !== ProjectMembershipRole.Admin && "This is an admin only operation."}
|
||||
</b>
|
||||
</p>
|
||||
<ProjectPermissionCan I={ProjectPermissionActions.Edit} a={ProjectPermissionSub.Settings}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
onClick={onEnableBlindIndices}
|
||||
isDisabled={!isAllowed || membership.role !== ProjectMembershipRole.Admin}
|
||||
color="mineshaft"
|
||||
type="submit"
|
||||
isLoading={isIndexing}
|
||||
>
|
||||
Enable Blind Indexing
|
||||
</Button>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
</div>
|
||||
) : (
|
||||
<div />
|
||||
);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export { ProjectIndexSecretsSection } from "./ProjectIndexSecretsSection";
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
|
||||
import { Button, Spinner } from "@app/components/v2";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionSub,
|
||||
useProjectPermission,
|
||||
useWorkspace
|
||||
} from "@app/context";
|
||||
import { useGetWorkspaceById, useMigrateProjectToV3 } from "@app/hooks/api";
|
||||
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||
import { ProjectVersion } from "@app/hooks/api/workspace/types";
|
||||
|
||||
enum ProjectUpgradeStatus {
|
||||
InProgress = "IN_PROGRESS",
|
||||
// Completed -> Will be null if completed. So a completed status is not needed
|
||||
Failed = "FAILED"
|
||||
}
|
||||
|
||||
export const SecretV2MigrationSection = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { data: workspaceDetails } = useGetWorkspaceById(
|
||||
// if v3 no need to fetch
|
||||
currentWorkspace?.version === ProjectVersion.V3 ? "" : currentWorkspace?.id || "",
|
||||
{
|
||||
refetchInterval:
|
||||
currentWorkspace?.upgradeStatus === ProjectUpgradeStatus.InProgress ? 3000 : false
|
||||
}
|
||||
);
|
||||
const { membership } = useProjectPermission();
|
||||
const migrateProjectToV3 = useMigrateProjectToV3();
|
||||
|
||||
const isProjectUpgraded = workspaceDetails?.version === ProjectVersion.V3;
|
||||
|
||||
if (isProjectUpgraded || currentWorkspace?.version === ProjectVersion.V3) return null;
|
||||
const isUpgrading = workspaceDetails?.upgradeStatus === ProjectUpgradeStatus.InProgress;
|
||||
|
||||
const handleMigrationSecretV2 = async () => {
|
||||
try {
|
||||
await migrateProjectToV3.mutateAsync({ workspaceId: currentWorkspace?.id || "" });
|
||||
createNotification({
|
||||
text: "Migrated project to new KMS",
|
||||
type: "success"
|
||||
});
|
||||
} catch {
|
||||
createNotification({
|
||||
text: "Failed to upgrade project",
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
};
|
||||
// for non admin this would throw an error
|
||||
// so no need to render
|
||||
return (
|
||||
<div className="mt-4 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
{isUpgrading && (
|
||||
<div className="absolute top-0 left-0 z-50 flex h-screen w-screen items-center justify-center bg-bunker-500 bg-opacity-80">
|
||||
<Spinner size="lg" className="text-primary" />
|
||||
<div className="ml-4 flex flex-col space-y-1">
|
||||
<div className="text-3xl font-medium">Please wait</div>
|
||||
<span className="inline-block">Upgrading your project...</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<p className="mb-2 text-lg font-semibold">Action Required</p>
|
||||
<p className="mb-4 leading-7 text-gray-400">
|
||||
There is a new update for your project. Introducing Infisical KMS.
|
||||
<b>
|
||||
{membership.role !== ProjectMembershipRole.Admin && "This is an admin only operation."}
|
||||
</b>
|
||||
</p>
|
||||
<ProjectPermissionCan I={ProjectPermissionActions.Edit} a={ProjectPermissionSub.Settings}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
onClick={handleMigrationSecretV2}
|
||||
isDisabled={
|
||||
!isAllowed || membership.role !== ProjectMembershipRole.Admin || isUpgrading
|
||||
}
|
||||
color="mineshaft"
|
||||
type="submit"
|
||||
isLoading={migrateProjectToV3.isLoading}
|
||||
>
|
||||
Start Migration
|
||||
</Button>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { SecretV2MigrationSection } from "./SecretV2MigrationSection";
|
||||
Reference in New Issue
Block a user