Files
Checkmate/server/src/api/controllers/settingsController.ts
T

143 lines
4.7 KiB
TypeScript
Raw Normal View History

import { Request, Response, RequestHandler } from "express";
import { catchAsync } from "@/utils/catchAsync.js";
2026-06-09 12:34:15 -07:00
import { updateAppSettingsBodyValidation } from "@/api/validation/settingsValidation.js";
import { sendTestEmailBodyValidation } from "@/api/validation/notificationValidation.js";
2026-01-09 15:16:17 -08:00
import { AppError } from "@/utils/AppError.js";
2026-06-09 12:34:15 -07:00
import { ISettingsService } from "@/domain/app-settings/app-settings.service.js";
import { IEmailService } from "@/service/emailService.js";
import { IProxiesService } from "@/domain/proxies/proxy.service.js";
2026-06-09 12:34:15 -07:00
import { Settings } from "@/domain/app-settings/app-settings.type.js";
2026-03-20 11:42:40 -07:00
export interface ISettingsController {
getAppSettings: RequestHandler;
updateAppSettings: RequestHandler;
sendTestEmail: RequestHandler;
2026-03-20 11:42:40 -07:00
}
class SettingsController implements ISettingsController {
2026-03-12 09:13:35 -07:00
private settingsService: ISettingsService;
private emailService: IEmailService;
private proxiesService: IProxiesService;
constructor(settingsService: ISettingsService, emailService: IEmailService, proxiesService: IProxiesService) {
2025-04-20 11:29:53 -07:00
this.settingsService = settingsService;
2025-05-16 15:01:06 -07:00
this.emailService = emailService;
this.proxiesService = proxiesService;
2025-04-20 11:29:53 -07:00
}
buildAppSettings = async (dbSettings: Settings) => {
2026-03-20 12:40:27 -07:00
const sanitizedSettings: Record<string, unknown> = { ...dbSettings };
2025-05-13 13:51:11 -07:00
delete sanitizedSettings.version;
2026-01-21 13:01:31 -08:00
delete sanitizedSettings.jwtSecret;
const globalProxy =
dbSettings.globalProxyEnabled && dbSettings.globalProxyId ? await this.proxiesService.getProxySummary(dbSettings.globalProxyId) : null;
2026-03-20 12:40:27 -07:00
const returnSettings: Record<string, unknown | null> = {
2025-05-09 14:53:36 -07:00
pagespeedKeySet: false,
emailPasswordSet: false,
globalProxy,
2026-01-09 15:16:17 -08:00
settings: null,
2025-05-09 14:53:36 -07:00
};
if (typeof sanitizedSettings.pagespeedApiKey !== "undefined") {
2025-05-09 14:53:36 -07:00
returnSettings.pagespeedKeySet = true;
delete sanitizedSettings.pagespeedApiKey;
2025-04-20 11:29:53 -07:00
}
2025-05-09 14:53:36 -07:00
if (typeof sanitizedSettings.systemEmailPassword !== "undefined") {
returnSettings.emailPasswordSet = true;
delete sanitizedSettings.systemEmailPassword;
}
returnSettings.settings = sanitizedSettings;
2025-06-17 10:58:30 +08:00
return returnSettings;
};
getAppSettings = catchAsync(async (req: Request, res: Response) => {
const dbSettings = await this.settingsService.getDBSettings();
const returnSettings = await this.buildAppSettings(dbSettings);
return res.status(200).json({
success: true,
msg: "App settings fetched successfully",
data: returnSettings,
});
});
updateAppSettings = catchAsync(async (req: Request, res: Response) => {
const validatedBody = updateAppSettingsBodyValidation.parse(req.body);
if (validatedBody.globalProxyId) {
const proxy = await this.proxiesService.getProxySummary(validatedBody.globalProxyId);
if (!proxy) {
throw new AppError({ message: "Referenced proxy does not exist", status: 422 });
}
}
const updatedSettings = await this.settingsService.updateDbSettings(validatedBody);
const returnSettings = await this.buildAppSettings(updatedSettings);
return res.status(200).json({
success: true,
msg: "App settings updated successfully",
data: returnSettings,
});
});
sendTestEmail = catchAsync(async (req: Request, res: Response) => {
sendTestEmailBodyValidation.parse(req.body);
const {
to,
systemEmailHost,
systemEmailPort,
systemEmailAddress,
systemEmailDisplayName,
systemEmailPassword,
systemEmailUser,
systemEmailConnectionHost,
systemEmailSecure,
systemEmailPool,
systemEmailIgnoreTLS,
systemEmailRequireTLS,
systemEmailRejectUnauthorized,
systemEmailTLSServername,
} = req.body;
const subject = "This is a test email from Checkmate";
const context = { testName: "Monitoring System" };
const html = await this.emailService.buildEmail("testEmailTemplate", context);
if (!html) {
throw new AppError({ message: "Failed to build email template.", status: 500 });
2026-01-09 15:16:17 -08:00
}
let messageId: string;
try {
messageId = await this.emailService.sendEmail(to, subject, html, {
systemEmailHost,
systemEmailPort,
systemEmailUser,
systemEmailAddress,
systemEmailDisplayName,
systemEmailPassword,
systemEmailConnectionHost,
systemEmailSecure,
systemEmailPool,
systemEmailIgnoreTLS,
systemEmailRequireTLS,
systemEmailRejectUnauthorized,
systemEmailTLSServername,
});
} catch (error: unknown) {
// Surface the underlying SMTP failure: diagnosing the settings is the whole
// point of the test email endpoint.
throw new AppError({
message: error instanceof Error ? `Failed to send test email. ${error.message}` : "Failed to send test email.",
status: 500,
});
2026-03-02 18:46:21 +00:00
}
2026-01-09 15:16:17 -08:00
return res.status(200).json({
success: true,
msg: "Test email sent successfully",
data: { messageId },
});
});
2025-04-20 11:29:53 -07:00
}
export default SettingsController;