Files
oneuptime/App/FeatureSet/Frontend/Index.ts
Nawaz Dhandala d9c7259356 Refactor code for improved readability and consistency
- Simplified arrow function syntax in MasterPassword.tsx and DashboardAPI.ts
- Consolidated logger.debug statements in PublicDashboard.ts and DashboardDomainAPI.ts
- Reformatted multi-line statements for better clarity in various files
- Updated migration files for consistent naming conventions and formatting
- Enhanced code structure in DashboardDomainService.ts and MonitorTelemetryMonitor.ts
- Incremented version number to 10.0.40
2026-03-26 16:41:11 +00:00

553 lines
14 KiB
TypeScript

import UserMiddleware from "Common/Server/Middleware/UserAuthorization";
import {
IsBillingEnabled,
getFrontendEnvVars,
} from "Common/Server/EnvironmentConfig";
import Express, {
ExpressApplication,
ExpressRequest,
ExpressResponse,
ExpressStatic,
NextFunction,
RequestHandler,
} from "Common/Server/Utils/Express";
import JSONWebToken from "Common/Server/Utils/JsonWebToken";
import JSONWebTokenData from "Common/Types/JsonWebTokenData";
import logger from "Common/Server/Utils/Logger";
import Response from "Common/Server/Utils/Response";
import NotAuthorizedException from "Common/Types/Exception/NotAuthorizedException";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import { JSONObject } from "Common/Types/JSON";
import ObjectID from "Common/Types/ObjectID";
import {
handleRSS,
StatusPageData,
getStatusPageData,
} from "./Utils/StatusPage";
import DashboardDomainService from "Common/Server/Services/DashboardDomainService";
import DashboardDomain from "Common/Models/DatabaseModels/DashboardDomain";
const app: ExpressApplication = Express.getExpressApp();
const AccountsPublicPath: string = "/usr/src/app/FeatureSet/Accounts/public";
const AccountsViewPath: string =
"/usr/src/app/FeatureSet/Accounts/views/index.ejs";
const DashboardPublicPath: string = "/usr/src/app/FeatureSet/Dashboard/public";
const DashboardViewPath: string =
"/usr/src/app/FeatureSet/Dashboard/views/index.ejs";
const AdminPublicPath: string = "/usr/src/app/FeatureSet/AdminDashboard/public";
const AdminViewPath: string =
"/usr/src/app/FeatureSet/AdminDashboard/views/index.ejs";
const StatusPagePublicPath: string =
"/usr/src/app/FeatureSet/StatusPage/public";
const StatusPageViewPath: string =
"/usr/src/app/FeatureSet/StatusPage/views/index.ejs";
const PublicDashboardPublicPath: string =
"/usr/src/app/FeatureSet/PublicDashboard/public";
const PublicDashboardViewPath: string =
"/usr/src/app/FeatureSet/PublicDashboard/views/index.ejs";
interface FrontendConfig {
routePrefix: string;
publicPath: string;
indexViewPath: string;
primaryHostOnly?: boolean;
getVariablesToRenderIndexPage?: (
req: ExpressRequest,
res: ExpressResponse,
) => Promise<JSONObject>;
}
interface RenderFrontendOptions {
req: ExpressRequest;
res: ExpressResponse;
next: NextFunction;
frontendConfig: FrontendConfig;
}
const DashboardFallbackRoutePrefixesToSkip: Array<string> = [
"/status-page",
"/status-page-api",
"/status-page-sso-api",
"/status-page-identity-api",
"/public-dashboard",
"/public-dashboard-api",
"/api",
"/identity",
"/notification",
"/telemetry",
"/incoming-request-ingest",
"/otlp",
"/opentelemetry.proto.collector",
"/probe-ingest",
"/ingestor",
"/server-monitor",
"/realtime",
"/workflow",
"/workers",
"/mcp",
"/analytics-api",
"/heartbeat",
"/incoming-email",
"/file",
"/docs",
"/reference",
"/worker",
"/.well-known",
"/l",
"/manifest.json",
"/service-worker.js",
"/sw.js",
"/browserconfig.xml",
"/rss",
];
const StatusPageDomainFallbackRoutePrefixesToSkip: Array<string> = [
"/status-page-api",
"/status-page-sso-api",
"/status-page-identity-api",
"/public-dashboard-api",
"/.well-known",
"/rss",
];
const StatusPageFrontendConfig: FrontendConfig = {
routePrefix: "/status-page",
publicPath: StatusPagePublicPath,
indexViewPath: StatusPageViewPath,
getVariablesToRenderIndexPage: async (
req: ExpressRequest,
_res: ExpressResponse,
): Promise<JSONObject> => {
const statusPageData: StatusPageData | null = await getStatusPageData(req);
if (statusPageData) {
return {
title: statusPageData.title,
description: statusPageData.description,
faviconUrl: statusPageData.faviconUrl,
};
}
return {
title: "Status Page",
description:
"Status Page lets you see real-time information about the status of our services.",
faviconUrl:
"/status-page-api/favicon/" + ObjectID.getZeroObjectID().toString(),
};
},
};
const DashboardFrontendConfig: FrontendConfig = {
routePrefix: "/dashboard",
publicPath: DashboardPublicPath,
indexViewPath: DashboardViewPath,
primaryHostOnly: true,
};
const PublicDashboardFrontendConfig: FrontendConfig = {
routePrefix: "/public-dashboard",
publicPath: PublicDashboardPublicPath,
indexViewPath: PublicDashboardViewPath,
};
const DashboardRootPwaFileMap: Array<{ route: string; file: string }> = [
{ route: "/manifest.json", file: "manifest.json" },
{ route: "/sw.js", file: "sw.js" },
{ route: "/service-worker.js", file: "sw.js" },
{ route: "/browserconfig.xml", file: "browserconfig.xml" },
];
const normalizeHostname: (host: string) => string = (host: string): string => {
const hostParts: Array<string> = host.split(":");
const hostPart: string | undefined = hostParts[0];
if (!hostPart) {
return "";
}
return hostPart.trim().toLowerCase();
};
const getPrimaryHosts: () => Set<string> = (): Set<string> => {
const hostSet: Set<string> = new Set<string>();
const hostCandidates: Array<string> = [
process.env["HOST"] || "",
"localhost",
"ingress",
];
for (const hostCandidate of hostCandidates) {
const normalizedHost: string = normalizeHostname(hostCandidate);
if (normalizedHost) {
hostSet.add(normalizedHost);
}
}
return hostSet;
};
const PrimaryHosts: Set<string> = getPrimaryHosts();
const getRequestHostname: (req: ExpressRequest) => string = (
req: ExpressRequest,
): string => {
if (req.hostname) {
return normalizeHostname(req.hostname.toString());
}
const hostHeader: string | Array<string> | undefined = req.headers["host"];
if (typeof hostHeader === "string") {
return normalizeHostname(hostHeader);
}
if (Array.isArray(hostHeader)) {
const firstHostHeader: string | undefined = hostHeader[0];
if (!firstHostHeader) {
return "";
}
return normalizeHostname(firstHostHeader);
}
return "";
};
const isPrimaryHostRequest: (req: ExpressRequest) => boolean = (
req: ExpressRequest,
): boolean => {
const requestHost: string = getRequestHostname(req);
if (!requestHost) {
return true;
}
return PrimaryHosts.has(requestHost);
};
const shouldSkipDashboardFallbackRoute: (path: string) => boolean = (
path: string,
): boolean => {
return DashboardFallbackRoutePrefixesToSkip.some((prefix: string) => {
if (path === prefix) {
return true;
}
return path.startsWith(`${prefix}/`);
});
};
const shouldSkipStatusPageDomainFallbackRoute: (path: string) => boolean = (
path: string,
): boolean => {
return StatusPageDomainFallbackRoutePrefixesToSkip.some((prefix: string) => {
if (path === prefix) {
return true;
}
return path.startsWith(`${prefix}/`);
});
};
const sendFrontendEnvScript: (
req: ExpressRequest,
res: ExpressResponse,
next: NextFunction,
) => Promise<void> = async (
req: ExpressRequest,
res: ExpressResponse,
next: NextFunction,
): Promise<void> => {
try {
const env: JSONObject = getFrontendEnvVars();
const script: string = `
if(!window.process){
window.process = {}
}
if(!window.process.env){
window.process.env = {}
}
window.process.env = ${JSON.stringify(env)};
`;
Response.sendJavaScriptResponse(req, res, script);
} catch (err) {
next(err);
}
};
const renderFrontendIndexPage: (
options: RenderFrontendOptions,
) => Promise<void> = async (options: RenderFrontendOptions): Promise<void> => {
const { req, res, next, frontendConfig } = options;
try {
let variables: JSONObject = {};
if (frontendConfig.getVariablesToRenderIndexPage) {
try {
const variablesToRenderIndexPage: JSONObject =
await frontendConfig.getVariablesToRenderIndexPage(req, res);
variables = {
...variables,
...variablesToRenderIndexPage,
};
} catch (err) {
logger.error(err);
}
}
if (res.headersSent) {
return;
}
res.render(frontendConfig.indexViewPath, {
enableGoogleTagManager: IsBillingEnabled || false,
...variables,
});
} catch (err) {
next(err);
}
};
const ensureMasterAdminAccess: (
req: ExpressRequest,
res: ExpressResponse,
) => Promise<JSONObject> = async (
req: ExpressRequest,
res: ExpressResponse,
): Promise<JSONObject> => {
try {
const accessToken: string | undefined =
UserMiddleware.getAccessTokenFromExpressRequest(req);
if (!accessToken) {
Response.sendErrorResponse(
req,
res,
new NotAuthorizedException(
"Unauthorized: Only master admins can access the admin dashboard.",
),
);
return {};
}
const authData: JSONWebTokenData = JSONWebToken.decode(accessToken);
if (!authData.isMasterAdmin) {
Response.sendErrorResponse(
req,
res,
new NotAuthorizedException(
"Unauthorized: Only master admins can access the admin dashboard.",
),
);
return {};
}
return {};
} catch (error) {
logger.error(error);
Response.sendErrorResponse(
req,
res,
new NotAuthorizedException(
"Unauthorized: Only master admins can access the admin dashboard.",
),
);
return {};
}
};
const registerFrontendApp: (frontendConfig: FrontendConfig) => void = (
frontendConfig: FrontendConfig,
): void => {
const staticHandler: RequestHandler = ExpressStatic(
frontendConfig.publicPath,
) as RequestHandler;
app.use(
frontendConfig.routePrefix,
(req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
if (frontendConfig.primaryHostOnly && !isPrimaryHostRequest(req)) {
return next();
}
return staticHandler(req, res, next);
},
);
app.get(
`${frontendConfig.routePrefix}/env.js`,
(req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
if (frontendConfig.primaryHostOnly && !isPrimaryHostRequest(req)) {
return next();
}
return sendFrontendEnvScript(req, res, next);
},
);
app.get(
[frontendConfig.routePrefix, `${frontendConfig.routePrefix}/*`],
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
if (frontendConfig.primaryHostOnly && !isPrimaryHostRequest(req)) {
return next();
}
return renderFrontendIndexPage({
req,
res,
next,
frontendConfig,
});
},
);
};
const isDashboardDomain: (hostname: string) => Promise<boolean> = async (
hostname: string,
): Promise<boolean> => {
try {
const dashboardDomain: DashboardDomain | null =
await DashboardDomainService.findOneBy({
query: {
fullDomain: hostname,
},
select: {
_id: true,
},
props: {
isRoot: true,
},
});
return dashboardDomain !== null;
} catch (err) {
logger.error("Error checking if domain is a dashboard domain:");
logger.error(err);
return false;
}
};
const registerCustomDomainFallback: () => void = (): void => {
app.get(
"*",
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
if (isPrimaryHostRequest(req)) {
return next();
}
if (shouldSkipStatusPageDomainFallbackRoute(req.path)) {
return next();
}
/*
* Check if this custom domain belongs to a PublicDashboard.
* If so, serve the PublicDashboard SPA instead of StatusPage.
*/
const requestHostname: string = getRequestHostname(req);
if (requestHostname && (await isDashboardDomain(requestHostname))) {
return renderFrontendIndexPage({
req,
res,
next,
frontendConfig: PublicDashboardFrontendConfig,
});
}
// Default: serve StatusPage for custom domains
return renderFrontendIndexPage({
req,
res,
next,
frontendConfig: StatusPageFrontendConfig,
});
},
);
};
const registerDashboardFallbackForPrimaryHost: () => void = (): void => {
app.get(
"*",
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
if (IsBillingEnabled) {
return next();
}
if (!isPrimaryHostRequest(req)) {
return next();
}
if (shouldSkipDashboardFallbackRoute(req.path)) {
return next();
}
return renderFrontendIndexPage({
req,
res,
next,
frontendConfig: DashboardFrontendConfig,
});
},
);
};
const registerDashboardRootPwaFiles: () => void = (): void => {
for (const pwaFileRoute of DashboardRootPwaFileMap) {
app.get(
pwaFileRoute.route,
(req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
if (IsBillingEnabled || !isPrimaryHostRequest(req)) {
return next();
}
return res.sendFile(`${DashboardPublicPath}/${pwaFileRoute.file}`);
},
);
}
};
const init: PromiseVoidFunction = async (): Promise<void> => {
app.get("/rss", handleRSS);
app.get("/status-page/:statusPageId/rss", handleRSS);
registerFrontendApp({
routePrefix: "/accounts",
publicPath: AccountsPublicPath,
indexViewPath: AccountsViewPath,
primaryHostOnly: true,
});
registerFrontendApp(DashboardFrontendConfig);
registerFrontendApp({
routePrefix: "/admin",
publicPath: AdminPublicPath,
indexViewPath: AdminViewPath,
primaryHostOnly: true,
getVariablesToRenderIndexPage: ensureMasterAdminAccess,
});
registerFrontendApp(StatusPageFrontendConfig);
registerFrontendApp(PublicDashboardFrontendConfig);
registerDashboardRootPwaFiles();
registerCustomDomainFallback();
registerDashboardFallbackForPrimaryHost();
};
export default {
init,
};