Merge branch 'heads/main' into daniel/srp-removal-round-2

This commit is contained in:
Daniel Hougaard
2025-07-30 04:44:57 +04:00
474 changed files with 5372 additions and 28647 deletions
@@ -17,7 +17,7 @@ export const useCreateAccessApprovalPolicy = () => {
return useMutation<object, object, TCreateAccessPolicyDTO>({
mutationFn: async ({
environment,
environments,
projectSlug,
approvals,
approvers,
@@ -29,7 +29,7 @@ export const useCreateAccessApprovalPolicy = () => {
approvalsRequired
}) => {
const { data } = await apiRequest.post("/api/v1/access-approvals/policies", {
environment,
environments,
projectSlug,
approvals,
bypassers,
@@ -63,7 +63,8 @@ export const useUpdateAccessApprovalPolicy = () => {
secretPath,
enforcementLevel,
allowedSelfApprovals,
approvalsRequired
approvalsRequired,
environments
}) => {
const { data } = await apiRequest.patch(`/api/v1/access-approvals/policies/${id}`, {
approvals,
@@ -73,7 +74,8 @@ export const useUpdateAccessApprovalPolicy = () => {
name,
enforcementLevel,
allowedSelfApprovals,
approvalsRequired
approvalsRequired,
environments
});
return data;
},
@@ -8,9 +8,8 @@ export type TAccessApprovalPolicy = {
name: string;
approvals: number;
secretPath: string;
envId: string;
workspace: string;
environment: WorkspaceEnv;
environments: WorkspaceEnv[];
projectId: string;
policyType: PolicyType;
approversRequired: boolean;
@@ -166,7 +165,7 @@ export type TGetSecretApprovalPolicyOfBoardDTO = {
export type TCreateAccessPolicyDTO = {
projectSlug: string;
name?: string;
environment: string;
environments: string[];
approvers?: Approver[];
bypassers?: Bypasser[];
approvals?: number;
@@ -182,7 +181,7 @@ export type TUpdateAccessPolicyDTO = {
approvers?: Approver[];
bypassers?: Bypasser[];
secretPath?: string;
environment?: string;
environments?: string[];
approvals?: number;
enforcementLevel?: EnforcementLevel;
allowedSelfApprovals: boolean;
+1
View File
@@ -51,6 +51,7 @@ export type TServerConfig = {
invalidatingCache: boolean;
fipsEnabled: boolean;
envOverrides?: Record<string, string>;
paramsFolderSecretDetectionEnabled: boolean;
};
export type TUpdateServerConfigDTO = {
@@ -2,15 +2,26 @@ import { AppConnection } from "@app/hooks/api/appConnections/enums";
import { TRootAppConnection } from "@app/hooks/api/appConnections/types/root-connection";
export enum AzureClientSecretsConnectionMethod {
OAuth = "oauth"
OAuth = "oauth",
ClientSecret = "client-secret"
}
export type TAzureClientSecretsConnection = TRootAppConnection & {
app: AppConnection.AzureClientSecrets;
} & {
method: AzureClientSecretsConnectionMethod.OAuth;
credentials: {
code: string;
tenantId: string;
};
};
} & (
| {
method: AzureClientSecretsConnectionMethod.OAuth;
credentials: {
code: string;
tenantId: string;
};
}
| {
method: AzureClientSecretsConnectionMethod.ClientSecret;
credentials: {
clientSecret: string;
clientId: string;
tenantId: string;
};
}
);
@@ -11,6 +11,7 @@ export type TGitHubConnection = TRootAppConnection & { app: AppConnection.GitHub
method: GitHubConnectionMethod.OAuth;
credentials: {
code: string;
host?: string;
};
}
| {
@@ -18,6 +19,7 @@ export type TGitHubConnection = TRootAppConnection & { app: AppConnection.GitHub
credentials: {
code: string;
installationId: string;
host?: string;
};
}
);
@@ -86,6 +86,7 @@ export const useCreateIdentity = () => {
queryClient.invalidateQueries({
queryKey: subscriptionQueryKeys.getOrgSubsription(organizationId)
});
queryClient.invalidateQueries({ queryKey: identitiesKeys.searchIdentitiesRoot });
}
});
};
@@ -110,6 +111,7 @@ export const useUpdateIdentity = () => {
queryKey: organizationKeys.getOrgIdentityMemberships(organizationId)
});
queryClient.invalidateQueries({ queryKey: identitiesKeys.getIdentityById(identityId) });
queryClient.invalidateQueries({ queryKey: identitiesKeys.searchIdentitiesRoot });
}
});
};
@@ -130,6 +132,7 @@ export const useDeleteIdentity = () => {
queryClient.invalidateQueries({
queryKey: subscriptionQueryKeys.getOrgSubsription(organizationId)
});
queryClient.invalidateQueries({ queryKey: identitiesKeys.searchIdentitiesRoot });
}
});
};
@@ -25,7 +25,9 @@ import {
export const identitiesKeys = {
getIdentityById: (identityId: string) => [{ identityId }, "identity"] as const,
searchIdentities: (dto: TSearchIdentitiesDTO) => ["identity", "search", dto] as const,
searchIdentitiesRoot: ["identity", "search"] as const,
searchIdentities: (dto: TSearchIdentitiesDTO) =>
[...identitiesKeys.searchIdentitiesRoot, dto] as const,
getIdentityUniversalAuth: (identityId: string) =>
[{ identityId }, "identity-universal-auth"] as const,
getIdentityUniversalAuthClientSecrets: (identityId: string) =>
@@ -0,0 +1 @@
export * from "./mutations";
+24 -1
View File
@@ -15,7 +15,7 @@ export const useImportEnvKey = () => {
formData.append("file", file);
try {
const response = await apiRequest.post("/api/v3/migrate/env-key/", formData, {
const response = await apiRequest.post("/api/v3/external-migration/env-key/", formData, {
headers: {
"Content-Type": "multipart/form-data"
},
@@ -39,3 +39,26 @@ export const useImportEnvKey = () => {
}
});
};
export const useImportVault = () => {
return useMutation({
mutationFn: async ({
vaultAccessToken,
vaultNamespace,
vaultUrl,
mappingType
}: {
vaultAccessToken: string;
vaultNamespace?: string;
vaultUrl: string;
mappingType: string;
}) => {
await apiRequest.post("/api/v3/external-migration/vault/", {
vaultAccessToken,
vaultNamespace,
vaultUrl,
mappingType
});
}
});
};
@@ -10,7 +10,7 @@ export const useCreateSecretApprovalPolicy = () => {
return useMutation<object, object, TCreateSecretPolicyDTO>({
mutationFn: async ({
environment,
environments,
workspaceId,
approvals,
approvers,
@@ -21,7 +21,7 @@ export const useCreateSecretApprovalPolicy = () => {
allowedSelfApprovals
}) => {
const { data } = await apiRequest.post("/api/v1/secret-approvals", {
environment,
environments,
workspaceId,
approvals,
approvers,
@@ -53,7 +53,8 @@ export const useUpdateSecretApprovalPolicy = () => {
secretPath,
name,
enforcementLevel,
allowedSelfApprovals
allowedSelfApprovals,
environments
}) => {
const { data } = await apiRequest.patch(`/api/v1/secret-approvals/${id}`, {
approvals,
@@ -62,7 +63,8 @@ export const useUpdateSecretApprovalPolicy = () => {
secretPath,
name,
enforcementLevel,
allowedSelfApprovals
allowedSelfApprovals,
environments
});
return data;
},
@@ -5,8 +5,7 @@ export type TSecretApprovalPolicy = {
id: string;
workspace: string;
name: string;
envId: string;
environment: WorkspaceEnv;
environments: WorkspaceEnv[];
secretPath?: string;
approvals: number;
approvers: Approver[];
@@ -48,7 +47,7 @@ export type TGetSecretApprovalPolicyOfBoardDTO = {
export type TCreateSecretPolicyDTO = {
workspaceId: string;
name?: string;
environment: string;
environments: string[];
secretPath: string;
approvers?: Approver[];
bypassers?: Bypasser[];
@@ -68,6 +67,7 @@ export type TUpdateSecretPolicyDTO = {
enforcementLevel?: EnforcementLevel;
// for invalidating list
workspaceId: string;
environments?: string[];
};
export type TDeleteSecretPolicyDTO = {
@@ -1,7 +1,6 @@
import { SecretSync, SecretSyncImportBehavior } from "@app/hooks/api/secretSyncs";
import { DiscriminativePick } from "@app/types";
import { TRenderSync } from "../render-sync";
import { TOnePassSync } from "./1password-sync";
import { TAwsParameterStoreSync } from "./aws-parameter-store-sync";
import { TAwsSecretsManagerSync } from "./aws-secrets-manager-sync";
@@ -24,6 +23,7 @@ import { THerokuSync } from "./heroku-sync";
import { THumanitecSync } from "./humanitec-sync";
import { TOCIVaultSync } from "./oci-vault-sync";
import { TRailwaySync } from "./railway-sync";
import { TRenderSync } from "./render-sync";
import { TSupabaseSync } from "./supabase";
import { TTeamCitySync } from "./teamcity-sync";
import { TTerraformCloudSync } from "./terraform-cloud-sync";
@@ -1,6 +1,6 @@
import { AppConnection } from "@app/hooks/api/appConnections/enums";
import { SecretSync } from "@app/hooks/api/secretSyncs";
import { TRootSecretSync } from "@app/hooks/api/secretSyncs/types/root-sync";
import { RootSyncOptions, TRootSecretSync } from "@app/hooks/api/secretSyncs/types/root-sync";
export type TRenderSync = TRootSecretSync & {
destination: SecretSync.Render;
@@ -16,6 +16,10 @@ export type TRenderSync = TRootSecretSync & {
name: string;
id: string;
};
syncOptions: RootSyncOptions & {
autoRedeployServices?: boolean;
};
};
export enum RenderSyncScope {
+4 -2
View File
@@ -281,7 +281,8 @@ export const useUpdateProject = () => {
newProjectDescription,
newSlug,
secretSharing,
showSnapshotsLegacy
showSnapshotsLegacy,
secretDetectionIgnoreValues
}) => {
const { data } = await apiRequest.patch<{ workspace: Workspace }>(
`/api/v1/workspace/${projectID}`,
@@ -290,7 +291,8 @@ export const useUpdateProject = () => {
description: newProjectDescription,
slug: newSlug,
secretSharing,
showSnapshotsLegacy
showSnapshotsLegacy,
secretDetectionIgnoreValues
}
);
return data.workspace;
@@ -40,6 +40,7 @@ export type Workspace = {
hasDeleteProtection: boolean;
secretSharing: boolean;
showSnapshotsLegacy: boolean;
secretDetectionIgnoreValues: string[];
};
export type WorkspaceEnv = {
@@ -81,6 +82,7 @@ export type UpdateProjectDTO = {
newSlug?: string;
secretSharing?: boolean;
showSnapshotsLegacy?: boolean;
secretDetectionIgnoreValues?: string[];
};
export type UpdatePitVersionLimitDTO = { projectSlug: string; pitVersionLimit: number };
+2 -1
View File
@@ -49,7 +49,8 @@ export const usePathAccessPolicies = ({ secretPath, environment }: Params) => {
return useMemo(() => {
const pathPolicies = policies?.filter(
(policy) =>
policy.environment.slug === environment && matchesPath(secretPath, policy.secretPath)
policy.environments?.some((env) => env.slug === environment) &&
matchesPath(secretPath, policy.secretPath)
);
return {
@@ -0,0 +1,71 @@
import { MouseEvent, useCallback, useEffect, useRef, useState } from "react";
type Params = {
minWidth: number;
maxWidth: number;
initialWidth: number;
};
export const useResizableColWidth = ({ minWidth, maxWidth, initialWidth }: Params) => {
const [colWidth, setColWidth] = useState(initialWidth);
const [isResizing, setIsResizing] = useState(false);
const startX = useRef(0);
const startWidth = useRef(0);
const handleMouseDown = useCallback(
(e: MouseEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
setIsResizing(true);
startX.current = e.clientX;
startWidth.current = colWidth;
},
[colWidth]
);
const handleMouseMove = useCallback(
(e: MouseEvent) => {
if (!isResizing) return;
const deltaX = e.clientX - startX.current;
const newWidth = Math.max(minWidth, Math.min(maxWidth, startWidth.current + deltaX));
setColWidth(newWidth);
},
[isResizing]
);
const handleMouseUp = useCallback(() => {
setIsResizing(false);
}, []);
useEffect(() => {
if (isResizing) {
document.addEventListener(
"mousemove",
// @ts-expect-error native discrepancy
handleMouseMove
);
document.addEventListener("mouseup", handleMouseUp);
document.body.style.cursor = "ew-resize";
document.body.style.userSelect = "none";
}
return () => {
document.removeEventListener(
"mousemove",
// @ts-expect-error native discrepancy
handleMouseMove
);
document.removeEventListener("mouseup", handleMouseUp);
document.body.style.cursor = "";
document.body.style.userSelect = "";
};
}, [isResizing, handleMouseMove, handleMouseUp]);
return {
colWidth,
handleMouseDown,
isResizing
};
};