mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-13 20:29:34 +00:00
feat(infisical-pg): completed secret rollback
This commit is contained in:
@@ -19,7 +19,7 @@ import {
|
||||
TUpdateFolderDTO
|
||||
} from "./types";
|
||||
|
||||
const queryKeys = {
|
||||
export const folderQueryKeys = {
|
||||
getSecretFolders: ({ projectId, environment, path }: TGetProjectFoldersDTO) =>
|
||||
["secret-folders", { projectId, environment, path }] as const
|
||||
};
|
||||
@@ -46,14 +46,14 @@ export const useGetProjectFolders = ({
|
||||
TSecretFolder[],
|
||||
unknown,
|
||||
TSecretFolder[],
|
||||
ReturnType<typeof queryKeys.getSecretFolders>
|
||||
ReturnType<typeof folderQueryKeys.getSecretFolders>
|
||||
>,
|
||||
"queryKey" | "queryFn"
|
||||
>;
|
||||
}) =>
|
||||
useQuery({
|
||||
...options,
|
||||
queryKey: queryKeys.getSecretFolders({ projectId, environment, path }),
|
||||
queryKey: folderQueryKeys.getSecretFolders({ projectId, environment, path }),
|
||||
enabled: Boolean(projectId) && Boolean(environment) && (options?.enabled ?? true),
|
||||
queryFn: async () => fetchProjectFolders(projectId, environment, path)
|
||||
});
|
||||
@@ -65,7 +65,7 @@ export const useGetFoldersByEnv = ({
|
||||
}: TGetFoldersByEnvDTO) => {
|
||||
const folders = useQueries({
|
||||
queries: environments.map((environment) => ({
|
||||
queryKey: queryKeys.getSecretFolders({ projectId, environment, path }),
|
||||
queryKey: folderQueryKeys.getSecretFolders({ projectId, environment, path }),
|
||||
queryFn: async () => fetchProjectFolders(projectId, environment, path),
|
||||
enabled: Boolean(projectId) && Boolean(environment)
|
||||
}))
|
||||
@@ -106,7 +106,9 @@ export const useCreateFolder = () => {
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { projectId, environment, path }) => {
|
||||
queryClient.invalidateQueries(queryKeys.getSecretFolders({ projectId, environment, path }));
|
||||
queryClient.invalidateQueries(
|
||||
folderQueryKeys.getSecretFolders({ projectId, environment, path })
|
||||
);
|
||||
queryClient.invalidateQueries(
|
||||
secretSnapshotKeys.list({ workspaceId: projectId, environment, directory: path })
|
||||
);
|
||||
@@ -131,7 +133,9 @@ export const useUpdateFolder = () => {
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { projectId, environment, path }) => {
|
||||
queryClient.invalidateQueries(queryKeys.getSecretFolders({ projectId, environment, path }));
|
||||
queryClient.invalidateQueries(
|
||||
folderQueryKeys.getSecretFolders({ projectId, environment, path })
|
||||
);
|
||||
queryClient.invalidateQueries(
|
||||
secretSnapshotKeys.list({ workspaceId: projectId, environment, directory: path })
|
||||
);
|
||||
@@ -157,7 +161,9 @@ export const useDeleteFolder = () => {
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { path = "/", projectId, environment }) => {
|
||||
queryClient.invalidateQueries(queryKeys.getSecretFolders({ projectId, environment, path }));
|
||||
queryClient.invalidateQueries(
|
||||
folderQueryKeys.getSecretFolders({ projectId, environment, path })
|
||||
);
|
||||
queryClient.invalidateQueries(
|
||||
secretSnapshotKeys.list({ workspaceId: projectId, environment, directory: path })
|
||||
);
|
||||
|
||||
@@ -35,13 +35,13 @@ const fetchWorkspaceSnaphots = async ({
|
||||
offset = 0
|
||||
}: TGetSecretSnapshotsDTO & { offset: number }) => {
|
||||
const res = await apiRequest.get<{ secretSnapshots: TSecretSnapshot[] }>(
|
||||
`/api/v1/workspace/${workspaceId}/secret-snapshots`,
|
||||
`/api/ee/v1/workspace/${workspaceId}/secret-snapshots`,
|
||||
{
|
||||
params: {
|
||||
limit,
|
||||
offset,
|
||||
environment,
|
||||
directory
|
||||
path: directory
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -60,12 +60,12 @@ export const useGetWorkspaceSnapshotList = (dto: TGetSecretSnapshotsDTO & { isPa
|
||||
|
||||
const fetchSnapshotEncSecrets = async (snapshotId: string) => {
|
||||
const res = await apiRequest.get<{ secretSnapshot: TSnapshotData }>(
|
||||
`/api/v1/secret-snapshot/${snapshotId}`
|
||||
`/api/ee/v1/secret-snapshot/${snapshotId}`
|
||||
);
|
||||
return res.data.secretSnapshot;
|
||||
};
|
||||
|
||||
export const useGetSnapshotSecrets = ({ decryptFileKey, env, snapshotId }: TSnapshotDataProps) =>
|
||||
export const useGetSnapshotSecrets = ({ decryptFileKey, snapshotId }: TSnapshotDataProps) =>
|
||||
useQuery({
|
||||
queryKey: secretSnapshotKeys.snapshotData(snapshotId),
|
||||
enabled: Boolean(snapshotId && decryptFileKey),
|
||||
@@ -82,45 +82,43 @@ export const useGetSnapshotSecrets = ({ decryptFileKey, env, snapshotId }: TSnap
|
||||
|
||||
const sharedSecrets: DecryptedSecret[] = [];
|
||||
const personalSecrets: Record<string, { id: string; value: string }> = {};
|
||||
data.secretVersions
|
||||
.filter(({ environment }) => environment === env)
|
||||
.forEach((encSecret) => {
|
||||
const secretKey = decryptSymmetric({
|
||||
ciphertext: encSecret.secretKeyCiphertext,
|
||||
iv: encSecret.secretKeyIV,
|
||||
tag: encSecret.secretKeyTag,
|
||||
key
|
||||
});
|
||||
|
||||
const secretValue = decryptSymmetric({
|
||||
ciphertext: encSecret.secretValueCiphertext,
|
||||
iv: encSecret.secretValueIV,
|
||||
tag: encSecret.secretValueTag,
|
||||
key
|
||||
});
|
||||
|
||||
const secretComment = "";
|
||||
|
||||
const decryptedSecret = {
|
||||
id: encSecret.secret,
|
||||
env: encSecret.environment,
|
||||
key: secretKey,
|
||||
value: secretValue,
|
||||
tags: encSecret.tags,
|
||||
comment: secretComment,
|
||||
createdAt: encSecret.createdAt,
|
||||
updatedAt: encSecret.updatedAt,
|
||||
type: "modified",
|
||||
version: encSecret.version
|
||||
};
|
||||
|
||||
if (encSecret.type === "personal") {
|
||||
personalSecrets[decryptedSecret.key] = { id: encSecret.secret, value: secretValue };
|
||||
} else {
|
||||
sharedSecrets.push(decryptedSecret);
|
||||
}
|
||||
data.secretVersions.forEach((encSecret) => {
|
||||
const secretKey = decryptSymmetric({
|
||||
ciphertext: encSecret.secretKeyCiphertext,
|
||||
iv: encSecret.secretKeyIV,
|
||||
tag: encSecret.secretKeyTag,
|
||||
key
|
||||
});
|
||||
|
||||
const secretValue = decryptSymmetric({
|
||||
ciphertext: encSecret.secretValueCiphertext,
|
||||
iv: encSecret.secretValueIV,
|
||||
tag: encSecret.secretValueTag,
|
||||
key
|
||||
});
|
||||
|
||||
const secretComment = "";
|
||||
|
||||
const decryptedSecret = {
|
||||
id: encSecret.secretId,
|
||||
env: data.environment.slug,
|
||||
key: secretKey,
|
||||
value: secretValue,
|
||||
tags: encSecret.tags,
|
||||
comment: secretComment,
|
||||
createdAt: encSecret.createdAt,
|
||||
updatedAt: encSecret.updatedAt,
|
||||
type: "modified",
|
||||
version: encSecret.version
|
||||
};
|
||||
|
||||
if (encSecret.type === "personal") {
|
||||
personalSecrets[decryptedSecret.key] = { id: encSecret.secretId, value: secretValue };
|
||||
} else {
|
||||
sharedSecrets.push(decryptedSecret);
|
||||
}
|
||||
});
|
||||
|
||||
sharedSecrets.forEach((val) => {
|
||||
if (personalSecrets?.[val.key]) {
|
||||
val.idOverride = personalSecrets[val.key].id;
|
||||
@@ -130,7 +128,7 @@ export const useGetSnapshotSecrets = ({ decryptFileKey, env, snapshotId }: TSnap
|
||||
});
|
||||
|
||||
return {
|
||||
version: data.version,
|
||||
id: data.id,
|
||||
secrets: sharedSecrets,
|
||||
createdAt: data.createdAt,
|
||||
folders: data.folderVersion
|
||||
@@ -144,11 +142,11 @@ const fetchWorkspaceSecretSnaphotCount = async (
|
||||
directory = "/"
|
||||
) => {
|
||||
const res = await apiRequest.get<{ count: number }>(
|
||||
`/api/v1/workspace/${workspaceId}/secret-snapshots/count`,
|
||||
`/api/ee/v1/workspace/${workspaceId}/secret-snapshots/count`,
|
||||
{
|
||||
params: {
|
||||
environment,
|
||||
directory
|
||||
path: directory
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -171,11 +169,8 @@ export const usePerformSecretRollback = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<{}, {}, TSecretRollbackDTO>({
|
||||
mutationFn: async ({ workspaceId, ...dto }) => {
|
||||
const { data } = await apiRequest.post(
|
||||
`/api/v1/workspace/${workspaceId}/secret-snapshots/rollback`,
|
||||
dto
|
||||
);
|
||||
mutationFn: async ({ snapshotId }) => {
|
||||
const { data } = await apiRequest.post(`/api/ee/v1/secret-snapshot/${snapshotId}/rollback`);
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { workspaceId, environment, directory }) => {
|
||||
@@ -183,6 +178,10 @@ export const usePerformSecretRollback = () => {
|
||||
{ workspaceId, environment, secretPath: directory },
|
||||
"secrets"
|
||||
]);
|
||||
queryClient.invalidateQueries([
|
||||
"secret-folders",
|
||||
{ projectId: workspaceId, environment, path: directory }
|
||||
]);
|
||||
queryClient.invalidateQueries(
|
||||
secretSnapshotKeys.list({ workspaceId, environment, directory })
|
||||
);
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import { UserWsKeyPair } from "../keys/types";
|
||||
import { EncryptedSecretVersion } from "../secrets/types";
|
||||
import { WorkspaceEnv } from "../types";
|
||||
|
||||
export type TSecretSnapshot = {
|
||||
id: string;
|
||||
workspace: string;
|
||||
version: number;
|
||||
secretVersions: string[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
__v: number;
|
||||
};
|
||||
|
||||
export type TSnapshotData = Omit<TSecretSnapshot, "secretVersions"> & {
|
||||
id: string;
|
||||
secretVersions: EncryptedSecretVersion[];
|
||||
folderVersion: Array<{ name: string; id: string }>;
|
||||
environment: WorkspaceEnv;
|
||||
};
|
||||
|
||||
export type TSnapshotDataProps = {
|
||||
@@ -30,8 +31,8 @@ export type TGetSecretSnapshotsDTO = {
|
||||
};
|
||||
|
||||
export type TSecretRollbackDTO = {
|
||||
snapshotId: string;
|
||||
workspaceId: string;
|
||||
version: number;
|
||||
environment: string;
|
||||
directory?: string;
|
||||
};
|
||||
|
||||
@@ -46,12 +46,12 @@ export type DecryptedSecret = {
|
||||
|
||||
export type EncryptedSecretVersion = {
|
||||
id: string;
|
||||
secret: string;
|
||||
secretId: string;
|
||||
version: number;
|
||||
workspace: string;
|
||||
type: string;
|
||||
environment: string;
|
||||
isDeleted: boolean;
|
||||
envId: string;
|
||||
secretKeyCiphertext: string;
|
||||
secretKeyIV: string;
|
||||
secretKeyTag: string;
|
||||
|
||||
@@ -97,6 +97,7 @@ export const SnapshotView = ({
|
||||
{}
|
||||
);
|
||||
const diffView: Array<TDiffView<DecryptedSecret>> = [];
|
||||
console.log({ rollingSecrets, secrets });
|
||||
rollingSecrets.forEach((rollSecret) => {
|
||||
const { id } = rollSecret;
|
||||
const doesExist = Boolean(secretGroupById?.[id]);
|
||||
@@ -118,9 +119,9 @@ export const SnapshotView = ({
|
||||
});
|
||||
return diffView;
|
||||
}, [secrets, rollingSecrets]);
|
||||
|
||||
console.log(secretDiffView);
|
||||
const handleClickRollback = async () => {
|
||||
if (!snapshotData?.version) {
|
||||
if (!snapshotData?.id) {
|
||||
createNotification({
|
||||
text: "Failed to find secret version",
|
||||
type: "success"
|
||||
@@ -130,7 +131,7 @@ export const SnapshotView = ({
|
||||
try {
|
||||
await performRollback({
|
||||
workspaceId,
|
||||
version: snapshotData.version,
|
||||
snapshotId: snapshotData.id,
|
||||
environment,
|
||||
directory: secretPath
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user