mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-29 14:45:24 +00:00
257 lines
7.6 KiB
TypeScript
257 lines
7.6 KiB
TypeScript
import type { Express, RequestHandler } from "express";
|
|
import { statsLogger } from "../../../src/backend/utils/logger.js";
|
|
import { createCurrentSettingsRepository } from "../../../src/backend/database/repositories/factory.js";
|
|
|
|
type HostMetricsSettingsConfig = {
|
|
statusCheckInterval: number;
|
|
metricsInterval: number;
|
|
};
|
|
|
|
type HostMetricsSettingsRoutesDeps = {
|
|
requireAdmin: RequestHandler;
|
|
defaultStatsConfig: HostMetricsSettingsConfig;
|
|
refreshAllPolling: () => Promise<void>;
|
|
};
|
|
|
|
function isMissingSettingsTable(error: unknown): boolean {
|
|
return (
|
|
error instanceof Error && error.message.includes("no such table: settings")
|
|
);
|
|
}
|
|
|
|
export function registerHostMetricsSettingsRoutes(
|
|
app: Express,
|
|
{
|
|
requireAdmin,
|
|
defaultStatsConfig: DEFAULT_STATS_CONFIG,
|
|
refreshAllPolling,
|
|
}: HostMetricsSettingsRoutesDeps,
|
|
): void {
|
|
/**
|
|
* @openapi
|
|
* /global-settings:
|
|
* get:
|
|
* summary: Get global monitoring defaults
|
|
* tags:
|
|
* - Host Metrics
|
|
* responses:
|
|
* 200:
|
|
* description: Global monitoring settings.
|
|
* 403:
|
|
* description: Requires admin privileges.
|
|
*/
|
|
app.get("/global-settings", requireAdmin, async (_req, res) => {
|
|
try {
|
|
const settings = createCurrentSettingsRepository();
|
|
const statusValue = await settings.get("global_status_check_interval");
|
|
const metricsValue = await settings.get("global_metrics_interval");
|
|
|
|
res.json({
|
|
statusCheckInterval: statusValue
|
|
? parseInt(statusValue, 10)
|
|
: DEFAULT_STATS_CONFIG.statusCheckInterval,
|
|
metricsInterval: metricsValue
|
|
? parseInt(metricsValue, 10)
|
|
: DEFAULT_STATS_CONFIG.metricsInterval,
|
|
});
|
|
} catch (error) {
|
|
if (isMissingSettingsTable(error)) {
|
|
statsLogger.warn("Settings table does not exist, using defaults", {
|
|
operation: "global_settings_table_check",
|
|
error: error.message,
|
|
});
|
|
return res.json({
|
|
statusCheckInterval: DEFAULT_STATS_CONFIG.statusCheckInterval,
|
|
metricsInterval: DEFAULT_STATS_CONFIG.metricsInterval,
|
|
});
|
|
}
|
|
|
|
statsLogger.error("Failed to fetch global settings", {
|
|
operation: "global_settings_fetch_error",
|
|
error: error instanceof Error ? error.message : String(error),
|
|
});
|
|
res.status(500).json({ error: "Failed to fetch global settings" });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @openapi
|
|
* /global-settings:
|
|
* post:
|
|
* summary: Update global monitoring defaults
|
|
* tags:
|
|
* - Host Metrics
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* statusCheckInterval:
|
|
* type: integer
|
|
* metricsInterval:
|
|
* type: integer
|
|
* responses:
|
|
* 200:
|
|
* description: Settings saved.
|
|
* 400:
|
|
* description: Invalid parameters.
|
|
* 403:
|
|
* description: Requires admin privileges.
|
|
*/
|
|
app.post("/global-settings", requireAdmin, async (req, res) => {
|
|
const { statusCheckInterval, metricsInterval } = req.body;
|
|
|
|
if (
|
|
statusCheckInterval !== undefined &&
|
|
(typeof statusCheckInterval !== "number" ||
|
|
statusCheckInterval < 5 ||
|
|
statusCheckInterval > 3600)
|
|
) {
|
|
return res.status(400).json({
|
|
error: "statusCheckInterval must be between 5 and 3600 seconds",
|
|
});
|
|
}
|
|
if (
|
|
metricsInterval !== undefined &&
|
|
(typeof metricsInterval !== "number" ||
|
|
metricsInterval < 5 ||
|
|
metricsInterval > 3600)
|
|
) {
|
|
return res
|
|
.status(400)
|
|
.json({ error: "metricsInterval must be between 5 and 3600 seconds" });
|
|
}
|
|
|
|
try {
|
|
const settings = createCurrentSettingsRepository();
|
|
|
|
if (statusCheckInterval !== undefined) {
|
|
await settings.set(
|
|
"global_status_check_interval",
|
|
String(statusCheckInterval),
|
|
);
|
|
}
|
|
if (metricsInterval !== undefined) {
|
|
await settings.set("global_metrics_interval", String(metricsInterval));
|
|
}
|
|
|
|
await refreshAllPolling();
|
|
|
|
res.json({
|
|
success: true,
|
|
message: "Settings updated and polling refreshed",
|
|
});
|
|
} catch (error) {
|
|
if (isMissingSettingsTable(error)) {
|
|
statsLogger.error(
|
|
"Settings table does not exist, cannot save settings",
|
|
{
|
|
operation: "global_settings_table_check",
|
|
error: error.message,
|
|
},
|
|
);
|
|
return res.status(500).json({
|
|
error:
|
|
"Database settings table is missing. Please check database initialization.",
|
|
});
|
|
}
|
|
|
|
statsLogger.error("Failed to save global settings", {
|
|
operation: "global_settings_save_error",
|
|
error: error instanceof Error ? error.message : String(error),
|
|
});
|
|
res.status(500).json({
|
|
error: "Failed to save global settings",
|
|
details: error instanceof Error ? error.message : String(error),
|
|
});
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @openapi
|
|
* /global-settings/history:
|
|
* get:
|
|
* summary: Get metrics history retention setting
|
|
* tags:
|
|
* - Host Metrics
|
|
* responses:
|
|
* 200:
|
|
* description: Retention setting in days.
|
|
* 403:
|
|
* description: Requires admin privileges.
|
|
*/
|
|
app.get("/global-settings/history", requireAdmin, async (_req, res) => {
|
|
try {
|
|
const value = await createCurrentSettingsRepository().get(
|
|
"metrics_history_retention_days",
|
|
);
|
|
const days = value ? parseInt(value, 10) : 7;
|
|
res.json({ metricsHistoryRetentionDays: isNaN(days) ? 7 : days });
|
|
} catch (error) {
|
|
statsLogger.error("Failed to fetch history retention setting", {
|
|
operation: "history_retention_fetch_error",
|
|
error: error instanceof Error ? error.message : String(error),
|
|
});
|
|
res
|
|
.status(500)
|
|
.json({ error: "Failed to fetch history retention setting" });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @openapi
|
|
* /global-settings/history:
|
|
* post:
|
|
* summary: Update metrics history retention setting
|
|
* tags:
|
|
* - Host Metrics
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* metricsHistoryRetentionDays:
|
|
* type: integer
|
|
* minimum: 1
|
|
* maximum: 90
|
|
* responses:
|
|
* 200:
|
|
* description: Setting saved.
|
|
* 400:
|
|
* description: Invalid value.
|
|
* 403:
|
|
* description: Requires admin privileges.
|
|
*/
|
|
app.post("/global-settings/history", requireAdmin, async (req, res) => {
|
|
const { metricsHistoryRetentionDays } = req.body;
|
|
if (
|
|
typeof metricsHistoryRetentionDays !== "number" ||
|
|
metricsHistoryRetentionDays < 1 ||
|
|
metricsHistoryRetentionDays > 90
|
|
) {
|
|
return res.status(400).json({
|
|
error: "metricsHistoryRetentionDays must be between 1 and 90",
|
|
});
|
|
}
|
|
try {
|
|
await createCurrentSettingsRepository().set(
|
|
"metrics_history_retention_days",
|
|
String(Math.floor(metricsHistoryRetentionDays)),
|
|
);
|
|
res.json({ success: true });
|
|
} catch (error) {
|
|
statsLogger.error("Failed to save history retention setting", {
|
|
operation: "history_retention_save_error",
|
|
error: error instanceof Error ? error.message : String(error),
|
|
});
|
|
res
|
|
.status(500)
|
|
.json({ error: "Failed to save history retention setting" });
|
|
}
|
|
});
|
|
}
|