From caf6a46a4e618d6639b8eb183efc22284cf251ea Mon Sep 17 00:00:00 2001 From: Phillip Ho Date: Thu, 28 Mar 2024 16:36:30 -0700 Subject: [PATCH] feat: set CORS URLs endpoint (#472) * feat: set CORS URLs endpoint * remove debug --- src/server/routes/configuration/cors/add.ts | 5 +- src/server/routes/configuration/cors/get.ts | 10 ++- .../routes/configuration/cors/remove.ts | 4 +- src/server/routes/configuration/cors/set.ts | 63 +++++++++++++++++++ src/server/routes/index.ts | 2 + 5 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 src/server/routes/configuration/cors/set.ts diff --git a/src/server/routes/configuration/cors/add.ts b/src/server/routes/configuration/cors/add.ts index eddcbc51b..b004e5b57 100644 --- a/src/server/routes/configuration/cors/add.ts +++ b/src/server/routes/configuration/cors/add.ts @@ -10,8 +10,7 @@ import { ReplySchema } from "./get"; const BodySchema = Type.Object({ urlsToAdd: Type.Array( Type.String({ - description: - "Comma separated list of origins to allow CORS for. Thirdweb URLs are automatically added.", + description: "Comma separated list of origins that will call Engine", minLength: 1, }), ), @@ -19,7 +18,7 @@ const BodySchema = Type.Object({ BodySchema.examples = [ { - urlsToAdd: ["https://example.com", "https://example2.com"], + urlsToAdd: ["https://example.com", "https://subdomain.example.com"], }, ]; diff --git a/src/server/routes/configuration/cors/get.ts b/src/server/routes/configuration/cors/get.ts index 63a238c34..f9ad642d0 100644 --- a/src/server/routes/configuration/cors/get.ts +++ b/src/server/routes/configuration/cors/get.ts @@ -3,9 +3,10 @@ import { FastifyInstance } from "fastify"; import { StatusCodes } from "http-status-codes"; import { getConfig } from "../../../../utils/cache/getConfig"; import { standardResponseSchema } from "../../../schemas/sharedApiSchemas"; +import { mandatoryAllowedCorsUrls } from "../../../utils/cors-urls"; export const ReplySchema = Type.Object({ - result: Type.Union([Type.Array(Type.String()), Type.String(), Type.Null()]), + result: Type.Array(Type.String()), }); export async function getCorsConfiguration(fastify: FastifyInstance) { @@ -27,8 +28,13 @@ export async function getCorsConfiguration(fastify: FastifyInstance) { handler: async (req, res) => { const config = await getConfig(false); + // Omit required domains. + const omitted = config.accessControlAllowOrigin + .split(",") + .filter((url) => !mandatoryAllowedCorsUrls.includes(url)); + res.status(200).send({ - result: config.accessControlAllowOrigin.split(","), + result: omitted, }); }, }); diff --git a/src/server/routes/configuration/cors/remove.ts b/src/server/routes/configuration/cors/remove.ts index 3eb651e0a..662c439eb 100644 --- a/src/server/routes/configuration/cors/remove.ts +++ b/src/server/routes/configuration/cors/remove.ts @@ -10,14 +10,14 @@ import { ReplySchema } from "./get"; const BodySchema = Type.Object({ urlsToRemove: Type.Array( Type.String({ - description: "Comma separated list urls", + description: "Comma separated list of origins to remove", }), ), }); BodySchema.examples = [ { - urlsToRemove: ["https://example.com", "https://example2.com"], + urlsToRemove: ["https://example.com", "https://subdomain.example.com"], }, ]; diff --git a/src/server/routes/configuration/cors/set.ts b/src/server/routes/configuration/cors/set.ts new file mode 100644 index 000000000..a119e4ce8 --- /dev/null +++ b/src/server/routes/configuration/cors/set.ts @@ -0,0 +1,63 @@ +import { Static, Type } from "@sinclair/typebox"; +import { FastifyInstance } from "fastify"; +import { StatusCodes } from "http-status-codes"; +import { updateConfiguration } from "../../../../db/configuration/updateConfiguration"; +import { getConfig } from "../../../../utils/cache/getConfig"; +import { standardResponseSchema } from "../../../schemas/sharedApiSchemas"; +import { mandatoryAllowedCorsUrls } from "../../../utils/cors-urls"; +import { ReplySchema } from "./get"; + +const BodySchema = Type.Object({ + urls: Type.Array( + Type.String({ + description: "Comma separated list of origins that will call Engine", + minLength: 1, + }), + ), +}); + +BodySchema.examples = [ + { + urls: ["https://example.com", "https://subdomain.example.com"], + }, +]; + +export async function setUrlsToCorsConfiguration(fastify: FastifyInstance) { + fastify.route<{ + Body: Static; + Reply: Static; + }>({ + method: "PUT", + url: "/configuration/cors", + schema: { + summary: "Set CORS URLs", + description: + "Replaces the CORS URLs to allow client-side calls to Engine", + tags: ["Configuration"], + operationId: "setUrlsToCorsConfiguration", + body: BodySchema, + response: { + ...standardResponseSchema, + [StatusCodes.OK]: ReplySchema, + }, + }, + handler: async (req, res) => { + const urls = req.body.urls.map((url) => url.trim()); + + // Add required domains and dedupe. + const dedupe = Array.from( + new Set([...urls, ...mandatoryAllowedCorsUrls]), + ); + + await updateConfiguration({ + accessControlAllowOrigin: dedupe.join(","), + }); + + // Fetch and return the updated configuration + const config = await getConfig(false); + res.status(200).send({ + result: config.accessControlAllowOrigin.split(","), + }); + }, + }); +} diff --git a/src/server/routes/index.ts b/src/server/routes/index.ts index d0273aa94..c76bf2324 100644 --- a/src/server/routes/index.ts +++ b/src/server/routes/index.ts @@ -116,6 +116,7 @@ import { sendSignedUserOp } from "./transaction/blockchain/sendSignedUserOp"; import { checkGroupStatus } from "./transaction/group"; // Indexer +import { setUrlsToCorsConfiguration } from "./configuration/cors/set"; import { getContractEventLogs } from "./contract/events/getContractEventLogs"; import { getEventLogs } from "./contract/events/getEventLogsByTimestamp"; import { pageEventLogs } from "./contract/events/paginateEventLogs"; @@ -162,6 +163,7 @@ export const withRoutes = async (fastify: FastifyInstance) => { await fastify.register(getCorsConfiguration); await fastify.register(addUrlToCorsConfiguration); await fastify.register(removeUrlToCorsConfiguration); + await fastify.register(setUrlsToCorsConfiguration); await fastify.register(getCacheConfiguration); await fastify.register(updateCacheConfiguration);