make replicated secrets more intuitive

This commit is contained in:
Maidul Islam
2024-05-30 16:38:01 -04:00
committed by =
parent 41914e0027
commit c67642786f
5 changed files with 29 additions and 13 deletions

View File

@@ -9,6 +9,16 @@ export type TSecretReplicationDALFactory = ReturnType<typeof secretReplicationDA
export const secretReplicationDALFactory = (db: TDbClient) => {
const orm = ormify(db, TableName.SecretVersion);
/**
* Retrieves secret versions based on the specified filter criteria.
*
* @param {Object} filter - The filter criteria for querying secret versions.
* @param {string} filter.folderId - The ID of the folder containing the secrets.
* @param {Array<Object>} filter.secrets - An array of secret objects containing the ID and version of each secret.
* @param {Knex} [tx] - An optional Knex transaction object. If provided, the query will be executed within this transaction.
*
* @returns {Promise<Array<Object>>} A promise that resolves to an array of secret version documents that match the filter criteria.
*/
const findSecretVersions = async (
filter: { folderId: string; secrets: { id: string; version: number }[] },
tx?: Knex

View File

@@ -84,7 +84,7 @@ export const secretReplicationServiceFactory = ({
pickOnlyImportIds,
_deDupeReplicationQueue: deDupeReplicationQueue,
_deDupeQueue: deDupeQueue
} = job.data;
} = job.data; // source import details (this is where the secrets are to be synced from)
// filter for initial filling
let secretImports = await secretImportDAL.find({
@@ -97,8 +97,10 @@ export const secretReplicationServiceFactory = ({
: secretImports;
if (!secretImports.length || !secrets.length) return;
// unfiltered secrets to be replicated
// unfiltered secrets to be replicated (will fetch the latest versions in case another queue already processed this request)
const toBeReplicatedSecrets = await secretReplicationDAL.findSecretVersions({ folderId, secrets });
// case: https://www.notion.so/infisical/Secret-Replication-6907fbe3130c4124976f7cba1b9fc4c7
const replicatedSecrets = toBeReplicatedSecrets.filter(
({ version, latestReplicatedVersion, secretBlindIndex }) =>
secretBlindIndex && (version === 1 || latestReplicatedVersion <= version)

View File

@@ -253,7 +253,7 @@ export const secretFolderServiceFactory = ({
const env = await projectEnvDAL.findOne({ projectId, slug: environment });
if (!env) throw new BadRequestError({ message: "Environment not found", name: "Update folder" });
const folder = await folderDAL
.findOne({ envId: env.id, id, parentId: parentFolder.id })
.findOne({ envId: env.id, id, parentId: parentFolder.id, isReserved: false })
// now folder api accepts id based change
// this is for cli backward compatiability and when cli removes this, we will remove this logic
.catch(() => folderDAL.findOne({ envId: env.id, name: id, parentId: parentFolder.id }));
@@ -328,7 +328,12 @@ export const secretFolderServiceFactory = ({
if (!parentFolder) throw new BadRequestError({ message: "Secret path not found" });
const [doc] = await folderDAL.delete(
{ envId: env.id, [uuidValidate(idOrName) ? "id" : "name"]: idOrName, parentId: parentFolder.id },
{
envId: env.id,
[uuidValidate(idOrName) ? "id" : "name"]: idOrName,
parentId: parentFolder.id,
isReserved: false
},
tx
);
if (!doc) throw new BadRequestError({ message: "Folder not found", name: "Delete folder" });

View File

@@ -156,8 +156,8 @@ export const CreateSecretImportForm = ({
errorText={error?.message}
helperText={
value
? "Manual control over when updates propagate in approval mode, giving you the flexibility to push changes as needed."
: "Instantaneous updates from the linked source on approval mode, ensuring real-time synchronization."
? "Secrets from the source will be automatically sent to the destination. If approval policies exist at the destination, the secrets will be sent as approval requests instead of being applied immediately."
: "Secrets from the source location will be imported to the selected destination immediately, ignoring any approval policies at the destination."
}
>
<Select
@@ -165,8 +165,8 @@ export const CreateSecretImportForm = ({
onValueChange={(val) => onChange(val === "true")}
className="w-full border border-mineshaft-500"
>
<SelectItem value="false">Linked Mode</SelectItem>
<SelectItem value="true">Replication Mode</SelectItem>
<SelectItem value="false">Ignore secret approval polices</SelectItem>
<SelectItem value="true">Respect secret approval polices</SelectItem>
</Select>
</FormControl>
)}

View File

@@ -24,7 +24,6 @@ import {
IconButton,
SecretInput,
TableContainer,
Tag,
Tooltip
} from "@app/components/v2";
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
@@ -47,17 +46,17 @@ type Props = {
export const EnvFolderIcon = ({
env,
secretPath,
isReplication
// isReplication
}: {
env: string;
secretPath: string;
isReplication?: boolean;
// isReplication?: boolean;
}) => (
<div className="inline-flex items-center space-x-2">
<div style={{ minWidth: "96px" }}>{env || "-"}</div>
{secretPath && (
<div className="inline-flex items-center space-x-2 border-l border-mineshaft-600 pl-2">
{isReplication && <Tag size="xs">Replication Mode</Tag>}
{/* {isReplication && <Tag size="xs">Replication Mode</Tag>} */}
<FontAwesomeIcon icon={faFolder} className="text-md text-green-700" />
<span>{secretPath}</span>
</div>
@@ -168,7 +167,7 @@ export const SecretImportItem = ({
<EnvFolderIcon
env={importEnv.slug || ""}
secretPath={secretImport?.importPath || ""}
isReplication={isReplication}
// isReplication={isReplication}
/>
</div>
<div className="flex items-center space-x-4 px-4 py-2">