mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-15 18:15:53 +00:00
Merge branch 'heads/main' into daniel/vault-import
This commit is contained in:
@@ -4,8 +4,10 @@ import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { appConnectionKeys } from "../queries";
|
||||
import {
|
||||
TBitbucketConnectionListEnvironmentsResponse,
|
||||
TBitbucketConnectionListRepositoriesResponse,
|
||||
TBitbucketConnectionListWorkspacesResponse,
|
||||
TBitbucketEnvironment,
|
||||
TBitbucketRepo,
|
||||
TBitbucketWorkspace
|
||||
} from "./types";
|
||||
@@ -15,7 +17,9 @@ const bitbucketConnectionKeys = {
|
||||
listRepos: (connectionId: string, workspaceSlug: string) =>
|
||||
[...bitbucketConnectionKeys.all, "repos", connectionId, workspaceSlug] as const,
|
||||
listWorkspaces: (connectionId: string) =>
|
||||
[...bitbucketConnectionKeys.all, "workspaces", connectionId] as const
|
||||
[...bitbucketConnectionKeys.all, "workspaces", connectionId] as const,
|
||||
listEnvironments: (connectionId: string, workspaceSlug: string, repoSlug: string) =>
|
||||
[...bitbucketConnectionKeys.all, "environments", connectionId, workspaceSlug, repoSlug] as const
|
||||
};
|
||||
|
||||
export const useBitbucketConnectionListWorkspaces = (
|
||||
@@ -68,3 +72,30 @@ export const useBitbucketConnectionListRepositories = (
|
||||
...options
|
||||
});
|
||||
};
|
||||
|
||||
export const useBitbucketConnectionListEnvironments = (
|
||||
connectionId: string,
|
||||
workspaceSlug: string,
|
||||
repoSlug: string,
|
||||
options?: Omit<
|
||||
UseQueryOptions<
|
||||
TBitbucketEnvironment[],
|
||||
unknown,
|
||||
TBitbucketEnvironment[],
|
||||
ReturnType<typeof bitbucketConnectionKeys.listEnvironments>
|
||||
>,
|
||||
"queryKey" | "queryFn"
|
||||
>
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: bitbucketConnectionKeys.listEnvironments(connectionId, workspaceSlug, repoSlug),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<TBitbucketConnectionListEnvironmentsResponse>(
|
||||
`/api/v1/app-connections/bitbucket/${connectionId}/environments?workspaceSlug=${encodeURIComponent(workspaceSlug)}&repositorySlug=${encodeURIComponent(repoSlug)}`
|
||||
);
|
||||
|
||||
return data.environments;
|
||||
},
|
||||
...options
|
||||
});
|
||||
};
|
||||
|
||||
@@ -15,3 +15,13 @@ export type TBitbucketConnectionListWorkspacesResponse = {
|
||||
export type TBitbucketConnectionListRepositoriesResponse = {
|
||||
repositories: TBitbucketRepo[];
|
||||
};
|
||||
|
||||
export type TBitbucketEnvironment = {
|
||||
uuid: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
};
|
||||
|
||||
export type TBitbucketConnectionListEnvironmentsResponse = {
|
||||
environments: TBitbucketEnvironment[];
|
||||
};
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./queries";
|
||||
@@ -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 { TDigitalOceanApp } from "./types";
|
||||
|
||||
const digitalOceanAppPlatformConnectionKeys = {
|
||||
all: [...appConnectionKeys.all, "digitalOceanAppPlatform"] as const,
|
||||
listAccounts: (connectionId: string) =>
|
||||
[...digitalOceanAppPlatformConnectionKeys.all, "workspace-scopes", connectionId] as const
|
||||
};
|
||||
|
||||
export const useDigitalOceanConnectionListApps = (
|
||||
connectionId: string,
|
||||
options?: Omit<
|
||||
UseQueryOptions<
|
||||
TDigitalOceanApp[],
|
||||
unknown,
|
||||
TDigitalOceanApp[],
|
||||
ReturnType<typeof digitalOceanAppPlatformConnectionKeys.listAccounts>
|
||||
>,
|
||||
"queryKey" | "queryFn"
|
||||
>
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: digitalOceanAppPlatformConnectionKeys.listAccounts(connectionId),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{ apps: TDigitalOceanApp[] }>(
|
||||
`/api/v1/app-connections/digital-ocean/${connectionId}/apps`
|
||||
);
|
||||
|
||||
return data.apps;
|
||||
},
|
||||
...options
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
export type TDigitalOceanAppPlatformVariable = {
|
||||
key: string;
|
||||
value: string;
|
||||
type: "SECRET" | "GENERAL";
|
||||
};
|
||||
|
||||
export type TDigitalOceanApp = {
|
||||
id: string;
|
||||
spec: {
|
||||
name: string;
|
||||
services: Array<{
|
||||
name: string;
|
||||
}>;
|
||||
envs?: TDigitalOceanAppPlatformVariable[];
|
||||
};
|
||||
};
|
||||
@@ -32,5 +32,7 @@ export enum AppConnection {
|
||||
Zabbix = "zabbix",
|
||||
Railway = "railway",
|
||||
Checkly = "checkly",
|
||||
Supabase = "supabase"
|
||||
Supabase = "supabase",
|
||||
DigitalOcean = "digital-ocean",
|
||||
Okta = "okta"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from "./queries";
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,36 @@
|
||||
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { appConnectionKeys } from "../queries";
|
||||
import { TOktaApp } from "./types";
|
||||
|
||||
const oktaConnectionKeys = {
|
||||
all: [...appConnectionKeys.all, "okta"] as const,
|
||||
listApps: (connectionId: string) => [...oktaConnectionKeys.all, "apps", connectionId] as const
|
||||
};
|
||||
|
||||
export const useOktaConnectionListApps = (
|
||||
connectionId: string,
|
||||
options?: Omit<
|
||||
UseQueryOptions<
|
||||
TOktaApp[],
|
||||
unknown,
|
||||
TOktaApp[],
|
||||
ReturnType<typeof oktaConnectionKeys.listApps>
|
||||
>,
|
||||
"queryKey" | "queryFn"
|
||||
>
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: oktaConnectionKeys.listApps(connectionId),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{ apps: TOktaApp[] }>(
|
||||
`/api/v1/app-connections/okta/${connectionId}/apps`
|
||||
);
|
||||
|
||||
return data.apps;
|
||||
},
|
||||
...options
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
export type TOktaApp = {
|
||||
id: string;
|
||||
label: string;
|
||||
};
|
||||
@@ -152,6 +152,14 @@ export type TSupabaseConnectionOption = TAppConnectionOptionBase & {
|
||||
app: AppConnection.Supabase;
|
||||
};
|
||||
|
||||
export type TDigitalOceanConnectionOption = TAppConnectionOptionBase & {
|
||||
app: AppConnection.DigitalOcean;
|
||||
};
|
||||
|
||||
export type TOktaConnectionOption = TAppConnectionOptionBase & {
|
||||
app: AppConnection.Okta;
|
||||
};
|
||||
|
||||
export type TAppConnectionOption =
|
||||
| TAwsConnectionOption
|
||||
| TGitHubConnectionOption
|
||||
@@ -183,7 +191,9 @@ export type TAppConnectionOption =
|
||||
| TBitbucketConnectionOption
|
||||
| TZabbixConnectionOption
|
||||
| TRailwayConnectionOption
|
||||
| TChecklyConnectionOption;
|
||||
| TChecklyConnectionOption
|
||||
| TDigitalOceanConnectionOption
|
||||
| TOktaConnectionOption;
|
||||
|
||||
export type TAppConnectionOptionMap = {
|
||||
[AppConnection.AWS]: TAwsConnectionOption;
|
||||
@@ -220,4 +230,6 @@ export type TAppConnectionOptionMap = {
|
||||
[AppConnection.Railway]: TRailwayConnectionOption;
|
||||
[AppConnection.Checkly]: TChecklyConnectionOption;
|
||||
[AppConnection.Supabase]: TSupabaseConnectionOption;
|
||||
[AppConnection.DigitalOcean]: TDigitalOceanConnectionOption;
|
||||
[AppConnection.Okta]: TOktaConnectionOption;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
import { TRootAppConnection } from "@app/hooks/api/appConnections/types/root-connection";
|
||||
|
||||
export enum DigitalOceanConnectionMethod {
|
||||
ApiToken = "api-token"
|
||||
}
|
||||
|
||||
export type TDigitalOceanConnection = TRootAppConnection & {
|
||||
app: AppConnection.DigitalOcean;
|
||||
method: DigitalOceanConnectionMethod.ApiToken;
|
||||
credentials: {
|
||||
apiToken: string;
|
||||
};
|
||||
};
|
||||
@@ -12,6 +12,7 @@ import { TCamundaConnection } from "./camunda-connection";
|
||||
import { TChecklyConnection } from "./checkly-connection";
|
||||
import { TCloudflareConnection } from "./cloudflare-connection";
|
||||
import { TDatabricksConnection } from "./databricks-connection";
|
||||
import { TDigitalOceanConnection } from "./digital-ocean";
|
||||
import { TFlyioConnection } from "./flyio-connection";
|
||||
import { TGcpConnection } from "./gcp-connection";
|
||||
import { TGitHubConnection } from "./github-connection";
|
||||
@@ -24,6 +25,7 @@ import { TLdapConnection } from "./ldap-connection";
|
||||
import { TMsSqlConnection } from "./mssql-connection";
|
||||
import { TMySqlConnection } from "./mysql-connection";
|
||||
import { TOCIConnection } from "./oci-connection";
|
||||
import { TOktaConnection } from "./okta-connection";
|
||||
import { TOracleDBConnection } from "./oracledb-connection";
|
||||
import { TPostgresConnection } from "./postgres-connection";
|
||||
import { TRailwayConnection } from "./railway-connection";
|
||||
@@ -44,6 +46,7 @@ export * from "./azure-devops-connection";
|
||||
export * from "./azure-key-vault-connection";
|
||||
export * from "./bitbucket-connection";
|
||||
export * from "./camunda-connection";
|
||||
export * from "./checkly-connection";
|
||||
export * from "./cloudflare-connection";
|
||||
export * from "./databricks-connection";
|
||||
export * from "./flyio-connection";
|
||||
@@ -58,9 +61,12 @@ export * from "./ldap-connection";
|
||||
export * from "./mssql-connection";
|
||||
export * from "./mysql-connection";
|
||||
export * from "./oci-connection";
|
||||
export * from "./okta-connection";
|
||||
export * from "./oracledb-connection";
|
||||
export * from "./postgres-connection";
|
||||
export * from "./railway-connection";
|
||||
export * from "./render-connection";
|
||||
export * from "./supabase-connection";
|
||||
export * from "./teamcity-connection";
|
||||
export * from "./terraform-cloud-connection";
|
||||
export * from "./vercel-connection";
|
||||
@@ -101,7 +107,9 @@ export type TAppConnection =
|
||||
| TZabbixConnection
|
||||
| TRailwayConnection
|
||||
| TChecklyConnection
|
||||
| TSupabaseConnection;
|
||||
| TSupabaseConnection
|
||||
| TDigitalOceanConnection
|
||||
| TOktaConnection;
|
||||
|
||||
export type TAvailableAppConnection = Pick<TAppConnection, "name" | "id">;
|
||||
|
||||
@@ -172,4 +180,6 @@ export type TAppConnectionMap = {
|
||||
[AppConnection.Railway]: TRailwayConnection;
|
||||
[AppConnection.Checkly]: TChecklyConnection;
|
||||
[AppConnection.Supabase]: TSupabaseConnection;
|
||||
[AppConnection.DigitalOcean]: TDigitalOceanConnection;
|
||||
[AppConnection.Okta]: TOktaConnection;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
import { TRootAppConnection } from "@app/hooks/api/appConnections/types/root-connection";
|
||||
|
||||
export enum OktaConnectionMethod {
|
||||
ApiToken = "api-token"
|
||||
}
|
||||
|
||||
export type TOktaConnection = TRootAppConnection & { app: AppConnection.Okta } & {
|
||||
method: OktaConnectionMethod.ApiToken;
|
||||
credentials: {
|
||||
instanceUrl: string;
|
||||
apiToken: string;
|
||||
};
|
||||
};
|
||||
@@ -57,6 +57,7 @@ export const useGetAuditLogs = (
|
||||
},
|
||||
getNextPageParam: (lastPage, pages) =>
|
||||
lastPage.length !== 0 ? pages.length * filters.limit : undefined,
|
||||
placeholderData: (prev) => prev,
|
||||
...options
|
||||
});
|
||||
};
|
||||
|
||||
@@ -51,7 +51,7 @@ export type IdentityMembershipOrg = {
|
||||
export type IdentityMembership = {
|
||||
id: string;
|
||||
identity: Identity;
|
||||
project: Pick<Workspace, "id" | "name" | "defaultProduct">;
|
||||
project: Pick<Workspace, "id" | "name" | "type">;
|
||||
roles: Array<
|
||||
{
|
||||
id: string;
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { TProjectRole } from "@app/hooks/api/roles/types";
|
||||
|
||||
import { ProjectType } from "../workspace/types";
|
||||
|
||||
export type TProjectTemplate = {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
type: ProjectType;
|
||||
roles: Pick<TProjectRole, "slug" | "name" | "permissions">[];
|
||||
environments?: { name: string; slug: string; position: number }[] | null;
|
||||
createdAt: string;
|
||||
@@ -16,6 +19,7 @@ export type TProjectTemplateResponse = { projectTemplate: TProjectTemplate };
|
||||
export type TCreateProjectTemplateDTO = {
|
||||
name: string;
|
||||
description?: string;
|
||||
type?: ProjectType;
|
||||
};
|
||||
|
||||
export type TUpdateProjectTemplateDTO = Partial<
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { useCreateReminder, useDeleteReminder, useGetReminder } from "./queries";
|
||||
@@ -0,0 +1,60 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { CreateReminderDTO, DeleteReminderDTO, Reminder } from "./types";
|
||||
|
||||
export const reminderKeys = {
|
||||
getReminder: (secretId: string) => ["get-reminder", secretId] as const
|
||||
};
|
||||
|
||||
export const useCreateReminder = (secretId: string) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<Reminder, object, CreateReminderDTO>({
|
||||
mutationFn: async ({ message, repeatDays, nextReminderDate, recipients }) => {
|
||||
const { data } = await apiRequest.post<{ reminder: Reminder }>(
|
||||
`/api/v1/reminders/secrets/${secretId}`,
|
||||
{
|
||||
message,
|
||||
repeatDays,
|
||||
nextReminderDate,
|
||||
recipients
|
||||
}
|
||||
);
|
||||
return data.reminder;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: reminderKeys.getReminder(secretId) });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteReminder = (secretId: string) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<Reminder, object, DeleteReminderDTO>({
|
||||
mutationFn: async () => {
|
||||
const { data } = await apiRequest.delete<{ reminder: Reminder }>(
|
||||
`/api/v1/reminders/secrets/${secretId}`
|
||||
);
|
||||
return data.reminder;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: reminderKeys.getReminder(secretId) });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetReminder = (secretId: string) => {
|
||||
return useQuery({
|
||||
queryKey: reminderKeys.getReminder(secretId),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{ reminder: Reminder }>(
|
||||
`/api/v1/reminders/secrets/${secretId}`
|
||||
);
|
||||
return data.reminder;
|
||||
},
|
||||
enabled: Boolean(secretId)
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
export type CreateReminderDTO = {
|
||||
message?: string | null;
|
||||
repeatDays?: number | null;
|
||||
nextReminderDate?: Date | null;
|
||||
secretId: string;
|
||||
recipients?: string[];
|
||||
};
|
||||
|
||||
export type DeleteReminderDTO = {
|
||||
secretId: string;
|
||||
reminderId: string;
|
||||
};
|
||||
|
||||
export type Reminder = { id: string } & CreateReminderDTO;
|
||||
@@ -4,11 +4,19 @@ export enum ReservedFolders {
|
||||
SecretReplication = "__reserve_replication_"
|
||||
}
|
||||
|
||||
export enum PendingAction {
|
||||
Create = "create",
|
||||
Update = "update",
|
||||
Delete = "delete"
|
||||
}
|
||||
|
||||
export type TSecretFolder = {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
parentId?: string | null;
|
||||
isPending?: boolean;
|
||||
pendingAction?: PendingAction;
|
||||
};
|
||||
|
||||
export type TSecretFolderWithPath = TSecretFolder & { path: string };
|
||||
|
||||
@@ -6,7 +6,8 @@ export enum SecretRotation {
|
||||
Auth0ClientSecret = "auth0-client-secret",
|
||||
AzureClientSecret = "azure-client-secret",
|
||||
LdapPassword = "ldap-password",
|
||||
AwsIamUserSecret = "aws-iam-user-secret"
|
||||
AwsIamUserSecret = "aws-iam-user-secret",
|
||||
OktaClientSecret = "okta-client-secret"
|
||||
}
|
||||
|
||||
export enum SecretRotationStatus {
|
||||
|
||||
@@ -35,6 +35,11 @@ import {
|
||||
TMySqlCredentialsRotation,
|
||||
TMySqlCredentialsRotationGeneratedCredentialsResponse
|
||||
} from "./mysql-credentials-rotation";
|
||||
import {
|
||||
TOktaClientSecretRotation,
|
||||
TOktaClientSecretRotationGeneratedCredentialsResponse,
|
||||
TOktaClientSecretRotationOption
|
||||
} from "./okta-client-secret-rotation";
|
||||
import {
|
||||
TOracleDBCredentialsRotation,
|
||||
TOracleDBCredentialsRotationGeneratedCredentialsResponse
|
||||
@@ -49,6 +54,7 @@ export type TSecretRotationV2 = (
|
||||
| TAzureClientSecretRotation
|
||||
| TLdapPasswordRotation
|
||||
| TAwsIamUserSecretRotation
|
||||
| TOktaClientSecretRotation
|
||||
) & {
|
||||
secrets: (SecretV3RawSanitized | null)[];
|
||||
};
|
||||
@@ -58,7 +64,8 @@ export type TSecretRotationV2Option =
|
||||
| TAuth0ClientSecretRotationOption
|
||||
| TAzureClientSecretRotationOption
|
||||
| TLdapPasswordRotationOption
|
||||
| TAwsIamUserSecretRotationOption;
|
||||
| TAwsIamUserSecretRotationOption
|
||||
| TOktaClientSecretRotationOption;
|
||||
|
||||
export type TListSecretRotationV2Options = { secretRotationOptions: TSecretRotationV2Option[] };
|
||||
|
||||
@@ -72,7 +79,8 @@ export type TViewSecretRotationGeneratedCredentialsResponse =
|
||||
| TAuth0ClientSecretRotationGeneratedCredentialsResponse
|
||||
| TAzureClientSecretRotationGeneratedCredentialsResponse
|
||||
| TLdapPasswordRotationGeneratedCredentialsResponse
|
||||
| TAwsIamUserSecretRotationGeneratedCredentialsResponse;
|
||||
| TAwsIamUserSecretRotationGeneratedCredentialsResponse
|
||||
| TOktaClientSecretRotationGeneratedCredentialsResponse;
|
||||
|
||||
export type TCreateSecretRotationV2DTO = DiscriminativePick<
|
||||
TSecretRotationV2,
|
||||
@@ -124,6 +132,7 @@ export type TSecretRotationOptionMap = {
|
||||
[SecretRotation.AzureClientSecret]: TAzureClientSecretRotationOption;
|
||||
[SecretRotation.LdapPassword]: TLdapPasswordRotationOption;
|
||||
[SecretRotation.AwsIamUserSecret]: TAwsIamUserSecretRotationOption;
|
||||
[SecretRotation.OktaClientSecret]: TOktaClientSecretRotationOption;
|
||||
};
|
||||
|
||||
export type TSecretRotationGeneratedCredentialsResponseMap = {
|
||||
@@ -135,4 +144,5 @@ export type TSecretRotationGeneratedCredentialsResponseMap = {
|
||||
[SecretRotation.AzureClientSecret]: TAzureClientSecretRotationGeneratedCredentialsResponse;
|
||||
[SecretRotation.LdapPassword]: TLdapPasswordRotationGeneratedCredentialsResponse;
|
||||
[SecretRotation.AwsIamUserSecret]: TAwsIamUserSecretRotationGeneratedCredentialsResponse;
|
||||
[SecretRotation.OktaClientSecret]: TOktaClientSecretRotationGeneratedCredentialsResponse;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
import { SecretRotation } from "@app/hooks/api/secretRotationsV2";
|
||||
import {
|
||||
TSecretRotationV2Base,
|
||||
TSecretRotationV2GeneratedCredentialsResponseBase
|
||||
} from "@app/hooks/api/secretRotationsV2/types/shared";
|
||||
|
||||
export type TOktaClientSecretRotation = TSecretRotationV2Base & {
|
||||
type: SecretRotation.OktaClientSecret;
|
||||
parameters: {
|
||||
clientId: string;
|
||||
};
|
||||
secretsMapping: {
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type TOktaClientSecretRotationGeneratedCredentials = {
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
};
|
||||
|
||||
export type TOktaClientSecretRotationGeneratedCredentialsResponse =
|
||||
TSecretRotationV2GeneratedCredentialsResponseBase<
|
||||
SecretRotation.OktaClientSecret,
|
||||
TOktaClientSecretRotationGeneratedCredentials
|
||||
>;
|
||||
|
||||
export type TOktaClientSecretRotationOption = {
|
||||
name: string;
|
||||
type: SecretRotation.OktaClientSecret;
|
||||
connection: AppConnection.Okta;
|
||||
template: {
|
||||
secretsMapping: TOktaClientSecretRotation["secretsMapping"];
|
||||
};
|
||||
};
|
||||
@@ -25,7 +25,9 @@ export enum SecretSync {
|
||||
Supabase = "supabase",
|
||||
Zabbix = "zabbix",
|
||||
Railway = "railway",
|
||||
Checkly = "checkly"
|
||||
Checkly = "checkly",
|
||||
DigitalOceanAppPlatform = "digital-ocean-app-platform",
|
||||
Bitbucket = "bitbucket"
|
||||
}
|
||||
|
||||
export enum SecretSyncStatus {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
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 TBitbucketSync = TRootSecretSync & {
|
||||
destination: SecretSync.Bitbucket;
|
||||
destinationConfig: {
|
||||
workspaceSlug: string;
|
||||
repositorySlug: string;
|
||||
environmentId?: string;
|
||||
};
|
||||
connection: {
|
||||
app: AppConnection.Bitbucket;
|
||||
name: string;
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
||||
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 TDigitalOceanAppPlatformSync = TRootSecretSync & {
|
||||
destination: SecretSync.DigitalOceanAppPlatform;
|
||||
destinationConfig: {
|
||||
appId: string;
|
||||
appName: string;
|
||||
};
|
||||
connection: {
|
||||
app: AppConnection.DigitalOcean;
|
||||
name: string;
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
@@ -8,11 +8,13 @@ import { TAwsSecretsManagerSync } from "./aws-secrets-manager-sync";
|
||||
import { TAzureAppConfigurationSync } from "./azure-app-configuration-sync";
|
||||
import { TAzureDevOpsSync } from "./azure-devops-sync";
|
||||
import { TAzureKeyVaultSync } from "./azure-key-vault-sync";
|
||||
import { TBitbucketSync } from "./bitbucket-sync";
|
||||
import { TCamundaSync } from "./camunda-sync";
|
||||
import { TChecklySync } from "./checkly-sync";
|
||||
import { TCloudflarePagesSync } from "./cloudflare-pages-sync";
|
||||
import { TCloudflareWorkersSync } from "./cloudflare-workers-sync";
|
||||
import { TDatabricksSync } from "./databricks-sync";
|
||||
import { TDigitalOceanAppPlatformSync } from "./digital-ocean-app-platform-sync";
|
||||
import { TFlyioSync } from "./flyio-sync";
|
||||
import { TGcpSync } from "./gcp-sync";
|
||||
import { TGitHubSync } from "./github-sync";
|
||||
@@ -63,7 +65,9 @@ export type TSecretSync =
|
||||
| TZabbixSync
|
||||
| TRailwaySync
|
||||
| TChecklySync
|
||||
| TSupabaseSync;
|
||||
| TSupabaseSync
|
||||
| TDigitalOceanAppPlatformSync
|
||||
| TBitbucketSync;
|
||||
|
||||
export type TListSecretSyncs = { secretSyncs: TSecretSync[] };
|
||||
|
||||
|
||||
@@ -2,9 +2,14 @@ import { MutationOptions, useMutation, useQueryClient } from "@tanstack/react-qu
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
import { dashboardKeys } from "@app/hooks/api/dashboard/queries";
|
||||
import {
|
||||
PendingChanges,
|
||||
PendingSecretUpdate
|
||||
} from "@app/pages/secret-manager/SecretDashboardPage/SecretMainPage.store";
|
||||
|
||||
import { commitKeys } from "../folderCommits/queries";
|
||||
import { secretApprovalRequestKeys } from "../secretApprovalRequest/queries";
|
||||
import { PendingAction } from "../secretFolders/types";
|
||||
import { secretSnapshotKeys } from "../secretSnapshots/queries";
|
||||
import { secretKeys } from "./queries";
|
||||
import {
|
||||
@@ -420,3 +425,102 @@ export const useBackfillSecretReference = () =>
|
||||
return data.message;
|
||||
}
|
||||
});
|
||||
|
||||
export const useCreateCommit = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<
|
||||
object,
|
||||
object,
|
||||
{
|
||||
workspaceId: string;
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
pendingChanges: PendingChanges;
|
||||
message: string;
|
||||
}
|
||||
>({
|
||||
mutationFn: async ({ workspaceId, environment, secretPath, pendingChanges, message }) => {
|
||||
const { data } = await apiRequest.post("/api/v1/pit/batch/commit", {
|
||||
projectId: workspaceId,
|
||||
environment,
|
||||
secretPath,
|
||||
changes: {
|
||||
secrets: {
|
||||
create:
|
||||
pendingChanges.secrets
|
||||
.filter((change) => change.type === PendingAction.Create)
|
||||
.map((change) => ({
|
||||
secretKey: change.secretKey,
|
||||
secretValue: change.secretValue,
|
||||
secretComment: change.secretComment,
|
||||
skipMultilineEncoding: change.skipMultilineEncoding,
|
||||
tagIds: change.tags?.map((tag) => tag.id),
|
||||
secretMetadata: change.secretMetadata
|
||||
})) || [],
|
||||
update:
|
||||
pendingChanges.secrets
|
||||
.filter((change) => change.type === PendingAction.Update)
|
||||
.map((change: PendingSecretUpdate) => ({
|
||||
secretKey: change.secretKey,
|
||||
newSecretName: change.newSecretName,
|
||||
secretValue:
|
||||
change.secretValue === ""
|
||||
? ""
|
||||
: change.secretValue || change.existingSecret.value,
|
||||
secretComment:
|
||||
change.secretComment === ""
|
||||
? ""
|
||||
: change.secretComment || change.existingSecret.comment,
|
||||
skipMultilineEncoding:
|
||||
change.skipMultilineEncoding !== undefined
|
||||
? change.skipMultilineEncoding
|
||||
: change.existingSecret.skipMultilineEncoding,
|
||||
tagIds:
|
||||
change.tags?.map((tag) => tag.id) ||
|
||||
change.existingSecret.tags?.map((tag) => tag.id),
|
||||
secretMetadata: change.secretMetadata || change.existingSecret.secretMetadata
|
||||
})) || [],
|
||||
delete:
|
||||
pendingChanges.secrets.filter((change) => change.type === PendingAction.Delete) || []
|
||||
},
|
||||
folders: {
|
||||
create:
|
||||
pendingChanges.folders.filter((change) => change.type === PendingAction.Create) || [],
|
||||
update:
|
||||
pendingChanges.folders
|
||||
.filter((change) => change.type === PendingAction.Update)
|
||||
.map((change) => ({
|
||||
...change,
|
||||
description: change.description || null
|
||||
})) || [],
|
||||
delete:
|
||||
pendingChanges.folders.filter((change) => change.type === PendingAction.Delete) || []
|
||||
}
|
||||
},
|
||||
message
|
||||
});
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { workspaceId, environment, secretPath }) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: dashboardKeys.getDashboardSecrets({ projectId: workspaceId, secretPath })
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: secretKeys.getProjectSecret({ workspaceId, environment, secretPath })
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: secretSnapshotKeys.list({ environment, workspaceId, directory: secretPath })
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: secretSnapshotKeys.count({ environment, workspaceId, directory: secretPath })
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: commitKeys.count({ workspaceId, environment, directory: secretPath })
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: commitKeys.history({ workspaceId, environment, directory: secretPath })
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: secretApprovalRequestKeys.count({ workspaceId }) });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ProjectPermissionActions } from "@app/context";
|
||||
|
||||
import { PendingAction } from "../secretFolders/types";
|
||||
import type { WsTag } from "../tags/types";
|
||||
|
||||
export enum SecretType {
|
||||
@@ -66,6 +67,8 @@ export type SecretV3RawSanitized = {
|
||||
isRotatedSecret?: boolean;
|
||||
secretReminderRecipients?: SecretReminderRecipient[];
|
||||
rotationId?: string;
|
||||
isPending?: boolean;
|
||||
pendingAction?: PendingAction;
|
||||
};
|
||||
|
||||
export type SecretV3Raw = {
|
||||
|
||||
@@ -255,12 +255,13 @@ export const useCreateWorkspace = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<{ data: { project: Workspace } }, object, CreateWorkspaceDTO>({
|
||||
mutationFn: async ({ projectName, projectDescription, kmsKeyId, template }) =>
|
||||
mutationFn: async ({ projectName, projectDescription, kmsKeyId, template, type }) =>
|
||||
createWorkspace({
|
||||
projectName,
|
||||
projectDescription,
|
||||
kmsKeyId,
|
||||
template
|
||||
template,
|
||||
type
|
||||
}),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
@@ -280,8 +281,7 @@ export const useUpdateProject = () => {
|
||||
newProjectDescription,
|
||||
newSlug,
|
||||
secretSharing,
|
||||
showSnapshotsLegacy,
|
||||
defaultProduct
|
||||
showSnapshotsLegacy
|
||||
}) => {
|
||||
const { data } = await apiRequest.patch<{ workspace: Workspace }>(
|
||||
`/api/v1/workspace/${projectID}`,
|
||||
@@ -289,7 +289,6 @@ export const useUpdateProject = () => {
|
||||
name: newProjectName,
|
||||
description: newProjectDescription,
|
||||
slug: newSlug,
|
||||
defaultProduct,
|
||||
secretSharing,
|
||||
showSnapshotsLegacy
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export type Workspace = {
|
||||
__v: number;
|
||||
id: string;
|
||||
name: string;
|
||||
defaultProduct: ProjectType;
|
||||
type: ProjectType;
|
||||
description?: string;
|
||||
orgId: string;
|
||||
version: ProjectVersion;
|
||||
@@ -68,6 +68,7 @@ export type TGetUpgradeProjectStatusDTO = {
|
||||
// mutation dto
|
||||
export type CreateWorkspaceDTO = {
|
||||
projectName: string;
|
||||
type: ProjectType;
|
||||
projectDescription?: string;
|
||||
kmsKeyId?: string;
|
||||
template?: string;
|
||||
@@ -80,7 +81,6 @@ export type UpdateProjectDTO = {
|
||||
newSlug?: string;
|
||||
secretSharing?: boolean;
|
||||
showSnapshotsLegacy?: boolean;
|
||||
defaultProduct?: ProjectType;
|
||||
};
|
||||
|
||||
export type UpdatePitVersionLimitDTO = { projectSlug: string; pitVersionLimit: number };
|
||||
@@ -184,6 +184,7 @@ export type TSearchProjectsDTO = {
|
||||
name?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
type?: ProjectType;
|
||||
options?: { enabled?: boolean };
|
||||
orderBy?: ProjectIdentityOrderBy;
|
||||
orderDirection?: OrderByDirection;
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { useCallback } from "react";
|
||||
import { useBlocker } from "@tanstack/react-router";
|
||||
|
||||
import {
|
||||
BatchContext,
|
||||
useBatchModeActions
|
||||
} from "@app/pages/secret-manager/SecretDashboardPage/SecretMainPage.store";
|
||||
|
||||
type TNavigationBlockerReturn = {
|
||||
isBlocked: boolean;
|
||||
};
|
||||
|
||||
export const useNavigationBlocker = ({
|
||||
shouldBlock = false,
|
||||
message = "Are you sure you want to leave? You may have unsaved changes.",
|
||||
context
|
||||
}: {
|
||||
shouldBlock: boolean;
|
||||
message: string;
|
||||
context: BatchContext;
|
||||
}): TNavigationBlockerReturn => {
|
||||
const { clearAllPendingChanges } = useBatchModeActions();
|
||||
const blockerFn = useCallback(() => {
|
||||
if (!shouldBlock) return false;
|
||||
|
||||
// eslint-disable-next-line no-alert
|
||||
const confirmed = window.confirm(message);
|
||||
if (confirmed) {
|
||||
clearAllPendingChanges(context);
|
||||
}
|
||||
|
||||
return !confirmed;
|
||||
}, [shouldBlock, message, context]);
|
||||
|
||||
useBlocker(blockerFn, shouldBlock);
|
||||
|
||||
return {
|
||||
isBlocked: shouldBlock
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user