mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-16 08:14:06 +00:00
feat(secret-approval): implemented the new policy based approval system bare version
This commit is contained in:
@@ -19,6 +19,7 @@ import {
|
||||
useGetImportedSecrets,
|
||||
useGetProjectFolders,
|
||||
useGetProjectSecrets,
|
||||
useGetSecretApprovalPolicyOfABoard,
|
||||
useGetSecretImports,
|
||||
useGetUserWsKey,
|
||||
useGetWorkspaceSnapshotList,
|
||||
@@ -118,6 +119,13 @@ export const SecretMainPage = () => {
|
||||
// fetch tags
|
||||
const { data: tags } = useGetWsTags(canReadSecret ? workspaceId : "");
|
||||
|
||||
const { data: boardPolicy } = useGetSecretApprovalPolicyOfABoard({
|
||||
workspaceId,
|
||||
environment,
|
||||
secretPath
|
||||
});
|
||||
const isProtectedBranch = Boolean(boardPolicy);
|
||||
|
||||
const {
|
||||
data: snapshotList,
|
||||
isFetchingNextPage: isFetchingNextSnapshotList,
|
||||
@@ -207,6 +215,7 @@ export const SecretMainPage = () => {
|
||||
secretPath={secretPath}
|
||||
isProjectRelated
|
||||
onEnvChange={handleEnvChange}
|
||||
isProtectedBranch={isProtectedBranch}
|
||||
/>
|
||||
</div>
|
||||
{!isRollbackMode ? (
|
||||
@@ -281,6 +290,7 @@ export const SecretMainPage = () => {
|
||||
workspaceId={workspaceId}
|
||||
secretPath={secretPath}
|
||||
decryptFileKey={decryptFileKey!}
|
||||
isProtectedBranch={isProtectedBranch}
|
||||
/>
|
||||
)}
|
||||
{!canReadSecret && folders?.length === 0 && <PermissionDeniedBanner />}
|
||||
@@ -292,6 +302,7 @@ export const SecretMainPage = () => {
|
||||
decryptFileKey={decryptFileKey!}
|
||||
secretPath={secretPath}
|
||||
autoCapitalize={currentWorkspace?.autoCapitalization}
|
||||
isProtectedBranch={isProtectedBranch}
|
||||
/>
|
||||
<SecretDropzone
|
||||
secrets={secrets}
|
||||
@@ -301,6 +312,7 @@ export const SecretMainPage = () => {
|
||||
secretPath={secretPath}
|
||||
isSmaller={isNotEmtpy}
|
||||
environments={currentWorkspace?.environments}
|
||||
isProtectedBranch={isProtectedBranch}
|
||||
/>
|
||||
<PitDrawer
|
||||
secretSnaphots={snapshotList}
|
||||
|
||||
@@ -23,6 +23,7 @@ type Props = {
|
||||
secretPath?: string;
|
||||
// modal props
|
||||
autoCapitalize?: boolean;
|
||||
isProtectedBranch?: boolean;
|
||||
};
|
||||
|
||||
export const CreateSecretForm = ({
|
||||
@@ -30,7 +31,8 @@ export const CreateSecretForm = ({
|
||||
workspaceId,
|
||||
decryptFileKey,
|
||||
secretPath = "/",
|
||||
autoCapitalize = true
|
||||
autoCapitalize = true,
|
||||
isProtectedBranch = false
|
||||
}: Props) => {
|
||||
const {
|
||||
register,
|
||||
@@ -62,7 +64,9 @@ export const CreateSecretForm = ({
|
||||
reset();
|
||||
createNotification({
|
||||
type: "success",
|
||||
text: "Successfully created secret"
|
||||
text: isProtectedBranch
|
||||
? "Requested changes have been send for review"
|
||||
: "Successfully created secret"
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
@@ -43,6 +43,7 @@ type Props = {
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
secrets?: DecryptedSecret[];
|
||||
isProtectedBranch?: boolean;
|
||||
};
|
||||
|
||||
export const SecretDropzone = ({
|
||||
@@ -52,7 +53,8 @@ export const SecretDropzone = ({
|
||||
decryptFileKey,
|
||||
environment,
|
||||
secretPath,
|
||||
secrets = []
|
||||
secrets = [],
|
||||
isProtectedBranch = false
|
||||
}: Props): JSX.Element => {
|
||||
const { t } = useTranslation();
|
||||
const [isDragActive, setDragActive] = useToggle();
|
||||
@@ -195,7 +197,9 @@ export const SecretDropzone = ({
|
||||
handlePopUpClose("overlapKeyWarning");
|
||||
createNotification({
|
||||
type: "success",
|
||||
text: "Successfully uploaded secrets"
|
||||
text: isProtectedBranch
|
||||
? "Uploaded changes have been send for review"
|
||||
: "Successfully uploaded secrets"
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
|
||||
@@ -49,7 +49,8 @@ type Props = {
|
||||
onDeleteSecret: () => void;
|
||||
onSaveSecret: (
|
||||
orgSec: DecryptedSecret,
|
||||
modSec: Omit<DecryptedSecret, "tags"> & { tags: { _id: string }[] }
|
||||
modSec: Omit<DecryptedSecret, "tags"> & { tags: { _id: string }[] },
|
||||
cb?: () => void
|
||||
) => Promise<void>;
|
||||
tags: WsTag[];
|
||||
onCreateTag: () => void;
|
||||
@@ -143,7 +144,7 @@ export const SecretDetailSidebar = ({
|
||||
};
|
||||
|
||||
const handleFormSubmit = async (data: TFormSchema) => {
|
||||
await onSaveSecret(secret, { ...secret, ...data });
|
||||
await onSaveSecret(secret, { ...secret, ...data }, () => reset());
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -54,7 +54,8 @@ type Props = {
|
||||
secret: DecryptedSecret;
|
||||
onSaveSecret: (
|
||||
orgSec: DecryptedSecret,
|
||||
modSec: Omit<DecryptedSecret, "tags"> & { tags: { _id: string }[] }
|
||||
modSec: Omit<DecryptedSecret, "tags"> & { tags: { _id: string }[] },
|
||||
cb?: () => void
|
||||
) => Promise<void>;
|
||||
onDeleteSecret: (sec: DecryptedSecret) => void;
|
||||
onDetailViewSecret: (sec: DecryptedSecret) => void;
|
||||
@@ -148,13 +149,14 @@ export const SecretItem = memo(
|
||||
);
|
||||
setValue("valueOverride", secret?.valueOverride, { shouldDirty: !isUnsavedOverride });
|
||||
} else {
|
||||
reset();
|
||||
setValue("overrideAction", SecretActionType.Modified, { shouldDirty: true });
|
||||
setValue("valueOverride", "", { shouldDirty: true });
|
||||
}
|
||||
};
|
||||
|
||||
const handleFormSubmit = async (data: TFormSchema) => {
|
||||
await onSaveSecret(secret, { ...secret, ...data });
|
||||
await onSaveSecret(secret, { ...secret, ...data }, () => reset());
|
||||
};
|
||||
|
||||
const handleTagSelect = (tag: WsTag) => {
|
||||
|
||||
@@ -27,6 +27,7 @@ type Props = {
|
||||
sortDir?: SortDir;
|
||||
tags?: WsTag[];
|
||||
isVisible?: boolean;
|
||||
isProtectedBranch?: boolean;
|
||||
};
|
||||
|
||||
const reorderSecretGroupByUnderscore = (secrets: DecryptedSecret[], sortDir: SortDir) => {
|
||||
@@ -84,7 +85,8 @@ export const SecretListView = ({
|
||||
filter,
|
||||
sortDir = SortDir.ASC,
|
||||
tags: wsTags = [],
|
||||
isVisible
|
||||
isVisible,
|
||||
isProtectedBranch = false
|
||||
}: Props) => {
|
||||
const { createNotification } = useNotificationContext();
|
||||
const queryClient = useQueryClient();
|
||||
@@ -178,8 +180,10 @@ export const SecretListView = ({
|
||||
const handleSaveSecret = useCallback(
|
||||
async (
|
||||
orgSecret: DecryptedSecret,
|
||||
modSecret: Omit<DecryptedSecret, "tags"> & { tags: { _id: string }[] }
|
||||
modSecret: Omit<DecryptedSecret, "tags"> & { tags: { _id: string }[] },
|
||||
cb?: () => void
|
||||
) => {
|
||||
console.log(orgSecret, modSecret);
|
||||
const { key: oldKey } = orgSecret;
|
||||
const { key, value, overrideAction, idOverride, valueOverride, tags, comment } = modSecret;
|
||||
const hasKeyChanged = oldKey !== key;
|
||||
@@ -193,6 +197,19 @@ export const SecretListView = ({
|
||||
) && isSameTags;
|
||||
|
||||
try {
|
||||
// personal secret change
|
||||
if (overrideAction === "deleted") {
|
||||
await handleSecretOperation("delete", "personal", oldKey);
|
||||
} else if (overrideAction && idOverride) {
|
||||
await handleSecretOperation("update", "personal", oldKey, {
|
||||
value: valueOverride,
|
||||
newKey: hasKeyChanged ? key : undefined,
|
||||
skipMultilineEncoding: modSecret.skipMultilineEncoding
|
||||
});
|
||||
} else if (overrideAction) {
|
||||
await handleSecretOperation("create", "personal", oldKey, { value: valueOverride });
|
||||
}
|
||||
|
||||
// shared secret change
|
||||
if (!isSharedSecUnchanged) {
|
||||
await handleSecretOperation("update", "shared", oldKey, {
|
||||
@@ -202,19 +219,7 @@ export const SecretListView = ({
|
||||
newKey: hasKeyChanged ? key : undefined,
|
||||
skipMultilineEncoding: modSecret.skipMultilineEncoding
|
||||
});
|
||||
}
|
||||
|
||||
// personal secret change
|
||||
if (overrideAction === "deleted") {
|
||||
await handleSecretOperation("delete", "personal", key);
|
||||
} else if (overrideAction && idOverride) {
|
||||
await handleSecretOperation("update", "personal", oldKey, {
|
||||
value: valueOverride,
|
||||
newKey: hasKeyChanged ? key : undefined,
|
||||
skipMultilineEncoding: modSecret.skipMultilineEncoding
|
||||
});
|
||||
} else if (overrideAction) {
|
||||
await handleSecretOperation("create", "personal", key, { value: valueOverride });
|
||||
if (isProtectedBranch) cb?.();
|
||||
}
|
||||
|
||||
queryClient.invalidateQueries(
|
||||
@@ -229,7 +234,9 @@ export const SecretListView = ({
|
||||
handlePopUpClose("secretDetail");
|
||||
createNotification({
|
||||
type: "success",
|
||||
text: "Successfully saved secrets"
|
||||
text: isProtectedBranch
|
||||
? "Requested changes have been sent for review"
|
||||
: "Successfully saved secrets"
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
@@ -259,7 +266,9 @@ export const SecretListView = ({
|
||||
handlePopUpClose("secretDetail");
|
||||
createNotification({
|
||||
type: "success",
|
||||
text: "Successfully deleted secret"
|
||||
text: isProtectedBranch
|
||||
? "Requested changes have been sent for review"
|
||||
: "Successfully deleted secret"
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
Reference in New Issue
Block a user