diff --git a/backend/src/ee/services/secret-replication/secret-replication-dal.ts b/backend/src/ee/services/secret-replication/secret-replication-dal.ts index e1013df99..5426a51cf 100644 --- a/backend/src/ee/services/secret-replication/secret-replication-dal.ts +++ b/backend/src/ee/services/secret-replication/secret-replication-dal.ts @@ -9,6 +9,16 @@ export type TSecretReplicationDALFactory = ReturnType { 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} 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>} 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 diff --git a/backend/src/ee/services/secret-replication/secret-replication-service.ts b/backend/src/ee/services/secret-replication/secret-replication-service.ts index d1b970b68..1f8b46058 100644 --- a/backend/src/ee/services/secret-replication/secret-replication-service.ts +++ b/backend/src/ee/services/secret-replication/secret-replication-service.ts @@ -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) diff --git a/backend/src/services/secret-folder/secret-folder-service.ts b/backend/src/services/secret-folder/secret-folder-service.ts index ee537577e..97258c006 100644 --- a/backend/src/services/secret-folder/secret-folder-service.ts +++ b/backend/src/services/secret-folder/secret-folder-service.ts @@ -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" }); diff --git a/frontend/src/views/SecretMainPage/components/ActionBar/CreateSecretImportForm.tsx b/frontend/src/views/SecretMainPage/components/ActionBar/CreateSecretImportForm.tsx index f579852a2..7f9f2a4fe 100644 --- a/frontend/src/views/SecretMainPage/components/ActionBar/CreateSecretImportForm.tsx +++ b/frontend/src/views/SecretMainPage/components/ActionBar/CreateSecretImportForm.tsx @@ -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." } > )} diff --git a/frontend/src/views/SecretMainPage/components/SecretImportListView/SecretImportItem.tsx b/frontend/src/views/SecretMainPage/components/SecretImportListView/SecretImportItem.tsx index 07c66f17c..fee86bc14 100644 --- a/frontend/src/views/SecretMainPage/components/SecretImportListView/SecretImportItem.tsx +++ b/frontend/src/views/SecretMainPage/components/SecretImportListView/SecretImportItem.tsx @@ -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; }) => (
{env || "-"}
{secretPath && (
- {isReplication && Replication Mode} + {/* {isReplication && Replication Mode} */} {secretPath}
@@ -168,7 +167,7 @@ export const SecretImportItem = ({