import { injectable } from "@codemation/core"; import type { AppConfig } from "../config/AppConfig"; import type { CodemationAuthConfig, CodemationAuthOAuthProviderConfig, CodemationAuthOidcProviderConfig, } from "../config/CodemationAuthConfig"; import type { CodemationFrontendAuthProviderSnapshot, CodemationFrontendAuthSnapshot, } from "./CodemationFrontendAuthSnapshot"; @injectable() export class CodemationFrontendAuthSnapshotFactory { createFromAppConfig(appConfig: AppConfig): CodemationFrontendAuthSnapshot { return this.createFromResolvedInputs({ authConfig: appConfig.auth, env: appConfig.env, uiAuthEnabled: this.resolveUiAuthEnabled(appConfig.auth, appConfig.env), }); } createFromResolvedInputs( args: Readonly<{ authConfig: CodemationAuthConfig | undefined; env: NodeJS.ProcessEnv; uiAuthEnabled: boolean; }>, ): CodemationFrontendAuthSnapshot { const snapshot = { config: args.authConfig, credentialsEnabled: args.authConfig?.kind === "local", oauthProviders: this.createOauthProviders(args.authConfig), secret: this.resolveAuthSecret(args.env), uiAuthEnabled: args.uiAuthEnabled, }; const cpWebOrigin = args.authConfig?.kind === "managed" ? args.env["CP_WEB_ORIGIN"]?.trim() || undefined : undefined; if (cpWebOrigin) { return { ...snapshot, cpWebOrigin }; } return snapshot; } private resolveUiAuthEnabled(authConfig: CodemationAuthConfig | undefined, env: NodeJS.ProcessEnv): boolean { const configuredOverride = env.CODEMATION_UI_AUTH_ENABLED?.trim().toLowerCase(); if (configuredOverride === "true") { return true; } if (configuredOverride === "false") { return false; } return !(env.NODE_ENV !== "production" && authConfig?.allowUnauthenticatedInDevelopment === true); } private resolveAuthSecret(env: NodeJS.ProcessEnv): string | null { const secret = env.AUTH_SECRET?.trim() || (env.NODE_ENV === "development" ? "codemation-dev-auth-secret-not-for-production" : undefined); return secret && secret.trim().length > 0 ? secret : null; } private createOauthProviders( authConfig: CodemationAuthConfig | undefined, ): ReadonlyArray { if (!authConfig) { return []; } const providers: CodemationFrontendAuthProviderSnapshot[] = []; for (const provider of authConfig.oauth ?? []) { providers.push(this.createOAuthProvider(provider)); } for (const provider of authConfig.oidc ?? []) { providers.push(this.createOidcProvider(provider)); } return providers; } private createOAuthProvider(provider: CodemationAuthOAuthProviderConfig): CodemationFrontendAuthProviderSnapshot { return { id: provider.provider, name: this.resolveOAuthProviderName(provider.provider), }; } private createOidcProvider(provider: CodemationAuthOidcProviderConfig): CodemationFrontendAuthProviderSnapshot { return { id: provider.id, name: provider.id, }; } private resolveOAuthProviderName(providerId: CodemationAuthOAuthProviderConfig["provider"]): string { if (providerId === "google") { return "Google"; } if (providerId === "github") { return "GitHub"; } return "Microsoft"; } }