Merge branch 'main' into feat/secretsBatchUI

This commit is contained in:
Carlos Monastyrski
2025-07-14 11:54:56 -03:00
259 changed files with 5578 additions and 534 deletions
@@ -170,7 +170,7 @@ export type TCreateAccessPolicyDTO = {
approvers?: Approver[];
bypassers?: Bypasser[];
approvals?: number;
secretPath?: string;
secretPath: string;
enforcementLevel?: EnforcementLevel;
allowedSelfApprovals: boolean;
approvalsRequired?: { numberOfApprovals: number; stepNumber: number }[];
+1
View File
@@ -40,6 +40,7 @@ export type TServerConfig = {
trustLdapEmails: boolean;
trustOidcEmails: boolean;
isSecretScanningDisabled: boolean;
kubernetesAutoFetchServiceAccountToken: boolean;
defaultAuthOrgSlug: string | null;
defaultAuthOrgId: string | null;
defaultAuthOrgAuthMethod?: string | null;
@@ -0,0 +1,2 @@
export * from "./queries";
export * from "./types";
@@ -0,0 +1,70 @@
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { appConnectionKeys } from "../queries";
import {
TBitbucketConnectionListRepositoriesResponse,
TBitbucketConnectionListWorkspacesResponse,
TBitbucketRepo,
TBitbucketWorkspace
} from "./types";
const bitbucketConnectionKeys = {
all: [...appConnectionKeys.all, "bitbucket"] as const,
listRepos: (connectionId: string, workspaceSlug: string) =>
[...bitbucketConnectionKeys.all, "repos", connectionId, workspaceSlug] as const,
listWorkspaces: (connectionId: string) =>
[...bitbucketConnectionKeys.all, "workspaces", connectionId] as const
};
export const useBitbucketConnectionListWorkspaces = (
connectionId: string,
options?: Omit<
UseQueryOptions<
TBitbucketWorkspace[],
unknown,
TBitbucketWorkspace[],
ReturnType<typeof bitbucketConnectionKeys.listWorkspaces>
>,
"queryKey" | "queryFn"
>
) => {
return useQuery({
queryKey: bitbucketConnectionKeys.listWorkspaces(connectionId),
queryFn: async () => {
const { data } = await apiRequest.get<TBitbucketConnectionListWorkspacesResponse>(
`/api/v1/app-connections/bitbucket/${connectionId}/workspaces`
);
return data.workspaces;
},
...options
});
};
export const useBitbucketConnectionListRepositories = (
connectionId: string,
workspaceSlug: string,
options?: Omit<
UseQueryOptions<
TBitbucketRepo[],
unknown,
TBitbucketRepo[],
ReturnType<typeof bitbucketConnectionKeys.listRepos>
>,
"queryKey" | "queryFn"
>
) => {
return useQuery({
queryKey: bitbucketConnectionKeys.listRepos(connectionId, workspaceSlug),
queryFn: async () => {
const { data } = await apiRequest.get<TBitbucketConnectionListRepositoriesResponse>(
`/api/v1/app-connections/bitbucket/${connectionId}/repositories?workspaceSlug=${encodeURIComponent(workspaceSlug)}`
);
return data.repositories;
},
...options
});
};
@@ -0,0 +1,17 @@
export type TBitbucketWorkspace = {
slug: string;
};
export type TBitbucketRepo = {
uuid: string;
slug: string;
full_name: string; // workspace-slug/repo-slug
};
export type TBitbucketConnectionListWorkspacesResponse = {
workspaces: TBitbucketWorkspace[];
};
export type TBitbucketConnectionListRepositoriesResponse = {
repositories: TBitbucketRepo[];
};
@@ -28,5 +28,7 @@ export enum AppConnection {
Flyio = "flyio",
Gitlab = "gitlab",
Cloudflare = "cloudflare",
Zabbix = "zabbix"
Bitbucket = "bitbucket",
Zabbix = "zabbix",
Railway = "railway"
}
@@ -0,0 +1,2 @@
export * from "./queries";
export * from "./types";
@@ -0,0 +1,37 @@
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { appConnectionKeys } from "@app/hooks/api/appConnections";
import { TRailwayProject } from "./types";
const railwayConnectionKeys = {
all: [...appConnectionKeys.all, "railway"] as const,
listSecretScopes: (connectionId: string) =>
[...railwayConnectionKeys.all, "workspace-scopes", connectionId] as const
};
export const useRailwayConnectionListProjects = (
connectionId: string,
options?: Omit<
UseQueryOptions<
TRailwayProject[],
unknown,
TRailwayProject[],
ReturnType<typeof railwayConnectionKeys.listSecretScopes>
>,
"queryKey" | "queryFn"
>
) => {
return useQuery({
queryKey: railwayConnectionKeys.listSecretScopes(connectionId),
queryFn: async () => {
const { data } = await apiRequest.get<{ projects: TRailwayProject[] }>(
`/api/v1/app-connections/railway/${connectionId}/projects`
);
return data.projects;
},
...options
});
};
@@ -0,0 +1,12 @@
export type TRailwayProject = {
id: string;
name: string;
environments: Array<{
id: string;
name: string;
}>;
services: Array<{
id: string;
name: string;
}>;
};
@@ -132,10 +132,18 @@ export type TCloudflareConnectionOption = TAppConnectionOptionBase & {
app: AppConnection.Cloudflare;
};
export type TBitbucketConnectionOption = TAppConnectionOptionBase & {
app: AppConnection.Bitbucket;
};
export type TZabbixConnectionOption = TAppConnectionOptionBase & {
app: AppConnection.Zabbix;
};
export type TRailwayConnectionOption = TAppConnectionOptionBase & {
app: AppConnection.Railway;
};
export type TAppConnectionOption =
| TAwsConnectionOption
| TGitHubConnectionOption
@@ -164,7 +172,9 @@ export type TAppConnectionOption =
| TFlyioConnectionOption
| TGitlabConnectionOption
| TCloudflareConnectionOption
| TZabbixConnectionOption;
| TBitbucketConnectionOption
| TZabbixConnectionOption
| TRailwayConnectionOption;
export type TAppConnectionOptionMap = {
[AppConnection.AWS]: TAwsConnectionOption;
@@ -196,5 +206,7 @@ export type TAppConnectionOptionMap = {
[AppConnection.Flyio]: TFlyioConnectionOption;
[AppConnection.Gitlab]: TGitlabConnectionOption;
[AppConnection.Cloudflare]: TCloudflareConnectionOption;
[AppConnection.Bitbucket]: TBitbucketConnectionOption;
[AppConnection.Zabbix]: TZabbixConnectionOption;
[AppConnection.Railway]: TRailwayConnectionOption;
};
@@ -0,0 +1,14 @@
import { AppConnection } from "@app/hooks/api/appConnections/enums";
import { TRootAppConnection } from "@app/hooks/api/appConnections/types/root-connection";
export enum BitbucketConnectionMethod {
ApiToken = "api-token"
}
export type TBitbucketConnection = TRootAppConnection & { app: AppConnection.Bitbucket } & {
method: BitbucketConnectionMethod.ApiToken;
credentials: {
email: string;
apiToken: string;
};
};
@@ -7,6 +7,7 @@ import { TAzureAppConfigurationConnection } from "./azure-app-configuration-conn
import { TAzureClientSecretsConnection } from "./azure-client-secrets-connection";
import { TAzureDevOpsConnection } from "./azure-devops-connection";
import { TAzureKeyVaultConnection } from "./azure-key-vault-connection";
import { TBitbucketConnection } from "./bitbucket-connection";
import { TCamundaConnection } from "./camunda-connection";
import { TCloudflareConnection } from "./cloudflare-connection";
import { TDatabricksConnection } from "./databricks-connection";
@@ -24,6 +25,7 @@ import { TMySqlConnection } from "./mysql-connection";
import { TOCIConnection } from "./oci-connection";
import { TOracleDBConnection } from "./oracledb-connection";
import { TPostgresConnection } from "./postgres-connection";
import { TRailwayConnection } from "./railway-connection";
import { TRenderConnection } from "./render-connection";
import { TTeamCityConnection } from "./teamcity-connection";
import { TTerraformCloudConnection } from "./terraform-cloud-connection";
@@ -38,6 +40,7 @@ export * from "./azure-app-configuration-connection";
export * from "./azure-client-secrets-connection";
export * from "./azure-devops-connection";
export * from "./azure-key-vault-connection";
export * from "./bitbucket-connection";
export * from "./camunda-connection";
export * from "./cloudflare-connection";
export * from "./databricks-connection";
@@ -92,7 +95,9 @@ export type TAppConnection =
| TFlyioConnection
| TGitLabConnection
| TCloudflareConnection
| TZabbixConnection;
| TBitbucketConnection
| TZabbixConnection
| TRailwayConnection;
export type TAvailableAppConnection = Pick<TAppConnection, "name" | "id">;
@@ -149,5 +154,7 @@ export type TAppConnectionMap = {
[AppConnection.Flyio]: TFlyioConnection;
[AppConnection.Gitlab]: TGitLabConnection;
[AppConnection.Cloudflare]: TCloudflareConnection;
[AppConnection.Bitbucket]: TBitbucketConnection;
[AppConnection.Zabbix]: TZabbixConnection;
[AppConnection.Railway]: TRailwayConnection;
};
@@ -0,0 +1,15 @@
import { AppConnection } from "@app/hooks/api/appConnections/enums";
import { TRootAppConnection } from "@app/hooks/api/appConnections/types/root-connection";
export enum RailwayConnectionMethod {
AccountToken = "account-token",
ProjectToken = "project-token",
TeamToken = "team-token"
}
export type TRailwayConnection = TRootAppConnection & { app: AppConnection.Railway } & {
method: RailwayConnectionMethod;
credentials: {
apiToken: string;
};
};
+10 -1
View File
@@ -54,7 +54,8 @@ export enum SqlProviders {
export enum DynamicSecretAwsIamAuth {
AssumeRole = "assume-role",
AccessKey = "access-key"
AccessKey = "access-key",
IRSA = "irsa"
}
export type TDynamicSecretProvider =
@@ -111,6 +112,14 @@ export type TDynamicSecretProvider =
policyDocument?: string;
userGroups?: string;
policyArns?: string;
}
| {
method: DynamicSecretAwsIamAuth.IRSA;
region: string;
awsPath?: string;
policyDocument?: string;
userGroups?: string;
policyArns?: string;
};
}
| {
@@ -3,6 +3,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { organizationKeys } from "../organization/queries";
import { subscriptionQueryKeys } from "../subscriptions/queries";
import { identitiesKeys } from "./queries";
import {
AddIdentityAliCloudAuthDTO,
@@ -82,6 +83,9 @@ export const useCreateIdentity = () => {
queryClient.invalidateQueries({
queryKey: organizationKeys.getOrgIdentityMemberships(organizationId)
});
queryClient.invalidateQueries({
queryKey: subscriptionQueryKeys.getOrgSubsription(organizationId)
});
}
});
};
@@ -123,6 +127,9 @@ export const useDeleteIdentity = () => {
queryClient.invalidateQueries({
queryKey: organizationKeys.getOrgIdentityMemberships(organizationId)
});
queryClient.invalidateQueries({
queryKey: subscriptionQueryKeys.getOrgSubsription(organizationId)
});
}
});
};
@@ -4,7 +4,7 @@ export {
useDeleteIntegrationAuth,
useDeleteIntegrationAuths,
useGetIntegrationAuthApps,
useGetIntegrationAuthBitBucketWorkspaces,
useGetIntegrationAuthBitbucketWorkspaces,
useGetIntegrationAuthById,
useGetIntegrationAuthChecklyGroups,
useGetIntegrationAuthCircleCIOrganizations,
@@ -6,8 +6,8 @@ import { TReactQueryOptions } from "@app/types/reactQuery";
import { workspaceKeys } from "../workspace";
import {
App,
BitBucketEnvironment,
BitBucketWorkspace,
BitbucketEnvironment,
BitbucketWorkspace,
ChecklyGroup,
CircleCIOrganization,
Environment,
@@ -98,9 +98,9 @@ const integrationAuthKeys = {
integrationAuthId: string;
appId: string;
}) => [{ integrationAuthId, appId }, "integrationAuthRailwayServices"] as const,
getIntegrationAuthBitBucketWorkspaces: (integrationAuthId: string) =>
getIntegrationAuthBitbucketWorkspaces: (integrationAuthId: string) =>
[{ integrationAuthId }, "integrationAuthBitbucketWorkspaces"] as const,
getIntegrationAuthBitBucketEnvironments: (
getIntegrationAuthBitbucketEnvironments: (
integrationAuthId: string,
workspaceSlug: string,
repoSlug: string
@@ -446,23 +446,23 @@ const fetchIntegrationAuthRailwayServices = async ({
return services;
};
const fetchIntegrationAuthBitBucketWorkspaces = async (integrationAuthId: string) => {
const fetchIntegrationAuthBitbucketWorkspaces = async (integrationAuthId: string) => {
const {
data: { workspaces }
} = await apiRequest.get<{ workspaces: BitBucketWorkspace[] }>(
} = await apiRequest.get<{ workspaces: BitbucketWorkspace[] }>(
`/api/v1/integration-auth/${integrationAuthId}/bitbucket/workspaces`
);
return workspaces;
};
const fetchIntegrationAuthBitBucketEnvironments = async (
const fetchIntegrationAuthBitbucketEnvironments = async (
integrationAuthId: string,
workspaceSlug: string,
repoSlug: string
) => {
const {
data: { environments }
} = await apiRequest.get<{ environments: BitBucketEnvironment[] }>(
} = await apiRequest.get<{ environments: BitbucketEnvironment[] }>(
`/api/v1/integration-auth/${integrationAuthId}/bitbucket/environments`,
{
params: {
@@ -833,10 +833,10 @@ export const useGetIntegrationAuthRailwayServices = ({
});
};
export const useGetIntegrationAuthBitBucketWorkspaces = (integrationAuthId: string) => {
export const useGetIntegrationAuthBitbucketWorkspaces = (integrationAuthId: string) => {
return useQuery({
queryKey: integrationAuthKeys.getIntegrationAuthBitBucketWorkspaces(integrationAuthId),
queryFn: () => fetchIntegrationAuthBitBucketWorkspaces(integrationAuthId),
queryKey: integrationAuthKeys.getIntegrationAuthBitbucketWorkspaces(integrationAuthId),
queryFn: () => fetchIntegrationAuthBitbucketWorkspaces(integrationAuthId),
enabled: true
});
};
@@ -858,7 +858,7 @@ export const useGetIntegrationAuthOctopusDeployScopeValues = (
...options
});
export const useGetIntegrationAuthBitBucketEnvironments = (
export const useGetIntegrationAuthBitbucketEnvironments = (
{
integrationAuthId,
workspaceSlug,
@@ -871,13 +871,13 @@ export const useGetIntegrationAuthBitBucketEnvironments = (
options?: TReactQueryOptions["options"]
) => {
return useQuery({
queryKey: integrationAuthKeys.getIntegrationAuthBitBucketEnvironments(
queryKey: integrationAuthKeys.getIntegrationAuthBitbucketEnvironments(
integrationAuthId,
workspaceSlug,
repoSlug
),
queryFn: () =>
fetchIntegrationAuthBitBucketEnvironments(integrationAuthId, workspaceSlug, repoSlug),
fetchIntegrationAuthBitbucketEnvironments(integrationAuthId, workspaceSlug, repoSlug),
...options
});
};
@@ -78,13 +78,13 @@ export type Service = {
serviceId: string;
};
export type BitBucketWorkspace = {
export type BitbucketWorkspace = {
uuid: string;
name: string;
slug: string;
};
export type BitBucketEnvironment = {
export type BitbucketEnvironment = {
uuid: string;
name: string;
slug: string;
@@ -49,7 +49,7 @@ export type TCreateSecretPolicyDTO = {
workspaceId: string;
name?: string;
environment: string;
secretPath?: string | null;
secretPath: string;
approvers?: Approver[];
bypassers?: Bypasser[];
approvals?: number;
@@ -62,7 +62,7 @@ export type TUpdateSecretPolicyDTO = {
name?: string;
approvers?: Approver[];
bypassers?: Bypasser[];
secretPath?: string | null;
secretPath?: string;
approvals?: number;
allowedSelfApprovals?: boolean;
enforcementLevel?: EnforcementLevel;
@@ -1,5 +1,6 @@
export enum SecretScanningDataSource {
GitHub = "github"
GitHub = "github",
Bitbucket = "bitbucket"
}
export enum SecretScanningScanStatus {
@@ -0,0 +1,18 @@
import { AppConnection } from "@app/hooks/api/appConnections/enums";
import { SecretScanningDataSource } from "../enums";
import { TSecretScanningDataSourceBase } from "./shared";
export type TBitbucketDataSource = TSecretScanningDataSourceBase & {
type: SecretScanningDataSource.Bitbucket;
config: {
workspaceSlug: string;
includeRepos: string[];
};
};
export type TBitbucketDataSourceOption = {
name: string;
type: SecretScanningDataSource.Bitbucket;
connection: AppConnection.Bitbucket;
};
@@ -8,9 +8,10 @@ import {
SecretScanningScanStatus,
SecretScanningScanType
} from "../enums";
import { TBitbucketDataSource, TBitbucketDataSourceOption } from "./bitbucket-data-source";
import { TGitHubDataSource, TGitHubDataSourceOption } from "./github-data-source";
export type TSecretScanningDataSource = TGitHubDataSource;
export type TSecretScanningDataSource = TGitHubDataSource | TBitbucketDataSource;
export type TSecretScanningDataSourceWithDetails = TSecretScanningDataSource & {
lastScannedAt: string | null;
@@ -23,7 +24,7 @@ export type TListSecretScanningDataSources = {
dataSources: TSecretScanningDataSourceWithDetails[];
};
export type TSecretScanningDataSourceOption = TGitHubDataSourceOption;
export type TSecretScanningDataSourceOption = TGitHubDataSourceOption | TBitbucketDataSourceOption;
export type TListSecretScanningDataSourceOptions = {
dataSourceOptions: TSecretScanningDataSourceOption[];
+2 -1
View File
@@ -21,7 +21,8 @@ export enum SecretSync {
Flyio = "flyio",
GitLab = "gitlab",
CloudflarePages = "cloudflare-pages",
Zabbix = "zabbix"
Zabbix = "zabbix",
Railway = "railway"
}
export enum SecretSyncStatus {
@@ -19,6 +19,7 @@ import { THCVaultSync } from "./hc-vault-sync";
import { THerokuSync } from "./heroku-sync";
import { THumanitecSync } from "./humanitec-sync";
import { TOCIVaultSync } from "./oci-vault-sync";
import { TRailwaySync } from "./railway-sync";
import { TTeamCitySync } from "./teamcity-sync";
import { TTerraformCloudSync } from "./terraform-cloud-sync";
import { TVercelSync } from "./vercel-sync";
@@ -55,7 +56,8 @@ export type TSecretSync =
| TFlyioSync
| TGitLabSync
| TCloudflarePagesSync
| TZabbixSync;
| TZabbixSync
| TRailwaySync;
export type TListSecretSyncs = { secretSyncs: TSecretSync[] };
@@ -0,0 +1,22 @@
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";
export type TRailwaySync = TRootSecretSync & {
destination: SecretSync.Railway;
destinationConfig: {
projectId: string;
projectName: string;
environmentName: string;
environmentId: string;
serviceId?: string;
serviceName?: string;
};
connection: {
app: AppConnection.Railway;
name: string;
id: string;
};
};
+4
View File
@@ -9,6 +9,7 @@ import { APIKeyDataV2 } from "../apiKeys/types";
import { MfaMethod } from "../auth/types";
import { TGroupWithProjectMemberships } from "../groups/types";
import { setAuthToken } from "../reactQuery";
import { subscriptionQueryKeys } from "../subscriptions/queries";
import { workspaceKeys } from "../workspace";
import { userKeys } from "./query-keys";
import {
@@ -188,6 +189,9 @@ export const useAddUsersToOrg = () => {
},
onSuccess: (_, { organizationId, projects }) => {
queryClient.invalidateQueries({ queryKey: userKeys.getOrgUsers(organizationId) });
queryClient.invalidateQueries({
queryKey: subscriptionQueryKeys.getOrgSubsription(organizationId)
});
projects?.forEach((project) => {
if (project.slug) {