From 4f348316e7855e84a74389f0504b31ae52243d54 Mon Sep 17 00:00:00 2001 From: x032205 Date: Wed, 9 Jul 2025 17:03:18 -0400 Subject: [PATCH] feat(secret-sync): Cloudflare Workers --- .../20250602155451_fix-secret-versions.ts | 2 +- backend/src/lib/api-docs/constants.ts | 3 + .../cloudflare-connection-router.ts | 28 ++++ .../cloudflare-workers-sync-router.ts | 17 +++ .../routes/v1/secret-sync-routers/index.ts | 2 + .../secret-sync-routers/secret-sync-router.ts | 6 + .../cloudflare/cloudflare-connection-fns.ts | 25 +++- .../cloudflare-connection-service.ts | 17 ++- .../cloudflare/cloudflare-connection-types.ts | 4 + .../cloudflare-workers-constants.ts | 10 ++ .../cloudflare-workers-fns.ts | 123 ++++++++++++++++++ .../cloudflare-workers-schemas.ts | 49 +++++++ .../cloudflare-workers-types.ts | 19 +++ .../secret-sync/cloudflare-workers/index.ts | 4 + .../services/secret-sync/secret-sync-enums.ts | 1 + .../services/secret-sync/secret-sync-fns.ts | 9 ++ .../services/secret-sync/secret-sync-maps.ts | 3 + .../services/secret-sync/secret-sync-types.ts | 10 ++ .../CloudflarePagesSyncFields.tsx | 4 +- .../CloudflareWorkersSyncFields.tsx | 59 +++++++++ .../SecretSyncDestinationFields.tsx | 3 + .../SecretSyncOptionsFields.tsx | 1 + .../CloudflareWorkersReviewFields.tsx | 14 ++ .../SecretSyncReviewFields.tsx | 4 + ...udflare-workers-sync-destination-schema.ts | 13 ++ .../forms/schemas/secret-sync-schema.ts | 2 + frontend/src/helpers/secretSyncs.ts | 5 + .../api/appConnections/cloudflare/queries.tsx | 37 +++++- .../api/appConnections/cloudflare/types.ts | 6 +- frontend/src/hooks/api/secretSyncs/enums.ts | 1 + .../types/cloudflare-workers-sync.ts | 15 +++ .../src/hooks/api/secretSyncs/types/index.ts | 2 + .../CloudflareWorkersSyncDestinationCol.tsx | 14 ++ .../SecretSyncDestinationCol.tsx | 3 + .../SecretSyncTable/helpers/index.ts | 4 + ...loudflareWorkersSyncDestinationSection.tsx | 14 ++ .../SecretSyncDestinatonSection.tsx | 4 + .../SecretSyncOptionsSection.tsx | 1 + 38 files changed, 526 insertions(+), 12 deletions(-) create mode 100644 backend/src/server/routes/v1/secret-sync-routers/cloudflare-workers-sync-router.ts create mode 100644 backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-constants.ts create mode 100644 backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-fns.ts create mode 100644 backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-schemas.ts create mode 100644 backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-types.ts create mode 100644 backend/src/services/secret-sync/cloudflare-workers/index.ts create mode 100644 frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/CloudflareWorkersSyncFields.tsx create mode 100644 frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/CloudflareWorkersReviewFields.tsx create mode 100644 frontend/src/components/secret-syncs/forms/schemas/cloudflare-workers-sync-destination-schema.ts create mode 100644 frontend/src/hooks/api/secretSyncs/types/cloudflare-workers-sync.ts create mode 100644 frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/CloudflareWorkersSyncDestinationCol.tsx create mode 100644 frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/CloudflareWorkersSyncDestinationSection.tsx diff --git a/backend/src/db/migrations/20250602155451_fix-secret-versions.ts b/backend/src/db/migrations/20250602155451_fix-secret-versions.ts index ace1895de..0fb23e327 100644 --- a/backend/src/db/migrations/20250602155451_fix-secret-versions.ts +++ b/backend/src/db/migrations/20250602155451_fix-secret-versions.ts @@ -3,7 +3,7 @@ import { Knex } from "knex"; import { chunkArray } from "@app/lib/fn"; import { selectAllTableCols } from "@app/lib/knex"; -import { logger, initLogger } from "@app/lib/logger"; +import { initLogger, logger } from "@app/lib/logger"; import { SecretType, TableName } from "../schemas"; diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index de5060f6f..e604899b6 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -2469,6 +2469,9 @@ export const SecretSyncs = { projectName: "The name of the Cloudflare Pages project to sync secrets to.", environment: "The environment of the Cloudflare Pages project to sync secrets to." }, + CLOUDFLARE_WORKERS: { + scriptId: "The ID of the Cloudflare Workers script to sync secrets to." + }, ZABBIX: { scope: "The Zabbix scope that secrets should be synced to.", hostId: "The ID of the Zabbix host to sync secrets to.", diff --git a/backend/src/server/routes/v1/app-connection-routers/cloudflare-connection-router.ts b/backend/src/server/routes/v1/app-connection-routers/cloudflare-connection-router.ts index bd3507a7d..e42935085 100644 --- a/backend/src/server/routes/v1/app-connection-routers/cloudflare-connection-router.ts +++ b/backend/src/server/routes/v1/app-connection-routers/cloudflare-connection-router.ts @@ -50,4 +50,32 @@ export const registerCloudflareConnectionRouter = async (server: FastifyZodProvi return projects; } }); + + server.route({ + method: "GET", + url: `/:connectionId/cloudflare-workers-projects`, + config: { + rateLimit: readLimit + }, + schema: { + params: z.object({ + connectionId: z.string().uuid() + }), + response: { + 200: z + .object({ + id: z.string() + }) + .array() + } + }, + onRequest: verifyAuth([AuthMode.JWT]), + handler: async (req) => { + const { connectionId } = req.params; + + const projects = await server.services.appConnection.cloudflare.listWorkersProjects(connectionId, req.permission); + + return projects; + } + }); }; diff --git a/backend/src/server/routes/v1/secret-sync-routers/cloudflare-workers-sync-router.ts b/backend/src/server/routes/v1/secret-sync-routers/cloudflare-workers-sync-router.ts new file mode 100644 index 000000000..a045a5031 --- /dev/null +++ b/backend/src/server/routes/v1/secret-sync-routers/cloudflare-workers-sync-router.ts @@ -0,0 +1,17 @@ +import { + CloudflareWorkersSyncSchema, + CreateCloudflareWorkersSyncSchema, + UpdateCloudflareWorkersSyncSchema +} from "@app/services/secret-sync/cloudflare-workers/cloudflare-workers-schemas"; +import { SecretSync } from "@app/services/secret-sync/secret-sync-enums"; + +import { registerSyncSecretsEndpoints } from "./secret-sync-endpoints"; + +export const registerCloudflareWorkersSyncRouter = async (server: FastifyZodProvider) => + registerSyncSecretsEndpoints({ + destination: SecretSync.CloudflareWorkers, + server, + responseSchema: CloudflareWorkersSyncSchema, + createSchema: CreateCloudflareWorkersSyncSchema, + updateSchema: UpdateCloudflareWorkersSyncSchema + }); diff --git a/backend/src/server/routes/v1/secret-sync-routers/index.ts b/backend/src/server/routes/v1/secret-sync-routers/index.ts index 67e1ac720..82e250fa1 100644 --- a/backend/src/server/routes/v1/secret-sync-routers/index.ts +++ b/backend/src/server/routes/v1/secret-sync-routers/index.ts @@ -9,6 +9,7 @@ import { registerAzureDevOpsSyncRouter } from "./azure-devops-sync-router"; import { registerAzureKeyVaultSyncRouter } from "./azure-key-vault-sync-router"; import { registerCamundaSyncRouter } from "./camunda-sync-router"; import { registerCloudflarePagesSyncRouter } from "./cloudflare-pages-sync-router"; +import { registerCloudflareWorkersSyncRouter } from "./cloudflare-workers-sync-router"; import { registerDatabricksSyncRouter } from "./databricks-sync-router"; import { registerFlyioSyncRouter } from "./flyio-sync-router"; import { registerGcpSyncRouter } from "./gcp-sync-router"; @@ -49,5 +50,6 @@ export const SECRET_SYNC_REGISTER_ROUTER_MAP: Record { @@ -43,6 +44,28 @@ export const listCloudflarePagesProjects = async ( })); }; +export const listCloudflareWorkersProjects = async ( + appConnection: TCloudflareConnection +): Promise => { + const { + credentials: { apiToken, accountId } + } = appConnection; + + const { data } = await request.get<{ result: { id: string }[] }>( + `${IntegrationUrls.CLOUDFLARE_API_URL}/client/v4/accounts/${accountId}/workers/scripts`, + { + headers: { + Authorization: `Bearer ${apiToken}`, + Accept: "application/json" + } + } + ); + + return data.result.map((a) => ({ + id: a.id + })); +}; + export const validateCloudflareConnectionCredentials = async (config: TCloudflareConnectionConfig) => { const { apiToken, accountId } = config.credentials; diff --git a/backend/src/services/app-connection/cloudflare/cloudflare-connection-service.ts b/backend/src/services/app-connection/cloudflare/cloudflare-connection-service.ts index 2d1f38786..4d7542a4b 100644 --- a/backend/src/services/app-connection/cloudflare/cloudflare-connection-service.ts +++ b/backend/src/services/app-connection/cloudflare/cloudflare-connection-service.ts @@ -2,7 +2,7 @@ import { logger } from "@app/lib/logger"; import { OrgServiceActor } from "@app/lib/types"; import { AppConnection } from "../app-connection-enums"; -import { listCloudflarePagesProjects } from "./cloudflare-connection-fns"; +import { listCloudflarePagesProjects, listCloudflareWorkersProjects } from "./cloudflare-connection-fns"; import { TCloudflareConnection } from "./cloudflare-connection-types"; type TGetAppConnectionFunc = ( @@ -24,7 +24,20 @@ export const cloudflareConnectionService = (getAppConnection: TGetAppConnectionF } }; + const listWorkersProjects = async (connectionId: string, actor: OrgServiceActor) => { + const appConnection = await getAppConnection(AppConnection.Cloudflare, connectionId, actor); + try { + const projects = await listCloudflareWorkersProjects(appConnection); + + return projects; + } catch (error) { + logger.error(error, "Failed to list Cloudflare Workers projects for Cloudflare connection"); + return []; + } + }; + return { - listPagesProjects + listPagesProjects, + listWorkersProjects }; }; diff --git a/backend/src/services/app-connection/cloudflare/cloudflare-connection-types.ts b/backend/src/services/app-connection/cloudflare/cloudflare-connection-types.ts index 6b2ee0d04..a340a3dcd 100644 --- a/backend/src/services/app-connection/cloudflare/cloudflare-connection-types.ts +++ b/backend/src/services/app-connection/cloudflare/cloudflare-connection-types.ts @@ -28,3 +28,7 @@ export type TCloudflarePagesProject = { id: string; name: string; }; + +export type TCloudflareWorkersProject = { + id: string; +}; diff --git a/backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-constants.ts b/backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-constants.ts new file mode 100644 index 000000000..459fda316 --- /dev/null +++ b/backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-constants.ts @@ -0,0 +1,10 @@ +import { AppConnection } from "@app/services/app-connection/app-connection-enums"; +import { SecretSync } from "@app/services/secret-sync/secret-sync-enums"; +import { TSecretSyncListItem } from "@app/services/secret-sync/secret-sync-types"; + +export const CLOUDFLARE_WORKERS_SYNC_LIST_OPTION: TSecretSyncListItem = { + name: "Cloudflare Workers", + destination: SecretSync.CloudflareWorkers, + connection: AppConnection.Cloudflare, + canImportSecrets: false +}; diff --git a/backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-fns.ts b/backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-fns.ts new file mode 100644 index 000000000..cd4984c97 --- /dev/null +++ b/backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-fns.ts @@ -0,0 +1,123 @@ +import { request } from "@app/lib/config/request"; +import { IntegrationUrls } from "@app/services/integration-auth/integration-list"; +import { matchesSchema } from "@app/services/secret-sync/secret-sync-fns"; +import { TSecretMap } from "@app/services/secret-sync/secret-sync-types"; + +import { SECRET_SYNC_NAME_MAP } from "../secret-sync-maps"; +import { TCloudflareWorkersSyncWithCredentials } from "./cloudflare-workers-types"; + +const getProjectEnvironmentSecretNames = async ( + secretSync: TCloudflareWorkersSyncWithCredentials +): Promise => { + const { + destinationConfig, + connection: { + credentials: { apiToken, accountId } + } + } = secretSync; + + const { data } = await request.get<{ + result: Array<{ name: string }>; + }>( + `${IntegrationUrls.CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accountId}/workers/scripts/${destinationConfig.scriptId}/secrets`, + { + headers: { + Authorization: `Bearer ${apiToken}`, + Accept: "application/json" + } + } + ); + + return data.result.map((s) => s.name); +}; + +const getSecretEndpointForSingle = (secretSync: TCloudflareWorkersSyncWithCredentials, secretName: string) => { + const { + destinationConfig, + connection: { + credentials: { accountId } + } + } = secretSync; + return `${IntegrationUrls.CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accountId}/workers/scripts/${destinationConfig.scriptId}/secrets/${secretName}`; +}; + +export const CloudflareWorkersSyncFns = { + syncSecrets: async (secretSync: TCloudflareWorkersSyncWithCredentials, secretMap: TSecretMap) => { + const { + connection: { + credentials: { apiToken } + } + } = secretSync; + + const existingSecretNames = await getProjectEnvironmentSecretNames(secretSync); + const secretMapKeys = new Set(Object.keys(secretMap)); + + const secretsToCreateOrUpdatePromises = Object.entries(secretMap).map(async ([key, val]) => { + await request.put( + getSecretEndpointForSingle(secretSync, key), + { value: val.value }, + { + headers: { + Authorization: `Bearer ${apiToken}`, + "Content-Type": "application/json" + } + } + ); + }); + await Promise.all(secretsToCreateOrUpdatePromises); + + if (!secretSync.syncOptions.disableSecretDeletion) { + const secretsToDeletePromises = existingSecretNames + .filter((existingKey) => { + const isManagedBySchema = matchesSchema( + existingKey, + secretSync.environment?.slug || "", + secretSync.syncOptions.keySchema + ); + const isInNewSecretMap = secretMapKeys.has(existingKey); + return !isInNewSecretMap && isManagedBySchema; + }) + .map(async (key) => { + await request.delete(getSecretEndpointForSingle(secretSync, key), { + headers: { + Authorization: `Bearer ${apiToken}` + } + }); + }); + await Promise.all(secretsToDeletePromises); + } + }, + + getSecrets: async (secretSync: TCloudflareWorkersSyncWithCredentials): Promise => { + throw new Error(`${SECRET_SYNC_NAME_MAP[secretSync.destination]} does not support importing secrets.`); + }, + + removeSecrets: async (secretSync: TCloudflareWorkersSyncWithCredentials, secretMap: TSecretMap) => { + const { + connection: { + credentials: { apiToken } + } + } = secretSync; + + const existingSecretNames = await getProjectEnvironmentSecretNames(secretSync); + const secretMapToRemoveKeys = new Set(Object.keys(secretMap)); + + const deletePromises = existingSecretNames.map(async (existingKey) => { + const isManagedBySchema = matchesSchema( + existingKey, + secretSync.environment?.slug || "", + secretSync.syncOptions.keySchema + ); + const isInSecretMapToRemove = secretMapToRemoveKeys.has(existingKey); + + if (isInSecretMapToRemove && isManagedBySchema) { + await request.delete(getSecretEndpointForSingle(secretSync, existingKey), { + headers: { + Authorization: `Bearer ${apiToken}` + } + }); + } + }); + await Promise.all(deletePromises); + } +}; diff --git a/backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-schemas.ts b/backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-schemas.ts new file mode 100644 index 000000000..c8bdac575 --- /dev/null +++ b/backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-schemas.ts @@ -0,0 +1,49 @@ +import { z } from "zod"; + +import { SecretSyncs } from "@app/lib/api-docs"; +import { AppConnection } from "@app/services/app-connection/app-connection-enums"; +import { SecretSync } from "@app/services/secret-sync/secret-sync-enums"; +import { + BaseSecretSyncSchema, + GenericCreateSecretSyncFieldsSchema, + GenericUpdateSecretSyncFieldsSchema +} from "@app/services/secret-sync/secret-sync-schemas"; +import { TSyncOptionsConfig } from "@app/services/secret-sync/secret-sync-types"; + +const CloudflareWorkersSyncDestinationConfigSchema = z.object({ + scriptId: z + .string() + .min(1, "Script ID is required") + .describe(SecretSyncs.DESTINATION_CONFIG.CLOUDFLARE_WORKERS.scriptId) +}); + +const CloudflareWorkersSyncOptionsConfig: TSyncOptionsConfig = { canImportSecrets: false }; + +export const CloudflareWorkersSyncSchema = BaseSecretSyncSchema( + SecretSync.CloudflareWorkers, + CloudflareWorkersSyncOptionsConfig +).extend({ + destination: z.literal(SecretSync.CloudflareWorkers), + destinationConfig: CloudflareWorkersSyncDestinationConfigSchema +}); + +export const CreateCloudflareWorkersSyncSchema = GenericCreateSecretSyncFieldsSchema( + SecretSync.CloudflareWorkers, + CloudflareWorkersSyncOptionsConfig +).extend({ + destinationConfig: CloudflareWorkersSyncDestinationConfigSchema +}); + +export const UpdateCloudflareWorkersSyncSchema = GenericUpdateSecretSyncFieldsSchema( + SecretSync.CloudflareWorkers, + CloudflareWorkersSyncOptionsConfig +).extend({ + destinationConfig: CloudflareWorkersSyncDestinationConfigSchema.optional() +}); + +export const CloudflareWorkersSyncListItemSchema = z.object({ + name: z.literal("Cloudflare Workers"), + connection: z.literal(AppConnection.Cloudflare), + destination: z.literal(SecretSync.CloudflareWorkers), + canImportSecrets: z.literal(false) +}); diff --git a/backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-types.ts b/backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-types.ts new file mode 100644 index 000000000..1b5adda7b --- /dev/null +++ b/backend/src/services/secret-sync/cloudflare-workers/cloudflare-workers-types.ts @@ -0,0 +1,19 @@ +import z from "zod"; + +import { TCloudflareConnection } from "@app/services/app-connection/cloudflare/cloudflare-connection-types"; + +import { + CloudflareWorkersSyncListItemSchema, + CloudflareWorkersSyncSchema, + CreateCloudflareWorkersSyncSchema +} from "./cloudflare-workers-schemas"; + +export type TCloudflareWorkersSyncListItem = z.infer; + +export type TCloudflareWorkersSync = z.infer; + +export type TCloudflareWorkersSyncInput = z.infer; + +export type TCloudflareWorkersSyncWithCredentials = TCloudflareWorkersSync & { + connection: TCloudflareConnection; +}; diff --git a/backend/src/services/secret-sync/cloudflare-workers/index.ts b/backend/src/services/secret-sync/cloudflare-workers/index.ts new file mode 100644 index 000000000..5d7916a4d --- /dev/null +++ b/backend/src/services/secret-sync/cloudflare-workers/index.ts @@ -0,0 +1,4 @@ +export * from "./cloudflare-workers-constants"; +export * from "./cloudflare-workers-fns"; +export * from "./cloudflare-workers-schemas"; +export * from "./cloudflare-workers-types"; diff --git a/backend/src/services/secret-sync/secret-sync-enums.ts b/backend/src/services/secret-sync/secret-sync-enums.ts index 62730c3da..022a7a1b3 100644 --- a/backend/src/services/secret-sync/secret-sync-enums.ts +++ b/backend/src/services/secret-sync/secret-sync-enums.ts @@ -21,6 +21,7 @@ export enum SecretSync { Flyio = "flyio", GitLab = "gitlab", CloudflarePages = "cloudflare-pages", + CloudflareWorkers = "cloudflare-workers", Zabbix = "zabbix" } diff --git a/backend/src/services/secret-sync/secret-sync-fns.ts b/backend/src/services/secret-sync/secret-sync-fns.ts index d058d355e..46ebd3742 100644 --- a/backend/src/services/secret-sync/secret-sync-fns.ts +++ b/backend/src/services/secret-sync/secret-sync-fns.ts @@ -31,6 +31,7 @@ import { AZURE_KEY_VAULT_SYNC_LIST_OPTION, azureKeyVaultSyncFactory } from "./az import { CAMUNDA_SYNC_LIST_OPTION, camundaSyncFactory } from "./camunda"; import { CLOUDFLARE_PAGES_SYNC_LIST_OPTION } from "./cloudflare-pages/cloudflare-pages-constants"; import { CloudflarePagesSyncFns } from "./cloudflare-pages/cloudflare-pages-fns"; +import { CLOUDFLARE_WORKERS_SYNC_LIST_OPTION, CloudflareWorkersSyncFns } from "./cloudflare-workers"; import { FLYIO_SYNC_LIST_OPTION, FlyioSyncFns } from "./flyio"; import { GCP_SYNC_LIST_OPTION } from "./gcp"; import { GcpSyncFns } from "./gcp/gcp-sync-fns"; @@ -70,6 +71,7 @@ const SECRET_SYNC_LIST_OPTIONS: Record = { [SecretSync.Flyio]: FLYIO_SYNC_LIST_OPTION, [SecretSync.GitLab]: GITLAB_SYNC_LIST_OPTION, [SecretSync.CloudflarePages]: CLOUDFLARE_PAGES_SYNC_LIST_OPTION, + [SecretSync.CloudflareWorkers]: CLOUDFLARE_WORKERS_SYNC_LIST_OPTION, [SecretSync.Zabbix]: ZABBIX_SYNC_LIST_OPTION }; @@ -238,6 +240,8 @@ export const SecretSyncFns = { return GitLabSyncFns.syncSecrets(secretSync, schemaSecretMap, { appConnectionDAL, kmsService }); case SecretSync.CloudflarePages: return CloudflarePagesSyncFns.syncSecrets(secretSync, schemaSecretMap); + case SecretSync.CloudflareWorkers: + return CloudflareWorkersSyncFns.syncSecrets(secretSync, schemaSecretMap); case SecretSync.Zabbix: return ZabbixSyncFns.syncSecrets(secretSync, schemaSecretMap); default: @@ -332,6 +336,9 @@ export const SecretSyncFns = { case SecretSync.CloudflarePages: secretMap = await CloudflarePagesSyncFns.getSecrets(secretSync); break; + case SecretSync.CloudflareWorkers: + secretMap = await CloudflareWorkersSyncFns.getSecrets(secretSync); + break; case SecretSync.Zabbix: secretMap = await ZabbixSyncFns.getSecrets(secretSync); break; @@ -412,6 +419,8 @@ export const SecretSyncFns = { return GitLabSyncFns.removeSecrets(secretSync, schemaSecretMap, { appConnectionDAL, kmsService }); case SecretSync.CloudflarePages: return CloudflarePagesSyncFns.removeSecrets(secretSync, schemaSecretMap); + case SecretSync.CloudflareWorkers: + return CloudflareWorkersSyncFns.removeSecrets(secretSync, schemaSecretMap); case SecretSync.Zabbix: return ZabbixSyncFns.removeSecrets(secretSync, schemaSecretMap); default: diff --git a/backend/src/services/secret-sync/secret-sync-maps.ts b/backend/src/services/secret-sync/secret-sync-maps.ts index 25df5d0b4..f7cdc9896 100644 --- a/backend/src/services/secret-sync/secret-sync-maps.ts +++ b/backend/src/services/secret-sync/secret-sync-maps.ts @@ -24,6 +24,7 @@ export const SECRET_SYNC_NAME_MAP: Record = { [SecretSync.Flyio]: "Fly.io", [SecretSync.GitLab]: "GitLab", [SecretSync.CloudflarePages]: "Cloudflare Pages", + [SecretSync.CloudflareWorkers]: "Cloudflare Workers", [SecretSync.Zabbix]: "Zabbix" }; @@ -50,6 +51,7 @@ export const SECRET_SYNC_CONNECTION_MAP: Record = { [SecretSync.Flyio]: AppConnection.Flyio, [SecretSync.GitLab]: AppConnection.GitLab, [SecretSync.CloudflarePages]: AppConnection.Cloudflare, + [SecretSync.CloudflareWorkers]: AppConnection.Cloudflare, [SecretSync.Zabbix]: AppConnection.Zabbix }; @@ -76,5 +78,6 @@ export const SECRET_SYNC_PLAN_MAP: Record = { [SecretSync.Flyio]: SecretSyncPlanType.Regular, [SecretSync.GitLab]: SecretSyncPlanType.Regular, [SecretSync.CloudflarePages]: SecretSyncPlanType.Regular, + [SecretSync.CloudflareWorkers]: SecretSyncPlanType.Regular, [SecretSync.Zabbix]: SecretSyncPlanType.Regular }; diff --git a/backend/src/services/secret-sync/secret-sync-types.ts b/backend/src/services/secret-sync/secret-sync-types.ts index b076ea9c4..272002d05 100644 --- a/backend/src/services/secret-sync/secret-sync-types.ts +++ b/backend/src/services/secret-sync/secret-sync-types.ts @@ -78,6 +78,12 @@ import { TCloudflarePagesSyncListItem, TCloudflarePagesSyncWithCredentials } from "./cloudflare-pages/cloudflare-pages-types"; +import { + TCloudflareWorkersSync, + TCloudflareWorkersSyncInput, + TCloudflareWorkersSyncListItem, + TCloudflareWorkersSyncWithCredentials +} from "./cloudflare-workers"; import { TFlyioSync, TFlyioSyncInput, TFlyioSyncListItem, TFlyioSyncWithCredentials } from "./flyio/flyio-sync-types"; import { TGcpSync, TGcpSyncInput, TGcpSyncListItem, TGcpSyncWithCredentials } from "./gcp"; import { TGitLabSync, TGitLabSyncInput, TGitLabSyncListItem, TGitLabSyncWithCredentials } from "./gitlab"; @@ -138,6 +144,7 @@ export type TSecretSync = | TFlyioSync | TGitLabSync | TCloudflarePagesSync + | TCloudflareWorkersSync | TZabbixSync; export type TSecretSyncWithCredentials = @@ -163,6 +170,7 @@ export type TSecretSyncWithCredentials = | TFlyioSyncWithCredentials | TGitLabSyncWithCredentials | TCloudflarePagesSyncWithCredentials + | TCloudflareWorkersSyncWithCredentials | TZabbixSyncWithCredentials; export type TSecretSyncInput = @@ -188,6 +196,7 @@ export type TSecretSyncInput = | TFlyioSyncInput | TGitLabSyncInput | TCloudflarePagesSyncInput + | TCloudflareWorkersSyncInput | TZabbixSyncInput; export type TSecretSyncListItem = @@ -213,6 +222,7 @@ export type TSecretSyncListItem = | TFlyioSyncListItem | TGitLabSyncListItem | TCloudflarePagesSyncListItem + | TCloudflareWorkersSyncListItem | TZabbixSyncListItem; export type TSyncOptionsConfig = { diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/CloudflarePagesSyncFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/CloudflarePagesSyncFields.tsx index d19092d63..eb196c9a4 100644 --- a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/CloudflarePagesSyncFields.tsx +++ b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/CloudflarePagesSyncFields.tsx @@ -4,7 +4,7 @@ import { SingleValue } from "react-select"; import { SecretSyncConnectionField } from "@app/components/secret-syncs/forms/SecretSyncConnectionField"; import { FilterableSelect, FormControl, Select, SelectItem } from "@app/components/v2"; import { - TCloudflareProject, + TCloudflarePagesProject, useCloudflareConnectionListPagesProjects } from "@app/hooks/api/appConnections/cloudflare"; import { SecretSync } from "@app/hooks/api/secretSyncs"; @@ -52,7 +52,7 @@ export const CloudflarePagesSyncFields = () => { isDisabled={!connectionId} value={projects ? (projects.find((project) => project.name === value) ?? []) : []} onChange={(option) => { - onChange((option as SingleValue)?.name ?? null); + onChange((option as SingleValue)?.name ?? null); }} options={projects} placeholder="Select a project..." diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/CloudflareWorkersSyncFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/CloudflareWorkersSyncFields.tsx new file mode 100644 index 000000000..a565abade --- /dev/null +++ b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/CloudflareWorkersSyncFields.tsx @@ -0,0 +1,59 @@ +import { Controller, useFormContext, useWatch } from "react-hook-form"; +import { SingleValue } from "react-select"; + +import { SecretSyncConnectionField } from "@app/components/secret-syncs/forms/SecretSyncConnectionField"; +import { FilterableSelect, FormControl } from "@app/components/v2"; +import { + TCloudflareWorkersProject, + useCloudflareConnectionListWorkersProjects +} from "@app/hooks/api/appConnections/cloudflare"; +import { SecretSync } from "@app/hooks/api/secretSyncs"; + +import { TSecretSyncForm } from "../schemas"; + +export const CloudflareWorkersSyncFields = () => { + const { control, setValue } = useFormContext< + TSecretSyncForm & { destination: SecretSync.CloudflareWorkers } + >(); + + const connectionId = useWatch({ name: "connection.id", control }); + + const { data: projects = [], isPending: isProjectsPending } = + useCloudflareConnectionListWorkersProjects(connectionId, { + enabled: Boolean(connectionId) + }); + + return ( + <> + { + setValue("destinationConfig.scriptId", ""); + }} + /> + ( + + project.id === value) ?? []) : []} + onChange={(option) => { + onChange((option as SingleValue)?.id ?? null); + }} + options={projects} + placeholder="Select a worker script..." + getOptionLabel={(option) => option.id} + getOptionValue={(option) => option.id} + /> + + )} + /> + + ); +}; diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/SecretSyncDestinationFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/SecretSyncDestinationFields.tsx index da8686cc1..b50b2c00f 100644 --- a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/SecretSyncDestinationFields.tsx +++ b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/SecretSyncDestinationFields.tsx @@ -11,6 +11,7 @@ import { AzureDevOpsSyncFields } from "./AzureDevOpsSyncFields"; import { AzureKeyVaultSyncFields } from "./AzureKeyVaultSyncFields"; import { CamundaSyncFields } from "./CamundaSyncFields"; import { CloudflarePagesSyncFields } from "./CloudflarePagesSyncFields"; +import { CloudflareWorkersSyncFields } from "./CloudflareWorkersSyncFields"; import { DatabricksSyncFields } from "./DatabricksSyncFields"; import { FlyioSyncFields } from "./FlyioSyncFields"; import { GcpSyncFields } from "./GcpSyncFields"; @@ -77,6 +78,8 @@ export const SecretSyncDestinationFields = () => { return ; case SecretSync.CloudflarePages: return ; + case SecretSync.CloudflareWorkers: + return ; case SecretSync.Zabbix: return ; default: diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncOptionsFields/SecretSyncOptionsFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncOptionsFields/SecretSyncOptionsFields.tsx index d91fc3771..f05b2d67e 100644 --- a/frontend/src/components/secret-syncs/forms/SecretSyncOptionsFields/SecretSyncOptionsFields.tsx +++ b/frontend/src/components/secret-syncs/forms/SecretSyncOptionsFields/SecretSyncOptionsFields.tsx @@ -58,6 +58,7 @@ export const SecretSyncOptionsFields = ({ hideInitialSync }: Props) => { case SecretSync.Flyio: case SecretSync.GitLab: case SecretSync.CloudflarePages: + case SecretSync.CloudflareWorkers: case SecretSync.Zabbix: AdditionalSyncOptionsFieldsComponent = null; break; diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/CloudflareWorkersReviewFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/CloudflareWorkersReviewFields.tsx new file mode 100644 index 000000000..6fe0f1f6a --- /dev/null +++ b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/CloudflareWorkersReviewFields.tsx @@ -0,0 +1,14 @@ +import { useFormContext } from "react-hook-form"; + +import { TSecretSyncForm } from "@app/components/secret-syncs/forms/schemas"; +import { GenericFieldLabel } from "@app/components/v2"; +import { SecretSync } from "@app/hooks/api/secretSyncs"; + +export const CloudflareWorkersSyncReviewFields = () => { + const { watch } = useFormContext< + TSecretSyncForm & { destination: SecretSync.CloudflareWorkers } + >(); + const scriptId = watch("destinationConfig.scriptId"); + + return {scriptId}; +}; diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/SecretSyncReviewFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/SecretSyncReviewFields.tsx index e2ffb9fa6..b5ebda7fa 100644 --- a/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/SecretSyncReviewFields.tsx +++ b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/SecretSyncReviewFields.tsx @@ -20,6 +20,7 @@ import { AzureDevOpsSyncReviewFields } from "./AzureDevOpsSyncReviewFields"; import { AzureKeyVaultSyncReviewFields } from "./AzureKeyVaultSyncReviewFields"; import { CamundaSyncReviewFields } from "./CamundaSyncReviewFields"; import { CloudflarePagesSyncReviewFields } from "./CloudflarePagesReviewFields"; +import { CloudflareWorkersSyncReviewFields } from "./CloudflareWorkersReviewFields"; import { DatabricksSyncReviewFields } from "./DatabricksSyncReviewFields"; import { FlyioSyncReviewFields } from "./FlyioSyncReviewFields"; import { GcpSyncReviewFields } from "./GcpSyncReviewFields"; @@ -125,6 +126,9 @@ export const SecretSyncReviewFields = () => { case SecretSync.CloudflarePages: DestinationFieldsComponent = ; break; + case SecretSync.CloudflareWorkers: + DestinationFieldsComponent = ; + break; case SecretSync.Zabbix: DestinationFieldsComponent = ; break; diff --git a/frontend/src/components/secret-syncs/forms/schemas/cloudflare-workers-sync-destination-schema.ts b/frontend/src/components/secret-syncs/forms/schemas/cloudflare-workers-sync-destination-schema.ts new file mode 100644 index 000000000..4723204fd --- /dev/null +++ b/frontend/src/components/secret-syncs/forms/schemas/cloudflare-workers-sync-destination-schema.ts @@ -0,0 +1,13 @@ +import { z } from "zod"; + +import { BaseSecretSyncSchema } from "@app/components/secret-syncs/forms/schemas/base-secret-sync-schema"; +import { SecretSync } from "@app/hooks/api/secretSyncs"; + +export const CloudflareWorkersSyncDestinationSchema = BaseSecretSyncSchema().merge( + z.object({ + destination: z.literal(SecretSync.CloudflareWorkers), + destinationConfig: z.object({ + scriptId: z.string().trim().min(1, "Script ID is required") + }) + }) +); diff --git a/frontend/src/components/secret-syncs/forms/schemas/secret-sync-schema.ts b/frontend/src/components/secret-syncs/forms/schemas/secret-sync-schema.ts index 331768e7f..2a3b802d3 100644 --- a/frontend/src/components/secret-syncs/forms/schemas/secret-sync-schema.ts +++ b/frontend/src/components/secret-syncs/forms/schemas/secret-sync-schema.ts @@ -8,6 +8,7 @@ import { AzureDevOpsSyncDestinationSchema } from "./azure-devops-sync-destinatio import { AzureKeyVaultSyncDestinationSchema } from "./azure-key-vault-sync-destination-schema"; import { CamundaSyncDestinationSchema } from "./camunda-sync-destination-schema"; import { CloudflarePagesSyncDestinationSchema } from "./cloudflare-pages-sync-destination-schema"; +import { CloudflareWorkersSyncDestinationSchema } from "./cloudflare-workers-sync-destination-schema"; import { DatabricksSyncDestinationSchema } from "./databricks-sync-destination-schema"; import { FlyioSyncDestinationSchema } from "./flyio-sync-destination-schema"; import { GcpSyncDestinationSchema } from "./gcp-sync-destination-schema"; @@ -47,6 +48,7 @@ const SecretSyncUnionSchema = z.discriminatedUnion("destination", [ FlyioSyncDestinationSchema, GitlabSyncDestinationSchema, CloudflarePagesSyncDestinationSchema, + CloudflareWorkersSyncDestinationSchema, ZabbixSyncDestinationSchema ]); diff --git a/frontend/src/helpers/secretSyncs.ts b/frontend/src/helpers/secretSyncs.ts index e42898036..be96e85e4 100644 --- a/frontend/src/helpers/secretSyncs.ts +++ b/frontend/src/helpers/secretSyncs.ts @@ -82,6 +82,10 @@ export const SECRET_SYNC_MAP: Record = { [SecretSync.Flyio]: AppConnection.Flyio, [SecretSync.GitLab]: AppConnection.Gitlab, [SecretSync.CloudflarePages]: AppConnection.Cloudflare, + [SecretSync.CloudflareWorkers]: AppConnection.Cloudflare, [SecretSync.Zabbix]: AppConnection.Zabbix }; diff --git a/frontend/src/hooks/api/appConnections/cloudflare/queries.tsx b/frontend/src/hooks/api/appConnections/cloudflare/queries.tsx index ae2efea99..267de55cc 100644 --- a/frontend/src/hooks/api/appConnections/cloudflare/queries.tsx +++ b/frontend/src/hooks/api/appConnections/cloudflare/queries.tsx @@ -3,21 +3,23 @@ import { useQuery, UseQueryOptions } from "@tanstack/react-query"; import { apiRequest } from "@app/config/request"; import { appConnectionKeys } from "../queries"; -import { TCloudflareProject } from "./types"; +import { TCloudflarePagesProject, TCloudflareWorkersProject } from "./types"; const cloudflareConnectionKeys = { all: [...appConnectionKeys.all, "cloudflare"] as const, listPagesProjects: (connectionId: string) => - [...cloudflareConnectionKeys.all, "pages-projects", connectionId] as const + [...cloudflareConnectionKeys.all, "pages-projects", connectionId] as const, + listWorkersProjects: (connectionId: string) => + [...cloudflareConnectionKeys.all, "workers-projects", connectionId] as const }; export const useCloudflareConnectionListPagesProjects = ( connectionId: string, options?: Omit< UseQueryOptions< - TCloudflareProject[], + TCloudflarePagesProject[], unknown, - TCloudflareProject[], + TCloudflarePagesProject[], ReturnType >, "queryKey" | "queryFn" @@ -26,7 +28,7 @@ export const useCloudflareConnectionListPagesProjects = ( return useQuery({ queryKey: cloudflareConnectionKeys.listPagesProjects(connectionId), queryFn: async () => { - const { data } = await apiRequest.get( + const { data } = await apiRequest.get( `/api/v1/app-connections/cloudflare/${connectionId}/cloudflare-pages-projects` ); @@ -35,3 +37,28 @@ export const useCloudflareConnectionListPagesProjects = ( ...options }); }; + +export const useCloudflareConnectionListWorkersProjects = ( + connectionId: string, + options?: Omit< + UseQueryOptions< + TCloudflareWorkersProject[], + unknown, + TCloudflareWorkersProject[], + ReturnType + >, + "queryKey" | "queryFn" + > +) => { + return useQuery({ + queryKey: cloudflareConnectionKeys.listWorkersProjects(connectionId), + queryFn: async () => { + const { data } = await apiRequest.get( + `/api/v1/app-connections/cloudflare/${connectionId}/cloudflare-workers-projects` + ); + + return data; + }, + ...options + }); +}; diff --git a/frontend/src/hooks/api/appConnections/cloudflare/types.ts b/frontend/src/hooks/api/appConnections/cloudflare/types.ts index ed7bda478..9f3996228 100644 --- a/frontend/src/hooks/api/appConnections/cloudflare/types.ts +++ b/frontend/src/hooks/api/appConnections/cloudflare/types.ts @@ -1,4 +1,8 @@ -export type TCloudflareProject = { +export type TCloudflarePagesProject = { id: string; name: string; }; + +export type TCloudflareWorkersProject = { + id: string; +}; diff --git a/frontend/src/hooks/api/secretSyncs/enums.ts b/frontend/src/hooks/api/secretSyncs/enums.ts index ab79f73bb..71b57df40 100644 --- a/frontend/src/hooks/api/secretSyncs/enums.ts +++ b/frontend/src/hooks/api/secretSyncs/enums.ts @@ -21,6 +21,7 @@ export enum SecretSync { Flyio = "flyio", GitLab = "gitlab", CloudflarePages = "cloudflare-pages", + CloudflareWorkers = "cloudflare-workers", Zabbix = "zabbix" } diff --git a/frontend/src/hooks/api/secretSyncs/types/cloudflare-workers-sync.ts b/frontend/src/hooks/api/secretSyncs/types/cloudflare-workers-sync.ts new file mode 100644 index 000000000..224fe8938 --- /dev/null +++ b/frontend/src/hooks/api/secretSyncs/types/cloudflare-workers-sync.ts @@ -0,0 +1,15 @@ +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 TCloudflareWorkersSync = TRootSecretSync & { + destination: SecretSync.CloudflareWorkers; + destinationConfig: { + scriptId: string; + }; + connection: { + app: AppConnection.Cloudflare; + name: string; + id: string; + }; +}; diff --git a/frontend/src/hooks/api/secretSyncs/types/index.ts b/frontend/src/hooks/api/secretSyncs/types/index.ts index 33119b8a3..762a870a4 100644 --- a/frontend/src/hooks/api/secretSyncs/types/index.ts +++ b/frontend/src/hooks/api/secretSyncs/types/index.ts @@ -10,6 +10,7 @@ import { TAzureDevOpsSync } from "./azure-devops-sync"; import { TAzureKeyVaultSync } from "./azure-key-vault-sync"; import { TCamundaSync } from "./camunda-sync"; import { TCloudflarePagesSync } from "./cloudflare-pages-sync"; +import { TCloudflareWorkersSync } from "./cloudflare-workers-sync"; import { TDatabricksSync } from "./databricks-sync"; import { TFlyioSync } from "./flyio-sync"; import { TGcpSync } from "./gcp-sync"; @@ -55,6 +56,7 @@ export type TSecretSync = | TFlyioSync | TGitLabSync | TCloudflarePagesSync + | TCloudflareWorkersSync | TZabbixSync; export type TListSecretSyncs = { secretSyncs: TSecretSync[] }; diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/CloudflareWorkersSyncDestinationCol.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/CloudflareWorkersSyncDestinationCol.tsx new file mode 100644 index 000000000..2efbdc75e --- /dev/null +++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/CloudflareWorkersSyncDestinationCol.tsx @@ -0,0 +1,14 @@ +import { TCloudflareWorkersSync } from "@app/hooks/api/secretSyncs/types/cloudflare-workers-sync"; + +import { getSecretSyncDestinationColValues } from "../helpers"; +import { SecretSyncTableCell } from "../SecretSyncTableCell"; + +type Props = { + secretSync: TCloudflareWorkersSync; +}; + +export const CloudflareWorkersSyncDestinationCol = ({ secretSync }: Props) => { + const { primaryText, secondaryText } = getSecretSyncDestinationColValues(secretSync); + + return ; +}; diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/SecretSyncDestinationCol.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/SecretSyncDestinationCol.tsx index c980df5bd..8b764a128 100644 --- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/SecretSyncDestinationCol.tsx +++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/SecretSyncDestinationCol.tsx @@ -8,6 +8,7 @@ import { AzureDevOpsSyncDestinationCol } from "./AzureDevOpsSyncDestinationCol"; import { AzureKeyVaultDestinationSyncCol } from "./AzureKeyVaultDestinationSyncCol"; import { CamundaSyncDestinationCol } from "./CamundaSyncDestinationCol"; import { CloudflarePagesSyncDestinationCol } from "./CloudflarePagesSyncDestinationCol"; +import { CloudflareWorkersSyncDestinationCol } from "./CloudflareWorkersSyncDestinationCol"; import { DatabricksSyncDestinationCol } from "./DatabricksSyncDestinationCol"; import { FlyioSyncDestinationCol } from "./FlyioSyncDestinationCol"; import { GcpSyncDestinationCol } from "./GcpSyncDestinationCol"; @@ -74,6 +75,8 @@ export const SecretSyncDestinationCol = ({ secretSync }: Props) => { return ; case SecretSync.CloudflarePages: return ; + case SecretSync.CloudflareWorkers: + return ; case SecretSync.Zabbix: return ; default: diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/helpers/index.ts b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/helpers/index.ts index 1787162e3..cedfebe9a 100644 --- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/helpers/index.ts +++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/helpers/index.ts @@ -145,6 +145,10 @@ export const getSecretSyncDestinationColValues = (secretSync: TSecretSync) => { primaryText = destinationConfig.projectName; secondaryText = destinationConfig.environment; break; + case SecretSync.CloudflareWorkers: + primaryText = destinationConfig.scriptId; + secondaryText = "Script ID"; + break; case SecretSync.Zabbix: if (destinationConfig.scope === ZabbixSyncScope.Host) { primaryText = destinationConfig.hostName; diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/CloudflareWorkersSyncDestinationSection.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/CloudflareWorkersSyncDestinationSection.tsx new file mode 100644 index 000000000..7d60315ca --- /dev/null +++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/CloudflareWorkersSyncDestinationSection.tsx @@ -0,0 +1,14 @@ +import { GenericFieldLabel } from "@app/components/secret-syncs"; +import { TCloudflareWorkersSync } from "@app/hooks/api/secretSyncs/types/cloudflare-workers-sync"; + +type Props = { + secretSync: TCloudflareWorkersSync; +}; + +export const CloudflareWorkersSyncDestinationSection = ({ secretSync }: Props) => { + const { + destinationConfig: { scriptId } + } = secretSync; + + return {scriptId}; +}; diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/SecretSyncDestinatonSection.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/SecretSyncDestinatonSection.tsx index 15c1b61f1..e69b8f082 100644 --- a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/SecretSyncDestinatonSection.tsx +++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/SecretSyncDestinatonSection.tsx @@ -19,6 +19,7 @@ import { AzureDevOpsSyncDestinationSection } from "./AzureDevOpsSyncDestinationS import { AzureKeyVaultSyncDestinationSection } from "./AzureKeyVaultSyncDestinationSection"; import { CamundaSyncDestinationSection } from "./CamundaSyncDestinationSection"; import { CloudflarePagesSyncDestinationSection } from "./CloudflarePagesSyncDestinationSection"; +import { CloudflareWorkersSyncDestinationSection } from "./CloudflareWorkersSyncDestinationSection"; import { DatabricksSyncDestinationSection } from "./DatabricksSyncDestinationSection"; import { FlyioSyncDestinationSection } from "./FlyioSyncDestinationSection"; import { GcpSyncDestinationSection } from "./GcpSyncDestinationSection"; @@ -115,6 +116,9 @@ export const SecretSyncDestinationSection = ({ secretSync, onEditDestination }: case SecretSync.CloudflarePages: DestinationComponents = ; break; + case SecretSync.CloudflareWorkers: + DestinationComponents = ; + break; case SecretSync.Zabbix: DestinationComponents = ; break; diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncOptionsSection/SecretSyncOptionsSection.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncOptionsSection/SecretSyncOptionsSection.tsx index 225800783..8d0c8a729 100644 --- a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncOptionsSection/SecretSyncOptionsSection.tsx +++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncOptionsSection/SecretSyncOptionsSection.tsx @@ -60,6 +60,7 @@ export const SecretSyncOptionsSection = ({ secretSync, onEditOptions }: Props) = case SecretSync.Flyio: case SecretSync.GitLab: case SecretSync.CloudflarePages: + case SecretSync.CloudflareWorkers: case SecretSync.Zabbix: AdditionalSyncOptionsComponent = null; break;