mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Rework of secret imports on the overview page
This commit is contained in:
@@ -182,7 +182,8 @@ export const useGetImportedSecretsAllEnvs = ({
|
|||||||
comment: encSecret.secretComment,
|
comment: encSecret.secretComment,
|
||||||
createdAt: encSecret.createdAt,
|
createdAt: encSecret.createdAt,
|
||||||
updatedAt: encSecret.updatedAt,
|
updatedAt: encSecret.updatedAt,
|
||||||
version: encSecret.version
|
version: encSecret.version,
|
||||||
|
sourceEnv: env
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
})),
|
})),
|
||||||
|
|||||||
@@ -86,13 +86,5 @@ export const useSecretOverview = (secrets: DashboardProjectSecretsOverview["secr
|
|||||||
[secrets]
|
[secrets]
|
||||||
);
|
);
|
||||||
|
|
||||||
const getSecretByKey = useCallback(
|
return { secKeys, getEnvSecretKeyCount };
|
||||||
(env: string, key: string) => {
|
|
||||||
const sec = secrets?.find((s) => s.env === env && s.key === key);
|
|
||||||
return sec;
|
|
||||||
},
|
|
||||||
[secrets]
|
|
||||||
);
|
|
||||||
|
|
||||||
return { secKeys, getSecretByKey, getEnvSecretKeyCount };
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ import { CreateSecretForm } from "./components/CreateSecretForm";
|
|||||||
import { FolderBreadCrumbs } from "./components/FolderBreadCrumbs";
|
import { FolderBreadCrumbs } from "./components/FolderBreadCrumbs";
|
||||||
import { SecretOverviewDynamicSecretRow } from "./components/SecretOverviewDynamicSecretRow";
|
import { SecretOverviewDynamicSecretRow } from "./components/SecretOverviewDynamicSecretRow";
|
||||||
import { SecretOverviewFolderRow } from "./components/SecretOverviewFolderRow";
|
import { SecretOverviewFolderRow } from "./components/SecretOverviewFolderRow";
|
||||||
import { SecretOverviewImportListView } from "./components/SecretOverviewImportListView";
|
|
||||||
import {
|
import {
|
||||||
SecretNoAccessOverviewTableRow,
|
SecretNoAccessOverviewTableRow,
|
||||||
SecretOverviewTableRow
|
SecretOverviewTableRow
|
||||||
@@ -203,12 +202,16 @@ export const OverviewPage = () => {
|
|||||||
setVisibleEnvs(userAvailableEnvs);
|
setVisibleEnvs(userAvailableEnvs);
|
||||||
}, [userAvailableEnvs]);
|
}, [userAvailableEnvs]);
|
||||||
|
|
||||||
const { isImportedSecretPresentInEnv, getImportedSecretByKey, getEnvImportedSecretKeyCount } =
|
const {
|
||||||
useGetImportedSecretsAllEnvs({
|
secretImports,
|
||||||
projectId: workspaceId,
|
isImportedSecretPresentInEnv,
|
||||||
path: secretPath,
|
getImportedSecretByKey,
|
||||||
environments: (userAvailableEnvs || []).map(({ slug }) => slug)
|
getEnvImportedSecretKeyCount
|
||||||
});
|
} = useGetImportedSecretsAllEnvs({
|
||||||
|
projectId: workspaceId,
|
||||||
|
path: secretPath,
|
||||||
|
environments: (userAvailableEnvs || []).map(({ slug }) => slug)
|
||||||
|
});
|
||||||
|
|
||||||
const { isPending: isOverviewLoading, data: overview } = useGetProjectSecretsOverview(
|
const { isPending: isOverviewLoading, data: overview } = useGetProjectSecretsOverview(
|
||||||
{
|
{
|
||||||
@@ -232,7 +235,6 @@ export const OverviewPage = () => {
|
|||||||
secrets,
|
secrets,
|
||||||
folders,
|
folders,
|
||||||
dynamicSecrets,
|
dynamicSecrets,
|
||||||
imports,
|
|
||||||
totalFolderCount,
|
totalFolderCount,
|
||||||
totalSecretCount,
|
totalSecretCount,
|
||||||
totalDynamicSecretCount,
|
totalDynamicSecretCount,
|
||||||
@@ -244,16 +246,20 @@ export const OverviewPage = () => {
|
|||||||
totalUniqueDynamicSecretsInPage
|
totalUniqueDynamicSecretsInPage
|
||||||
} = overview ?? {};
|
} = overview ?? {};
|
||||||
|
|
||||||
const importsShaped = imports
|
const secretImportsShaped = secretImports
|
||||||
?.filter((el) => !el.isReserved)
|
?.flatMap(({ data }) => data)
|
||||||
?.map(({ importPath, importEnv }) => ({ importPath, importEnv }))
|
.filter(Boolean)
|
||||||
.filter(
|
.flatMap((item) => item?.secrets || []);
|
||||||
(el, index, self) =>
|
|
||||||
index ===
|
const handleIsImportedSecretPresentInEnv = (envSlug: string, secretName: string) => {
|
||||||
self.findIndex(
|
if (secrets?.some((s) => s.key === secretName && s.env === envSlug)) {
|
||||||
(item) => item.importPath === el.importPath && item.importEnv.slug === el.importEnv.slug
|
return false;
|
||||||
)
|
}
|
||||||
);
|
if (secretImportsShaped.some((s) => s.key === secretName && s.sourceEnv === envSlug)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return isImportedSecretPresentInEnv(envSlug, secretName);
|
||||||
|
};
|
||||||
|
|
||||||
useResetPageHelper({
|
useResetPageHelper({
|
||||||
totalCount,
|
totalCount,
|
||||||
@@ -267,7 +273,18 @@ export const OverviewPage = () => {
|
|||||||
const { dynamicSecretNames, isDynamicSecretPresentInEnv } =
|
const { dynamicSecretNames, isDynamicSecretPresentInEnv } =
|
||||||
useDynamicSecretOverview(dynamicSecrets);
|
useDynamicSecretOverview(dynamicSecrets);
|
||||||
|
|
||||||
const { secKeys, getSecretByKey, getEnvSecretKeyCount } = useSecretOverview(secrets);
|
const { secKeys, getEnvSecretKeyCount } = useSecretOverview(
|
||||||
|
secrets?.concat(secretImportsShaped) || []
|
||||||
|
);
|
||||||
|
|
||||||
|
const getSecretByKey = useCallback(
|
||||||
|
(env: string, key: string) => {
|
||||||
|
const sec = secrets?.find((s) => s.env === env && s.key === key);
|
||||||
|
return sec;
|
||||||
|
},
|
||||||
|
[secrets]
|
||||||
|
);
|
||||||
|
|
||||||
const { data: tags } = useGetWsTags(
|
const { data: tags } = useGetWsTags(
|
||||||
permission.can(ProjectPermissionActions.Read, ProjectPermissionSub.Tags) ? workspaceId : ""
|
permission.can(ProjectPermissionActions.Read, ProjectPermissionSub.Tags) ? workspaceId : ""
|
||||||
);
|
);
|
||||||
@@ -1124,24 +1141,13 @@ export const OverviewPage = () => {
|
|||||||
key={`overview-${dynamicSecretName}-${index + 1}`}
|
key={`overview-${dynamicSecretName}-${index + 1}`}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{filter.import &&
|
|
||||||
importsShaped &&
|
|
||||||
importsShaped?.length > 0 &&
|
|
||||||
importsShaped?.map((item, index) => (
|
|
||||||
<SecretOverviewImportListView
|
|
||||||
secretImport={item}
|
|
||||||
environments={visibleEnvs}
|
|
||||||
key={`overview-secret-input-${index + 1}`}
|
|
||||||
allSecretImports={imports}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
{secKeys.map((key, index) => (
|
{secKeys.map((key, index) => (
|
||||||
<SecretOverviewTableRow
|
<SecretOverviewTableRow
|
||||||
isSelected={Boolean(selectedEntries.secret[key])}
|
isSelected={Boolean(selectedEntries.secret[key])}
|
||||||
onToggleSecretSelect={() => toggleSelectedEntry(EntryType.SECRET, key)}
|
onToggleSecretSelect={() => toggleSelectedEntry(EntryType.SECRET, key)}
|
||||||
secretPath={secretPath}
|
secretPath={secretPath}
|
||||||
getImportedSecretByKey={getImportedSecretByKey}
|
getImportedSecretByKey={getImportedSecretByKey}
|
||||||
isImportedSecretPresentInEnv={isImportedSecretPresentInEnv}
|
isImportedSecretPresentInEnv={handleIsImportedSecretPresentInEnv}
|
||||||
onSecretCreate={handleSecretCreate}
|
onSecretCreate={handleSecretCreate}
|
||||||
onSecretDelete={handleSecretDelete}
|
onSecretDelete={handleSecretDelete}
|
||||||
onSecretUpdate={handleSecretUpdate}
|
onSecretUpdate={handleSecretUpdate}
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
import { faCheck, faFileImport, faXmark } from "@fortawesome/free-solid-svg-icons";
|
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
||||||
import { twMerge } from "tailwind-merge";
|
|
||||||
|
|
||||||
import { Td, Tr } from "@app/components/v2";
|
|
||||||
import { TSecretImport, WorkspaceEnv } from "@app/hooks/api/types";
|
|
||||||
import { EnvFolderIcon } from "@app/pages/secret-manager/SecretDashboardPage/components/SecretImportListView/SecretImportItem";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
secretImport: { importPath: string; importEnv: WorkspaceEnv };
|
|
||||||
environments: { name: string; slug: string }[];
|
|
||||||
allSecretImports?: TSecretImport[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SecretOverviewImportListView = ({
|
|
||||||
secretImport,
|
|
||||||
environments = [],
|
|
||||||
allSecretImports = []
|
|
||||||
}: Props) => {
|
|
||||||
const isSecretPresentInEnv = (envSlug: string) => {
|
|
||||||
return allSecretImports.some((item) => {
|
|
||||||
if (item.isReplication) {
|
|
||||||
if (
|
|
||||||
item.importPath === secretImport.importPath &&
|
|
||||||
item.importEnv.slug === secretImport.importEnv.slug
|
|
||||||
) {
|
|
||||||
const reservedItem = allSecretImports.find((element) =>
|
|
||||||
element.importPath.includes(`__reserve_replication_${item.id}`)
|
|
||||||
);
|
|
||||||
// If the reserved item exists, check if the envSlug matches
|
|
||||||
if (reservedItem) {
|
|
||||||
return reservedItem.environment === envSlug;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If the item is not replication, check if the envSlug matches directly
|
|
||||||
return (
|
|
||||||
item.environment === envSlug &&
|
|
||||||
item.importPath === secretImport.importPath &&
|
|
||||||
item.importEnv.slug === secretImport.importEnv.slug
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Tr className="group">
|
|
||||||
<Td className="sticky left-0 z-10 border-r border-mineshaft-600 bg-mineshaft-800 bg-clip-padding px-0 py-0 group-hover:bg-mineshaft-700">
|
|
||||||
<div className="group flex cursor-pointer">
|
|
||||||
<div className="flex w-11 items-center py-2 pl-5 text-green-700">
|
|
||||||
<FontAwesomeIcon icon={faFileImport} />
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-grow items-center py-2 pl-4 pr-2">
|
|
||||||
<EnvFolderIcon
|
|
||||||
env={secretImport.importEnv.slug || ""}
|
|
||||||
secretPath={secretImport.importPath || ""}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Td>
|
|
||||||
{environments.map(({ slug }, i) => {
|
|
||||||
const isPresent = isSecretPresentInEnv(slug);
|
|
||||||
return (
|
|
||||||
<Td
|
|
||||||
key={`sec-overview-${slug}-${i + 1}-value`}
|
|
||||||
className={twMerge(
|
|
||||||
"px-0 py-0 group-hover:bg-mineshaft-700",
|
|
||||||
isPresent ? "text-green-600" : "text-red-600"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div className="h-full w-full border-r border-mineshaft-600 px-5 py-[0.85rem]">
|
|
||||||
<div className="flex justify-center">
|
|
||||||
<FontAwesomeIcon
|
|
||||||
// eslint-disable-next-line no-nested-ternary
|
|
||||||
icon={isSecretPresentInEnv(slug) ? faCheck : faXmark}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Td>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Tr>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { SecretOverviewImportListView } from "./SecretOverviewImportListView";
|
|
||||||
@@ -162,7 +162,7 @@ function SecretRenameRow({ environments, getSecretByKey, secretKey, secretPath }
|
|||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<Input
|
<Input
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
isReadOnly={isReadOnly}
|
isReadOnly={isReadOnly || secrets.filter(Boolean).length === 0}
|
||||||
autoCapitalization={currentWorkspace?.autoCapitalization}
|
autoCapitalization={currentWorkspace?.autoCapitalization}
|
||||||
variant="plain"
|
variant="plain"
|
||||||
isDisabled={isOverriden}
|
isDisabled={isOverriden}
|
||||||
|
|||||||
Reference in New Issue
Block a user