forked from EduCraft/curriculum-project-hub
4e2699d0a5
registerStaticSpa was never mounted, so production only exposed org-admin APIs. Wire it after auth/API routes, fold admin:build into npm run build, and install admin-web deps during deploy so admin-web/build ships with the release for same-origin /admin/*.
70 lines
2.6 KiB
TypeScript
70 lines
2.6 KiB
TypeScript
/**
|
|
* Registers org-admin HTTP surface: auth, org APIs, and the static SPA shell.
|
|
*/
|
|
import cookie from "@fastify/cookie";
|
|
import type { PrismaClient } from "@prisma/client";
|
|
import type { FastifyInstance } from "fastify";
|
|
import { registerAuthRoutes } from "./routes/authRoutes.js";
|
|
import { registerOrgRoutes } from "./routes/orgRoutes.js";
|
|
import { registerStaticSpa } from "./static.js";
|
|
import type { LocalSecretEnvelope } from "../security/secretEnvelope.js";
|
|
import type { ProviderReadinessProbe } from "../connections/providerReadiness.js";
|
|
import type { FeishuReadinessProbe } from "../connections/feishuReadiness.js";
|
|
|
|
export interface AdminPluginConfig {
|
|
readonly prisma: PrismaClient;
|
|
readonly sessionSecret: string;
|
|
readonly publicBaseUrl: string;
|
|
readonly feishuAppId: string;
|
|
readonly feishuAppSecret: string;
|
|
readonly projectWorkspaceRoot: string;
|
|
readonly secretEnvelope: LocalSecretEnvelope;
|
|
readonly providerReadinessProbe?: ProviderReadinessProbe;
|
|
readonly feishuConnectionReadinessProbe?: FeishuReadinessProbe;
|
|
readonly cookieSecure?: boolean;
|
|
readonly oauthScope?: string;
|
|
readonly fetchImpl?: typeof fetch;
|
|
readonly allowLegacyFeishuOAuth?: boolean;
|
|
}
|
|
|
|
export async function registerAdminPlugin(
|
|
app: FastifyInstance,
|
|
config: AdminPluginConfig,
|
|
): Promise<void> {
|
|
await app.register(cookie);
|
|
|
|
const cookieSecure =
|
|
config.cookieSecure ?? config.publicBaseUrl.startsWith("https://");
|
|
|
|
await registerAuthRoutes(app, {
|
|
prisma: config.prisma,
|
|
sessionSecret: config.sessionSecret,
|
|
publicBaseUrl: config.publicBaseUrl,
|
|
feishuAppId: config.feishuAppId,
|
|
feishuAppSecret: config.feishuAppSecret,
|
|
secretEnvelope: config.secretEnvelope,
|
|
cookieSecure,
|
|
...(config.oauthScope !== undefined ? { oauthScope: config.oauthScope } : {}),
|
|
...(config.fetchImpl !== undefined ? { fetchImpl: config.fetchImpl } : {}),
|
|
...(config.allowLegacyFeishuOAuth !== undefined
|
|
? { allowLegacyFeishuOAuth: config.allowLegacyFeishuOAuth }
|
|
: {}),
|
|
});
|
|
|
|
await registerOrgRoutes(app, {
|
|
prisma: config.prisma,
|
|
sessionSecret: config.sessionSecret,
|
|
projectWorkspaceRoot: config.projectWorkspaceRoot,
|
|
secretEnvelope: config.secretEnvelope,
|
|
...(config.providerReadinessProbe !== undefined
|
|
? { providerReadinessProbe: config.providerReadinessProbe }
|
|
: {}),
|
|
...(config.feishuConnectionReadinessProbe !== undefined
|
|
? { feishuConnectionReadinessProbe: config.feishuConnectionReadinessProbe }
|
|
: {}),
|
|
});
|
|
|
|
// After API + /admin/login so SPA fallback does not shadow auth routes.
|
|
await registerStaticSpa(app);
|
|
}
|