import { HttpApiBuilder, HttpServerRequest, HttpServerResponse, } from "@effect/platform"; import type { ScopeId as WorkspaceId } from "@executor/platform-sdk/schema"; import * as Cause from "effect/Cause"; import * as Either from "effect/Either"; import * as Effect from "effect/Effect"; import * as Schema from "effect/Schema"; import { ExecutorApi } from "../api"; import { ControlPlaneBadRequestError, ControlPlaneStorageError, } from "../errors"; import { getControlPlaneExecutor, resolveRequestedLocalWorkspace, } from "../local-context"; import { SourceOAuthPopupResultSchema, type SourceOAuthPopupResult, } from "./api"; const OAUTH_RESULT_STORAGE_KEY_PREFIX = "executor:oauth-result:"; const escapeHtml = (value: string): string => value .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); const serializeValueForScript = (value: unknown): string => JSON.stringify(value) .replaceAll("<", "\\u003c") .replaceAll(">", "\\u003e") .replaceAll("&", "\\u0026"); const encodeSourceOAuthPopupResultJson = Schema.encodeSync( Schema.parseJson(SourceOAuthPopupResultSchema), ); const serializeJsonLiteralForScript = (value: string): string => value .replaceAll("<", "\\u003c") .replaceAll(">", "\\u003e") .replaceAll("&", "\\u0026"); const htmlResponse = (html: string, status = 200) => HttpServerResponse.html(html).pipe( HttpServerResponse.setStatus(status), ); const readHeader = (headers: unknown, name: string): string | null => { if (headers instanceof Headers) { return headers.get(name); } if (headers && typeof headers === "object") { const record = headers as Record; const direct = record[name]; if (typeof direct === "string" && direct.length > 0) { return direct; } const lower = record[name.toLowerCase()]; if (typeof lower === "string" && lower.length > 0) { return lower; } } return null; }; const resolveRequestOrigin = (request: { url: string; headers: unknown }): string | null => { try { return new URL(request.url).origin; } catch { const forwardedHost = readHeader(request.headers, "x-forwarded-host"); const host = forwardedHost ?? readHeader(request.headers, "host"); if (!host) { return null; } const forwardedProto = readHeader(request.headers, "x-forwarded-proto"); const protocol = forwardedProto && forwardedProto.length > 0 ? forwardedProto : "http"; return `${protocol}://${host}`; } }; const toStartSourceOAuthError = (input: { workspaceId: WorkspaceId; provider: string; endpoint: string; cause: Cause.Cause; }) => { const pretty = Cause.pretty(input.cause); console.error("oauth.start_source_auth failed", { workspaceId: input.workspaceId, provider: input.provider, endpoint: input.endpoint, pretty, }); if (pretty.includes("Invalid URL") || pretty.includes("required")) { return new ControlPlaneBadRequestError({ operation: "oauth.start_source_auth", message: pretty, details: pretty, }); } return new ControlPlaneStorageError({ operation: "oauth.start_source_auth", message: pretty, details: pretty, }); }; const sourceOAuthPopupResultDocument = (input: { title: string; message: string; status: "connected" | "failed"; sessionId: string; payload: SourceOAuthPopupResult; }) => ` ${escapeHtml(input.title)}
${escapeHtml(input.status)}

${escapeHtml(input.title)}

${escapeHtml(input.message)}

`; export const ExecutorOAuthLive = HttpApiBuilder.group( ExecutorApi, "oauth", (handlers) => handlers .handle("startSourceAuth", ({ path, payload }) => resolveRequestedLocalWorkspace("oauth.start_source_auth", path.workspaceId).pipe( Effect.flatMap((executor) => Effect.gen(function* () { const request = yield* HttpServerRequest.HttpServerRequest; return yield* executor.oauth.startSourceAuth({ baseUrl: resolveRequestOrigin(request), displayName: payload.name, provider: { kind: payload.provider, endpoint: payload.endpoint, transport: payload.transport, queryParams: payload.queryParams, headers: payload.headers, }, }); }).pipe( Effect.catchAllCause((cause) => Effect.fail( toStartSourceOAuthError({ workspaceId: path.workspaceId, provider: payload.provider, endpoint: payload.endpoint, cause, }), ), ), ) ), ), ) .handle("sourceAuthCallback", ({ urlParams }) => Effect.flatMap(getControlPlaneExecutor(), (executor) => Effect.gen(function* () { const completed = yield* Effect.either( executor.oauth.completeSourceAuth({ state: urlParams.state, code: urlParams.code, error: urlParams.error, errorDescription: urlParams.error_description, }), ); if (Either.isRight(completed)) { return htmlResponse( sourceOAuthPopupResultDocument({ title: "OAuth connected", message: "OAuth credentials are ready. Return to the source form to finish saving.", status: "connected", sessionId: completed.right.sessionId, payload: { type: "executor:oauth-result", ok: true, sessionId: completed.right.sessionId, auth: completed.right.auth, }, }), ); } const message = completed.left instanceof Error ? completed.left.message : "Failed completing OAuth"; return htmlResponse( sourceOAuthPopupResultDocument({ title: "OAuth failed", message, status: "failed", sessionId: "failed", payload: { type: "executor:oauth-result", ok: false, sessionId: null, error: message, }, }), 500, ); }), ), ), );