openpanel/packages/devtools-server/src/serve-proxy.ts
Stefan Pejcic 09f9f9502d packages
2024-11-07 19:03:37 +01:00

152 lines
3.8 KiB
TypeScript

import path from "path";
import { readJSON, writeJSON } from "fs-extra";
import { createProxyMiddleware, fixRequestBody } from "http-proxy-middleware";
import {
REFINE_API_URL,
AUTH_SERVER_URL,
AUTH_CALLBACK_API_PATH,
AUTH_CALLBACK_UI_PATH,
AUTH_TRIGGER_API_PATH,
} from "./constants";
import { getProjectIdFromPackageJson } from "./project-id/get-project-id-from-package-json";
import type { Express, RequestHandler } from "express";
const persistPath = path.join(__dirname, "..", ".persist.json");
const saveAuth = async (token?: string, jwt?: string) => {
try {
await writeJSON(persistPath, { token, jwt });
} catch (error) {
//
}
};
const loadAuth = async () => {
try {
return (await readJSON(persistPath)) as { token?: string; jwt?: string };
} catch (error) {
//
}
return {};
};
export const serveProxy = async (app: Express) => {
let { token, jwt } = await loadAuth();
const authProxy = createProxyMiddleware({
target: `${AUTH_SERVER_URL}/api/.auth`,
secure: false,
changeOrigin: true,
logger: __DEVELOPMENT__ ? console : undefined,
on: {
proxyReq: fixRequestBody,
proxyRes: (_proxyRes, req) => {
if (req.url?.includes("self-service/logout/api")) {
token = undefined;
jwt = undefined;
saveAuth();
}
},
},
});
const refineProxy = createProxyMiddleware({
target: `${REFINE_API_URL}/.refine`,
secure: false,
changeOrigin: true,
logger: __DEVELOPMENT__ ? console : undefined,
on: {
proxyReq: fixRequestBody,
},
});
let currentProjectId: string | null | false = null;
const projectIdAppender: RequestHandler = async (req, _res, next) => {
if (!currentProjectId) {
currentProjectId = await getProjectIdFromPackageJson();
}
if (currentProjectId) {
req.headers["x-project-id"] = currentProjectId;
}
next();
};
const appendAuth: RequestHandler = async (req, _res, next) => {
if (token) {
req.headers["X-Session-Token"] = token;
}
if (req.url?.includes("self-service/logout/api")) {
req.body = {
session_token: token,
};
req.headers["Content-Length"] = Buffer.byteLength(
JSON.stringify(req.body),
).toString();
}
next();
};
const appendJwt: RequestHandler = async (req, _res, next) => {
if (jwt) {
req.headers["Authorization"] = `Bearer ${jwt}`;
delete req.headers["cookie"];
}
next();
};
const loginCallback: RequestHandler = async (req, res, _next) => {
const query = req.query;
if (query.token && query.jwt) {
token = query.token as string;
jwt = query.jwt as string;
await saveAuth(query.token as string, query.jwt as string);
}
const errorParams = new URLSearchParams();
if (query.error) {
errorParams.set("error", query.error as string);
}
if (query.code) {
errorParams.set("code", query.code as string);
}
res.redirect(`${AUTH_CALLBACK_UI_PATH}?${errorParams.toString()}`);
};
const loginTrigger: RequestHandler = async (req, res, _next) => {
const query = req.query;
const protocol = req.secure ? "https" : "http";
const host = req.headers.host;
if (!host) {
res.redirect(`${AUTH_CALLBACK_API_PATH}?error=Missing%20Host`);
return;
}
const callbackUrl = `${protocol}://${host}${AUTH_CALLBACK_API_PATH}`;
const params = new URLSearchParams({
provider: query.provider as string,
returnUrl: encodeURIComponent(callbackUrl),
});
res.redirect(`${AUTH_SERVER_URL}/login?${params.toString()}`);
};
app.use(AUTH_TRIGGER_API_PATH, loginTrigger);
app.use(AUTH_CALLBACK_API_PATH, loginCallback);
app.use("/api/.auth", appendAuth, authProxy);
app.use("/api/.refine", projectIdAppender, appendJwt, refineProxy);
};