Merge pull request #2675 from bluewave-labs/feat/mw-service

feat: add maintenance window service
This commit is contained in:
Alexander Holliday
2025-07-23 15:15:25 -07:00
committed by GitHub
4 changed files with 95 additions and 56 deletions

View File

@@ -11,16 +11,10 @@ class InviteController {
/**
* Creates a new InviteController instance
* @param {Object} dependencies - Dependencies injected into the controller
* @param {Object} dependencies.db - Database connection instance
* @param {Object} dependencies.settingsService - Service for managing application settings
* @param {Object} dependencies.emailService - Service for sending emails
* @param {Object} dependencies.stringService - Service for internationalized strings
* @param {Object} dependencies.inviteService - Service for invite-related operations
*/
constructor({ db, settingsService, emailService, stringService, inviteService }) {
this.db = db;
this.settingsService = settingsService;
this.emailService = emailService;
constructor({ stringService, inviteService }) {
this.stringService = stringService;
this.inviteService = inviteService;
}

View File

@@ -12,14 +12,15 @@ import { asyncHandler } from "../utils/errorUtils.js";
const SERVICE_NAME = "maintenanceWindowController";
class MaintenanceWindowController {
constructor(db, settingsService, stringService) {
constructor({ db, settingsService, stringService, maintenanceWindowService }) {
this.db = db;
this.settingsService = settingsService;
this.stringService = stringService;
this.maintenanceWindowService = maintenanceWindowService;
}
createMaintenanceWindows = asyncHandler(
async (req, res, next) => {
async (req, res) => {
await createMaintenanceWindowBodyValidation.validateAsync(req.body);
const teamId = req?.user?.teamId;
@@ -27,32 +28,7 @@ class MaintenanceWindowController {
throw new Error("Team ID is required");
}
const monitorIds = req.body.monitors;
const monitors = await this.db.getMonitorsByIds(monitorIds);
const unauthorizedMonitors = monitors.filter((monitor) => !monitor.teamId.equals(teamId));
if (unauthorizedMonitors.length > 0) {
const error = new Error("Unauthorized access to one or more monitors");
error.status = 403;
error.service = SERVICE_NAME;
error.method = "createMaintenanceWindows";
throw error;
}
const dbTransactions = monitorIds.map((monitorId) => {
return this.db.createMaintenanceWindow({
teamId,
monitorId,
name: req.body.name,
active: req.body.active ? req.body.active : true,
repeat: req.body.repeat,
start: req.body.start,
end: req.body.end,
});
});
await Promise.all(dbTransactions);
await this.maintenanceWindowService.createMaintenanceWindow({ teamId, body: req.body });
return res.success({
msg: this.stringService.maintenanceWindowCreate,
@@ -63,7 +39,7 @@ class MaintenanceWindowController {
);
getMaintenanceWindowById = asyncHandler(
async (req, res, next) => {
async (req, res) => {
await getMaintenanceWindowByIdParamValidation.validateAsync(req.params);
const teamId = req.user.teamId;
@@ -71,7 +47,8 @@ class MaintenanceWindowController {
throw new Error("Team ID is required");
}
const maintenanceWindow = await this.db.getMaintenanceWindowById({ id: req.params.id, teamId });
const maintenanceWindow = await this.maintenanceWindowService.getMaintenanceWindowById({ id: req.params.id, teamId });
return res.success({
msg: this.stringService.maintenanceWindowGetById,
data: maintenanceWindow,
@@ -82,7 +59,7 @@ class MaintenanceWindowController {
);
getMaintenanceWindowsByTeamId = asyncHandler(
async (req, res, next) => {
async (req, res) => {
await getMaintenanceWindowsByTeamIdQueryValidation.validateAsync(req.query);
const teamId = req?.user?.teamId;
@@ -91,7 +68,7 @@ class MaintenanceWindowController {
throw new Error("Team ID is required");
}
const maintenanceWindows = await this.db.getMaintenanceWindowsByTeamId(teamId, req.query);
const maintenanceWindows = await this.maintenanceWindowService.getMaintenanceWindowsByTeamId({ teamId, query: req.query });
return res.success({
msg: this.stringService.maintenanceWindowGetByTeam,
@@ -103,17 +80,15 @@ class MaintenanceWindowController {
);
getMaintenanceWindowsByMonitorId = asyncHandler(
async (req, res, next) => {
async (req, res) => {
await getMaintenanceWindowsByMonitorIdParamValidation.validateAsync(req.params);
const monitorId = req.params.monitorId;
const teamId = req?.user?.teamId;
if (!teamId) {
throw new Error("Team ID is required");
}
const maintenanceWindows = await this.db.getMaintenanceWindowsByMonitorId({ monitorId, teamId });
const maintenanceWindows = await this.maintenanceWindowService.getMaintenanceWindowsByMonitorId({ monitorId: req.params.monitorId, teamId });
return res.success({
msg: this.stringService.maintenanceWindowGetByUser,
@@ -125,7 +100,7 @@ class MaintenanceWindowController {
);
deleteMaintenanceWindow = asyncHandler(
async (req, res, next) => {
async (req, res) => {
await deleteMaintenanceWindowByIdParamValidation.validateAsync(req.params);
const teamId = req?.user?.teamId;
@@ -133,7 +108,8 @@ class MaintenanceWindowController {
throw new Error("Team ID is required");
}
await this.db.deleteMaintenanceWindowById({ id: req.params.id, teamId });
await this.maintenanceWindowService.deleteMaintenanceWindow({ id: req.params.id, teamId });
return res.success({
msg: this.stringService.maintenanceWindowDelete,
});
@@ -143,7 +119,7 @@ class MaintenanceWindowController {
);
editMaintenanceWindow = asyncHandler(
async (req, res, next) => {
async (req, res) => {
await editMaintenanceWindowByIdParamValidation.validateAsync(req.params);
await editMaintenanceByIdWindowBodyValidation.validateAsync(req.body);
@@ -152,8 +128,7 @@ class MaintenanceWindowController {
throw new Error("Team ID is required");
}
const editedMaintenanceWindow = await this.db.editMaintenanceWindowById({ id: req.params.id, body: req.body, teamId });
const editedMaintenanceWindow = await this.maintenanceWindowService.editMaintenanceWindow({ id: req.params.id, body: req.body, teamId });
return res.success({
msg: this.stringService.maintenanceWindowEdit,
data: editedMaintenanceWindow,

View File

@@ -62,6 +62,7 @@ import UserService from "./service/business/userService.js";
import CheckService from "./service/business/checkService.js";
import DiagnosticService from "./service/business/diagnosticService.js";
import InviteService from "./service/business/inviteService.js";
import MaintenanceWindowService from "./service/business/maintenanceWindowService.js";
//Network service and dependencies
import NetworkService from "./service/infrastructure/networkService.js";
@@ -205,6 +206,11 @@ const startApp = async () => {
emailService,
stringService,
});
const maintenanceWindowService = new MaintenanceWindowService({
db,
settingsService,
stringService,
});
// const jobQueueHelper = new JobQueueHelper({
// redisService,
// Queue,
@@ -265,6 +271,8 @@ const startApp = async () => {
ServiceRegistry.register(RedisService.SERVICE_NAME, redisService);
ServiceRegistry.register(UserService.SERVICE_NAME, userService);
ServiceRegistry.register(CheckService.SERVICE_NAME, checkService);
ServiceRegistry.register(InviteService.SERVICE_NAME, inviteService);
ServiceRegistry.register(MaintenanceWindowService.SERVICE_NAME, maintenanceWindowService);
await translationService.initialize();
@@ -311,18 +319,16 @@ const startApp = async () => {
});
const inviteController = new InviteController({
db: ServiceRegistry.get(MongoDB.SERVICE_NAME),
settingsService: ServiceRegistry.get(SettingsService.SERVICE_NAME),
emailService: ServiceRegistry.get(EmailService.SERVICE_NAME),
stringService: ServiceRegistry.get(StringService.SERVICE_NAME),
inviteService,
});
const maintenanceWindowController = new MaintenanceWindowController(
ServiceRegistry.get(MongoDB.SERVICE_NAME),
ServiceRegistry.get(SettingsService.SERVICE_NAME),
ServiceRegistry.get(StringService.SERVICE_NAME)
);
const maintenanceWindowController = new MaintenanceWindowController({
db: ServiceRegistry.get(MongoDB.SERVICE_NAME),
settingsService: ServiceRegistry.get(SettingsService.SERVICE_NAME),
stringService: ServiceRegistry.get(StringService.SERVICE_NAME),
maintenanceWindowService: ServiceRegistry.get(MaintenanceWindowService.SERVICE_NAME),
});
const queueController = new QueueController(ServiceRegistry.get(JobQueue.SERVICE_NAME), ServiceRegistry.get(StringService.SERVICE_NAME));

View File

@@ -0,0 +1,64 @@
const SERVICE_NAME = "maintenanceWindowService";
class MaintenanceWindowService {
static SERVICE_NAME = SERVICE_NAME;
constructor({ db, settingsService, stringService }) {
this.db = db;
this.settingsService = settingsService;
this.stringService = stringService;
}
createMaintenanceWindow = async ({ teamId, body }) => {
const monitorIds = body.monitors;
const monitors = await this.db.getMonitorsByIds(monitorIds);
const unauthorizedMonitors = monitors.filter((monitor) => !monitor.teamId.equals(teamId));
if (unauthorizedMonitors.length > 0) {
const error = new Error("Unauthorized access to one or more monitors");
error.status = 403;
error.service = SERVICE_NAME;
error.method = "createMaintenanceWindows";
throw error;
}
const dbTransactions = monitorIds.map((monitorId) => {
return this.db.createMaintenanceWindow({
teamId,
monitorId,
name: body.name,
active: body.active ? body.active : true,
repeat: body.repeat,
start: body.start,
end: body.end,
});
});
await Promise.all(dbTransactions);
};
getMaintenanceWindowById = async ({ id, teamId }) => {
const maintenanceWindow = await this.db.getMaintenanceWindowById({ id, teamId });
return maintenanceWindow;
};
getMaintenanceWindowsByTeamId = async ({ teamId, query }) => {
const maintenanceWindows = await this.db.getMaintenanceWindowsByTeamId(teamId, query);
return maintenanceWindows;
};
getMaintenanceWindowsByMonitorId = async ({ monitorId, teamId }) => {
const maintenanceWindows = await this.db.getMaintenanceWindowsByMonitorId({ monitorId, teamId });
return maintenanceWindows;
};
deleteMaintenanceWindow = async ({ id, teamId }) => {
await this.db.deleteMaintenanceWindowById({ id, teamId });
};
editMaintenanceWindow = async ({ id, teamId, body }) => {
const editedMaintenanceWindow = await this.db.editMaintenanceWindowById({ id, body, teamId });
return editedMaintenanceWindow;
};
}
export default MaintenanceWindowService;