feat: cloudflare pages secret sync

This commit is contained in:
Sheen Capadngan
2025-06-20 03:43:36 +08:00
parent d2c7ed62d0
commit 57e97a146b
38 changed files with 644 additions and 22 deletions
@@ -48,6 +48,7 @@ import { ValidateAzureKeyVaultConnectionCredentialsSchema } from "./azure-key-va
import { ValidateCamundaConnectionCredentialsSchema } from "./camunda";
import { camundaConnectionService } from "./camunda/camunda-connection-service";
import { ValidateCloudflareConnectionCredentialsSchema } from "./cloudflare/cloudflare-connection-schema";
import { cloudflareConnectionService } from "./cloudflare/cloudflare-connection-service";
import { ValidateDatabricksConnectionCredentialsSchema } from "./databricks";
import { databricksConnectionService } from "./databricks/databricks-connection-service";
import { ValidateFlyioConnectionCredentialsSchema } from "./flyio";
@@ -519,6 +520,7 @@ export const appConnectionServiceFactory = ({
oci: ociConnectionService(connectAppConnectionById, licenseService),
onepass: onePassConnectionService(connectAppConnectionById),
render: renderConnectionService(connectAppConnectionById),
cloudflare: cloudflareConnectionService(connectAppConnectionById),
flyio: flyioConnectionService(connectAppConnectionById)
};
};
@@ -3,10 +3,14 @@ import { AxiosError } from "axios";
import { request } from "@app/lib/config/request";
import { BadRequestError } from "@app/lib/errors";
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
import { IntegrationUrls } from "@app/services/integration-auth/integration-list";
import { CloudflareConnectionMethod } from "./cloudflare-connection-enum";
import { TCloudflareConnectionConfig } from "./cloudflare-connection-types";
import { IntegrationUrls } from "@app/services/integration-auth/integration-list";
import {
TCloudflareConnection,
TCloudflareConnectionConfig,
TCloudflarePagesProject
} from "./cloudflare-connection-types";
export const getCloudflareConnectionListItem = () => {
return {
@@ -16,6 +20,29 @@ export const getCloudflareConnectionListItem = () => {
};
};
export const listCloudflarePagesProjects = async (
appConnection: TCloudflareConnection
): Promise<TCloudflarePagesProject[]> => {
const {
credentials: { apiToken, accountId }
} = appConnection;
const { data } = await request.get<{ result: { name: string; id: string }[] }>(
`${IntegrationUrls.CLOUDFLARE_API_URL}/client/v4/accounts/${accountId}/pages/projects`,
{
headers: {
Authorization: `Bearer ${apiToken}`,
Accept: "application/json"
}
}
);
return data.result.map((a) => ({
name: a.name,
id: a.id
}));
};
export const validateCloudflareConnectionCredentials = async (config: TCloudflareConnectionConfig) => {
const { apiToken, accountId } = config.credentials;
@@ -27,7 +54,7 @@ export const validateCloudflareConnectionCredentials = async (config: TCloudflar
}
});
if (resp.data.data === null) {
if (resp.data === null) {
throw new BadRequestError({
message: "Unable to validate connection: Invalid API token provided."
});
@@ -35,6 +62,7 @@ export const validateCloudflareConnectionCredentials = async (config: TCloudflar
} catch (error: unknown) {
if (error instanceof AxiosError) {
throw new BadRequestError({
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
message: `Failed to validate credentials: ${error.response?.data?.errors?.[0]?.message || error.message || "Unknown error"}`
});
}
@@ -0,0 +1,30 @@
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 { TCloudflareConnection } from "./cloudflare-connection-types";
type TGetAppConnectionFunc = (
app: AppConnection,
connectionId: string,
actor: OrgServiceActor
) => Promise<TCloudflareConnection>;
export const cloudflareConnectionService = (getAppConnection: TGetAppConnectionFunc) => {
const listPagesProjects = async (connectionId: string, actor: OrgServiceActor) => {
const appConnection = await getAppConnection(AppConnection.Cloudflare, connectionId, actor);
try {
const projects = await listCloudflarePagesProjects(appConnection);
return projects;
} catch (error) {
logger.error(error, "Failed to list Cloudflare Pages projects for Cloudflare connection");
return [];
}
};
return {
listPagesProjects
};
};
@@ -23,3 +23,8 @@ export type TCloudflareConnectionConfig = DiscriminativePick<
> & {
orgId: string;
};
export type TCloudflarePagesProject = {
id: string;
name: string;
};