mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
make replicated secrets more intuitive
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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" });
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user