Merge branch 'develop' into fix/login-error-handling
This commit is contained in:
commit
9ad1e261a4
602 files changed
+15674
-10998
No files matched your search
+2
-1
@@ -8,4 +8,5 @@ coverage
|
||||
.clinic
|
||||
node_modules
|
||||
.vscode/*
|
||||
public
|
||||
public
|
||||
dist
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"ignore": ["src/locales/*", "*.log", "node_modules/*"],
|
||||
"watch": ["src/**/*.js", "*.json"],
|
||||
"ext": "js,json"
|
||||
"watch": ["src/**/*.ts", "src/**/*.js", "*.json"],
|
||||
"ext": "ts,js,json"
|
||||
}
|
||||
Generated
+2053
-1
File diff suppressed because it is too large.
Load diff
+10
-2
@@ -6,7 +6,9 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "c8 mocha",
|
||||
"dev": "nodemon src/index.js",
|
||||
"dev": "nodemon --exec tsx src/index.js",
|
||||
"start": "nodemon ./dist/index.js",
|
||||
"build": "tsc",
|
||||
"lint": "eslint .",
|
||||
"lint-fix": "eslint --fix .",
|
||||
"format": "prettier --write .",
|
||||
@@ -52,6 +54,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.17.0",
|
||||
"@types/express": "5.0.3",
|
||||
"@types/jsonwebtoken": "9.0.10",
|
||||
"@types/nodemailer": "7.0.1",
|
||||
"@types/ping": "0.4.4",
|
||||
"c8": "10.1.3",
|
||||
"chai": "5.2.0",
|
||||
"eslint": "^9.17.0",
|
||||
@@ -61,6 +67,8 @@
|
||||
"mocha": "11.1.0",
|
||||
"nodemon": "3.1.9",
|
||||
"prettier": "^3.3.3",
|
||||
"sinon": "19.0.2"
|
||||
"sinon": "19.0.2",
|
||||
"tsx": "4.20.5",
|
||||
"typescript": "5.9.2"
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -1,16 +1,16 @@
|
||||
import express from "express";
|
||||
import path from "path";
|
||||
import { responseHandler } from "./middleware/responseHandler.js";
|
||||
import { responseHandler } from "./middleware/v1/responseHandler.js";
|
||||
import cors from "cors";
|
||||
import helmet from "helmet";
|
||||
import compression from "compression";
|
||||
import cookieParser from "cookie-parser";
|
||||
import languageMiddleware from "./middleware/languageMiddleware.js";
|
||||
import languageMiddleware from "./middleware/v1/languageMiddleware.js";
|
||||
import swaggerUi from "swagger-ui-express";
|
||||
import { handleErrors } from "./middleware/handleErrors.js";
|
||||
import { handleErrors } from "./middleware/v1/handleErrors.js";
|
||||
import { setupRoutes } from "./config/routes.js";
|
||||
import { generalApiLimiter } from "./middleware/rateLimiter.js";
|
||||
import { sanitizeBody, sanitizeQuery } from "./middleware/sanitization.js";
|
||||
import { generalApiLimiter } from "./middleware/v1/rateLimiter.js";
|
||||
import { sanitizeBody, sanitizeQuery } from "./middleware/v1/sanitization.js";
|
||||
|
||||
export const createApp = ({ services, controllers, envSettings, frontendPath, openApiSpec }) => {
|
||||
const allowedOrigin = envSettings.clientHost;
|
||||
@@ -27,7 +27,7 @@ export const createApp = ({ services, controllers, envSettings, frontendPath, op
|
||||
cors({
|
||||
origin: allowedOrigin,
|
||||
methods: "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS",
|
||||
allowedHeaders: "*",
|
||||
allowedHeaders: ["Content-Type", "Authorization"],
|
||||
credentials: true,
|
||||
})
|
||||
);
|
||||
|
||||
@@ -1,24 +1,32 @@
|
||||
import { createCommonDependencies } from "../controllers/baseController.js";
|
||||
import { createCommonDependencies } from "../controllers/v1/baseController.js";
|
||||
|
||||
// Services
|
||||
|
||||
// Controllers
|
||||
import MonitorController from "../controllers/monitorController.js";
|
||||
import AuthController from "../controllers/authController.js";
|
||||
import SettingsController from "../controllers/settingsController.js";
|
||||
import CheckController from "../controllers/checkController.js";
|
||||
import InviteController from "../controllers/inviteController.js";
|
||||
import MaintenanceWindowController from "../controllers/maintenanceWindowController.js";
|
||||
import QueueController from "../controllers/queueController.js";
|
||||
import LogController from "../controllers/logController.js";
|
||||
import StatusPageController from "../controllers/statusPageController.js";
|
||||
import NotificationController from "../controllers/notificationController.js";
|
||||
import DiagnosticController from "../controllers/diagnosticController.js";
|
||||
// V1 Controllers
|
||||
import MonitorController from "../controllers/v1/monitorController.js";
|
||||
import AuthController from "../controllers/v1/authController.js";
|
||||
import SettingsController from "../controllers/v1/settingsController.js";
|
||||
import CheckController from "../controllers/v1/checkController.js";
|
||||
import InviteController from "../controllers/v1/inviteController.js";
|
||||
import MaintenanceWindowController from "../controllers/v1/maintenanceWindowController.js";
|
||||
import QueueController from "../controllers/v1/queueController.js";
|
||||
import LogController from "../controllers/v1/logController.js";
|
||||
import StatusPageController from "../controllers/v1/statusPageController.js";
|
||||
import NotificationController from "../controllers/v1/notificationController.js";
|
||||
import DiagnosticController from "../controllers/v1/diagnosticController.js";
|
||||
|
||||
// V2 Controllers
|
||||
import AuthControllerV2 from "../controllers/v2/AuthController.js";
|
||||
import InviteControllerV2 from "../controllers/v2/InviteController.js";
|
||||
import MaintenanceControllerV2 from "../controllers/v2/MaintenanceController.js";
|
||||
import MonitorControllerV2 from "../controllers/v2/MonitorController.js";
|
||||
import NotificationChannelControllerV2 from "../controllers/v2/NotificationChannelController.js";
|
||||
import QueueControllerV2 from "../controllers/v2/QueueController.js";
|
||||
export const initializeControllers = (services) => {
|
||||
const controllers = {};
|
||||
const commonDependencies = createCommonDependencies(services.db, services.errorService, services.logger, services.stringService);
|
||||
|
||||
// V1
|
||||
controllers.authController = new AuthController(commonDependencies, {
|
||||
settingsService: services.settingsService,
|
||||
emailService: services.emailService,
|
||||
@@ -62,5 +70,13 @@ export const initializeControllers = (services) => {
|
||||
diagnosticService: services.diagnosticService,
|
||||
});
|
||||
|
||||
//V2
|
||||
controllers.authControllerV2 = new AuthControllerV2(services.authServiceV2, services.inviteServiceV2);
|
||||
controllers.inviteControllerV2 = new InviteControllerV2(services.inviteServiceV2);
|
||||
controllers.maintenanceControllerV2 = new MaintenanceControllerV2(services.maintenanceServiceV2);
|
||||
controllers.monitorControllerV2 = new MonitorControllerV2(services.monitorServiceV2, services.checkServiceV2);
|
||||
controllers.notificationChannelControllerV2 = new NotificationChannelControllerV2(services.notificationChannelServiceV2);
|
||||
controllers.queueControllerV2 = new QueueControllerV2(services.jobQueueV2);
|
||||
|
||||
return controllers;
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
import dotenv from "dotenv";
|
||||
|
||||
export interface IEevConfig {
|
||||
NODE_ENV: string;
|
||||
JWT_SECRET: string;
|
||||
PORT: number;
|
||||
PAGESPEED_API_KEY: string;
|
||||
SMTP_HOST: string;
|
||||
SMTP_PORT: number;
|
||||
SMTP_USER: string;
|
||||
SMTP_PASS: string;
|
||||
}
|
||||
|
||||
dotenv.config();
|
||||
|
||||
export const config: IEevConfig = {
|
||||
NODE_ENV: process.env.NODE_ENV || "development",
|
||||
JWT_SECRET: process.env.JWT_SECRET || "your_jwt_secret",
|
||||
PORT: process.env.PORT ? parseInt(process.env.PORT, 10) : 3000,
|
||||
PAGESPEED_API_KEY: process.env.PAGESPEED_API_KEY || "",
|
||||
SMTP_HOST: process.env.SMTP_HOST || "smtp.example.com",
|
||||
SMTP_PORT: process.env.SMTP_PORT ? parseInt(process.env.SMTP_PORT, 10) : 587,
|
||||
SMTP_USER: process.env.SMTP_USER || "user@example.com",
|
||||
SMTP_PASS: process.env.SMTP_PASS || "your_smtp_password",
|
||||
};
|
||||
+37
-13
@@ -1,19 +1,28 @@
|
||||
import { verifyJWT } from "../middleware/verifyJWT.js";
|
||||
import { authApiLimiter } from "../middleware/rateLimiter.js";
|
||||
import { verifyJWT } from "../middleware/v1/verifyJWT.js";
|
||||
import { authApiLimiter } from "../middleware/v1/rateLimiter.js";
|
||||
|
||||
import AuthRoutes from "../routes/authRoute.js";
|
||||
import InviteRoutes from "../routes/inviteRoute.js";
|
||||
import MonitorRoutes from "../routes/monitorRoute.js";
|
||||
import CheckRoutes from "../routes/checkRoute.js";
|
||||
import SettingsRoutes from "../routes/settingsRoute.js";
|
||||
import MaintenanceWindowRoutes from "../routes/maintenanceWindowRoute.js";
|
||||
import StatusPageRoutes from "../routes/statusPageRoute.js";
|
||||
import QueueRoutes from "../routes/queueRoute.js";
|
||||
import LogRoutes from "../routes/logRoutes.js";
|
||||
import DiagnosticRoutes from "../routes/diagnosticRoute.js";
|
||||
import NotificationRoutes from "../routes/notificationRoute.js";
|
||||
import AuthRoutes from "../routes/v1/authRoute.js";
|
||||
import InviteRoutes from "../routes/v1//inviteRoute.js";
|
||||
import MonitorRoutes from "../routes/v1/monitorRoute.js";
|
||||
import CheckRoutes from "../routes/v1/checkRoute.js";
|
||||
import SettingsRoutes from "../routes/v1/settingsRoute.js";
|
||||
import MaintenanceWindowRoutes from "../routes/v1/maintenanceWindowRoute.js";
|
||||
import StatusPageRoutes from "../routes/v1/statusPageRoute.js";
|
||||
import QueueRoutes from "../routes/v1/queueRoute.js";
|
||||
import LogRoutes from "../routes/v1/logRoutes.js";
|
||||
import DiagnosticRoutes from "../routes/v1//diagnosticRoute.js";
|
||||
import NotificationRoutes from "../routes/v1/notificationRoute.js";
|
||||
|
||||
//V2
|
||||
import AuthRoutesV2 from "../routes/v2/auth.js";
|
||||
import InviteRoutesV2 from "../routes/v2/invite.js";
|
||||
import MaintenanceRoutesV2 from "../routes/v2/maintenance.js";
|
||||
import MonitorRoutesV2 from "../routes/v2/monitors.js";
|
||||
import NotificationChannelRoutesV2 from "../routes/v2/notificationChannels.js";
|
||||
import QueueRoutesV2 from "../routes/v2/queue.js";
|
||||
|
||||
export const setupRoutes = (app, controllers) => {
|
||||
// V1
|
||||
const authRoutes = new AuthRoutes(controllers.authController);
|
||||
const monitorRoutes = new MonitorRoutes(controllers.monitorController);
|
||||
const settingsRoutes = new SettingsRoutes(controllers.settingsController);
|
||||
@@ -37,4 +46,19 @@ export const setupRoutes = (app, controllers) => {
|
||||
app.use("/api/v1/status-page", statusPageRoutes.getRouter());
|
||||
app.use("/api/v1/notifications", verifyJWT, notificationRoutes.getRouter());
|
||||
app.use("/api/v1/diagnostic", verifyJWT, diagnosticRoutes.getRouter());
|
||||
|
||||
// V2
|
||||
const authRoutesV2 = new AuthRoutesV2(controllers.authControllerV2);
|
||||
const inviteRoutesV2 = new InviteRoutesV2(controllers.inviteControllerV2);
|
||||
const maintenanceRoutesV2 = new MaintenanceRoutesV2(controllers.maintenanceControllerV2);
|
||||
const monitorRoutesV2 = new MonitorRoutesV2(controllers.monitorControllerV2);
|
||||
const notificationChannelRoutesV2 = new NotificationChannelRoutesV2(controllers.notificationChannelControllerV2);
|
||||
const queueRoutesV2 = new QueueRoutesV2(controllers.queueControllerV2);
|
||||
|
||||
app.use("/api/v2/auth", authApiLimiter, authRoutesV2.getRouter());
|
||||
app.use("/api/v2/invite", inviteRoutesV2.getRouter());
|
||||
app.use("/api/v2/maintenance", maintenanceRoutesV2.getRouter());
|
||||
app.use("/api/v2/monitors", monitorRoutesV2.getRouter());
|
||||
app.use("/api/v2/notification-channels", notificationChannelRoutesV2.getRouter());
|
||||
app.use("/api/v2/queue", queueRoutesV2.getRouter());
|
||||
};
|
||||
+108
-39
@@ -1,22 +1,22 @@
|
||||
import ServiceRegistry from "../service/system/serviceRegistry.js";
|
||||
import TranslationService from "../service/system/translationService.js";
|
||||
import StringService from "../service/system/stringService.js";
|
||||
import MongoDB from "../db/mongo/MongoDB.js";
|
||||
import NetworkService from "../service/infrastructure/networkService.js";
|
||||
import EmailService from "../service/infrastructure/emailService.js";
|
||||
import BufferService from "../service/infrastructure/bufferService.js";
|
||||
import StatusService from "../service/infrastructure/statusService.js";
|
||||
import NotificationUtils from "../service/infrastructure/notificationUtils.js";
|
||||
import NotificationService from "../service/infrastructure/notificationService.js";
|
||||
import ErrorService from "../service/infrastructure/errorService.js";
|
||||
import SuperSimpleQueueHelper from "../service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js";
|
||||
import SuperSimpleQueue from "../service/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js";
|
||||
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";
|
||||
import MonitorService from "../service/business/monitorService.js";
|
||||
import ServiceRegistry from "../service/v1/system/serviceRegistry.js";
|
||||
import TranslationService from "../service/v1/system/translationService.js";
|
||||
import StringService from "../service/v1/system/stringService.js";
|
||||
import MongoDB from "../db/v1/MongoDB.js";
|
||||
import NetworkService from "../service/v1/infrastructure/networkService.js";
|
||||
import EmailService from "../service/v1/infrastructure/emailService.js";
|
||||
import BufferService from "../service/v1/infrastructure/bufferService.js";
|
||||
import StatusService from "../service/v1/infrastructure/statusService.js";
|
||||
import NotificationUtils from "../service/v1/infrastructure/notificationUtils.js";
|
||||
import NotificationService from "../service/v1/infrastructure/notificationService.js";
|
||||
import ErrorService from "../service/v1/infrastructure/errorService.js";
|
||||
import SuperSimpleQueueHelper from "../service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js";
|
||||
import SuperSimpleQueue from "../service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js";
|
||||
import UserService from "../service/v1/business/userService.js";
|
||||
import CheckService from "../service/v1/business/checkService.js";
|
||||
import DiagnosticService from "../service/v1/business/diagnosticService.js";
|
||||
import InviteService from "../service/v1/business/inviteService.js";
|
||||
import MaintenanceWindowService from "../service/v1/business/maintenanceWindowService.js";
|
||||
import MonitorService from "../service/v1/business/monitorService.js";
|
||||
import papaparse from "papaparse";
|
||||
import axios from "axios";
|
||||
import got from "got";
|
||||
@@ -46,27 +46,49 @@ import { GenerateAvatarImage } from "../utils/imageProcessing.js";
|
||||
import { ParseBoolean } from "../utils/utils.js";
|
||||
|
||||
// Models
|
||||
import Check from "../db/models/Check.js";
|
||||
import Monitor from "../db/models/Monitor.js";
|
||||
import User from "../db/models/User.js";
|
||||
import InviteToken from "../db/models/InviteToken.js";
|
||||
import StatusPage from "../db/models/StatusPage.js";
|
||||
import Team from "../db/models/Team.js";
|
||||
import MaintenanceWindow from "../db/models/MaintenanceWindow.js";
|
||||
import MonitorStats from "../db/models/MonitorStats.js";
|
||||
import Notification from "../db/models/Notification.js";
|
||||
import RecoveryToken from "../db/models/RecoveryToken.js";
|
||||
import AppSettings from "../db/models/AppSettings.js";
|
||||
import Check from "../db/v1/models/Check.js";
|
||||
import Monitor from "../db/v1/models/Monitor.js";
|
||||
import User from "../db/v1/models/User.js";
|
||||
import InviteToken from "../db/v1/models/InviteToken.js";
|
||||
import StatusPage from "../db/v1/models/StatusPage.js";
|
||||
import Team from "../db/v1/models/Team.js";
|
||||
import MaintenanceWindow from "../db/v1/models/MaintenanceWindow.js";
|
||||
import MonitorStats from "../db/v1/models/MonitorStats.js";
|
||||
import Notification from "../db/v1/models/Notification.js";
|
||||
import RecoveryToken from "../db/v1/models/RecoveryToken.js";
|
||||
import AppSettings from "../db/v1/models/AppSettings.js";
|
||||
|
||||
import InviteModule from "../db/mongo/modules/inviteModule.js";
|
||||
import CheckModule from "../db/mongo/modules/checkModule.js";
|
||||
import StatusPageModule from "../db/mongo/modules/statusPageModule.js";
|
||||
import UserModule from "../db/mongo/modules/userModule.js";
|
||||
import MaintenanceWindowModule from "../db/mongo/modules/maintenanceWindowModule.js";
|
||||
import MonitorModule from "../db/mongo/modules/monitorModule.js";
|
||||
import NotificationModule from "../db/mongo/modules/notificationModule.js";
|
||||
import RecoveryModule from "../db/mongo/modules/recoveryModule.js";
|
||||
import SettingsModule from "../db/mongo/modules/settingsModule.js";
|
||||
import InviteModule from "../db/v1/modules/inviteModule.js";
|
||||
import CheckModule from "../db/v1/modules/checkModule.js";
|
||||
import StatusPageModule from "../db/v1/modules/statusPageModule.js";
|
||||
import UserModule from "../db/v1/modules/userModule.js";
|
||||
import MaintenanceWindowModule from "../db/v1/modules/maintenanceWindowModule.js";
|
||||
import MonitorModule from "../db/v1/modules/monitorModule.js";
|
||||
import NotificationModule from "../db/v1/modules/notificationModule.js";
|
||||
import RecoveryModule from "../db/v1/modules/recoveryModule.js";
|
||||
import SettingsModule from "../db/v1/modules/settingsModule.js";
|
||||
|
||||
// V2 Business
|
||||
import AuthServiceV2 from "../service/v2/business/AuthService.js";
|
||||
import CheckServiceV2 from "../service/v2/business/CheckService.js";
|
||||
import InviteServiceV2 from "../service/v2/business/InviteService.js";
|
||||
import MaintenanceServiceV2 from "../service/v2/business/MaintenanceService.js";
|
||||
import MonitorServiceV2 from "../service/v2/business/MonitorService.js";
|
||||
import MonitorStatsServiceV2 from "../service/v2/business/MonitorStatsService.js";
|
||||
import NotificationChannelServiceV2 from "../service/v2/business/NotificationChannelService.js";
|
||||
import QueueServiceV2 from "../service/v2/business/QueueService.js";
|
||||
import UserServiceV2 from "../service/v2/business/UserService.js";
|
||||
|
||||
// V2 Infra
|
||||
import DiscordServiceV2 from "../service/v2/infrastructure/NotificationServices/Discord.js";
|
||||
import EmailServiceV2 from "../service/v2/infrastructure/NotificationServices/Email.js";
|
||||
import SlackServiceV2 from "../service/v2/infrastructure/NotificationServices/Slack.js";
|
||||
import WebhookServiceV2 from "../service/v2/infrastructure/NotificationServices/Webhook.js";
|
||||
import JobGeneratorV2 from "../service/v2/infrastructure/JobGenerator.js";
|
||||
import JobQueueV2 from "../service/v2/infrastructure/JobQueue.js";
|
||||
import NetworkServiceV2 from "../service/v2/infrastructure/NetworkService.js";
|
||||
import NotificationServiceV2 from "../service/v2/infrastructure/NotificationService.js";
|
||||
import StatusServiceV2 from "../service/v2/infrastructure/StatusService.js";
|
||||
|
||||
export const initializeServices = async ({ logger, envSettings, settingsService }) => {
|
||||
const serviceRegistry = new ServiceRegistry({ logger });
|
||||
@@ -208,7 +230,35 @@ export const initializeServices = async ({ logger, envSettings, settingsService
|
||||
games,
|
||||
});
|
||||
|
||||
// V2 Services
|
||||
const checkServiceV2 = new CheckServiceV2();
|
||||
const inviteServiceV2 = new InviteServiceV2();
|
||||
const maintenanceServiceV2 = new MaintenanceServiceV2();
|
||||
const monitorStatsServiceV2 = new MonitorStatsServiceV2();
|
||||
const notificationChannelServiceV2 = new NotificationChannelServiceV2();
|
||||
const userServiceV2 = new UserServiceV2();
|
||||
const discordServiceV2 = new DiscordServiceV2();
|
||||
const emailServiceV2 = new EmailServiceV2(userServiceV2);
|
||||
const slackServiceV2 = new SlackServiceV2();
|
||||
const webhookServiceV2 = new WebhookServiceV2();
|
||||
const networkServiceV2 = new NetworkServiceV2();
|
||||
const statusServiceV2 = new StatusServiceV2();
|
||||
const notificationServiceV2 = new NotificationServiceV2(userServiceV2);
|
||||
const jobGeneratorV2 = new JobGeneratorV2(
|
||||
networkServiceV2,
|
||||
checkServiceV2,
|
||||
monitorStatsServiceV2,
|
||||
statusServiceV2,
|
||||
notificationServiceV2,
|
||||
maintenanceServiceV2
|
||||
);
|
||||
const jobQueueV2 = await JobQueueV2.create(jobGeneratorV2);
|
||||
const authServiceV2 = new AuthServiceV2(jobQueueV2);
|
||||
const monitorServiceV2 = new MonitorServiceV2(jobQueueV2);
|
||||
const queueServiceV2 = new QueueServiceV2(jobQueueV2);
|
||||
|
||||
const services = {
|
||||
//v1
|
||||
settingsService,
|
||||
translationService,
|
||||
stringService,
|
||||
@@ -227,6 +277,25 @@ export const initializeServices = async ({ logger, envSettings, settingsService
|
||||
monitorService,
|
||||
errorService,
|
||||
logger,
|
||||
//v2
|
||||
jobQueueV2,
|
||||
authServiceV2,
|
||||
checkServiceV2,
|
||||
inviteServiceV2,
|
||||
maintenanceServiceV2,
|
||||
monitorServiceV2,
|
||||
monitorStatsServiceV2,
|
||||
notificationChannelServiceV2,
|
||||
queueServiceV2,
|
||||
userServiceV2,
|
||||
discordServiceV2,
|
||||
emailServiceV2,
|
||||
slackServiceV2,
|
||||
webhookServiceV2,
|
||||
networkServiceV2,
|
||||
statusServiceV2,
|
||||
notificationServiceV2,
|
||||
jobGeneratorV2,
|
||||
};
|
||||
|
||||
Object.values(services).forEach((service) => {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { createAnnouncementValidation } from "../validation/joi.js";
|
||||
import { createAnnouncementValidation } from "../../validation/joi.js";
|
||||
import BaseController from "./baseController.js";
|
||||
|
||||
const SERVICE_NAME = "announcementController";
|
||||
+20
-3
@@ -10,10 +10,10 @@ import {
|
||||
editUserByIdParamValidation,
|
||||
editUserByIdBodyValidation,
|
||||
editSuperadminUserByIdBodyValidation,
|
||||
} from "../validation/joi.js";
|
||||
editUserPasswordByIdBodyValidation,
|
||||
} from "../../validation/joi.js";
|
||||
|
||||
const SERVICE_NAME = "authController";
|
||||
|
||||
/**
|
||||
* Authentication Controller
|
||||
*
|
||||
@@ -436,7 +436,7 @@ class AuthController extends BaseController {
|
||||
async (req, res) => {
|
||||
const roles = req?.user?.role;
|
||||
if (!roles.includes("superadmin")) {
|
||||
throw createError("Unauthorized", 403);
|
||||
throw this.errorService.createError("Unauthorized", 403);
|
||||
}
|
||||
|
||||
const userId = req.params.userId;
|
||||
@@ -456,6 +456,23 @@ class AuthController extends BaseController {
|
||||
SERVICE_NAME,
|
||||
"editUserById"
|
||||
);
|
||||
editUserPasswordById = this.asyncHandler(
|
||||
async (req, res) => {
|
||||
const roles = req?.user?.role;
|
||||
if (!roles.includes("superadmin")) {
|
||||
throw this.errorService.createError("Unauthorized", 403);
|
||||
}
|
||||
|
||||
const userId = req.params.userId;
|
||||
await editUserByIdParamValidation.validateAsync(req.params);
|
||||
await editUserPasswordByIdBodyValidation.validateAsync(req.body);
|
||||
const updatedPassword = req.body.password;
|
||||
await this.userService.setPasswordByUserId(userId, updatedPassword);
|
||||
return res.success({ msg: "Password reset successfully" });
|
||||
},
|
||||
SERVICE_NAME,
|
||||
"editUserPasswordById"
|
||||
);
|
||||
}
|
||||
|
||||
export default AuthController;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { AppError } from "../service/infrastructure/errorService.js";
|
||||
import { AppError } from "../../service/v1/infrastructure/errorService.js";
|
||||
|
||||
export const createCommonDependencies = (db, errorService, logger, stringService) => {
|
||||
return {
|
||||
+1
-1
@@ -9,7 +9,7 @@ import {
|
||||
ackCheckBodyValidation,
|
||||
ackAllChecksParamValidation,
|
||||
ackAllChecksBodyValidation,
|
||||
} from "../validation/joi.js";
|
||||
} from "../../validation/joi.js";
|
||||
|
||||
const SERVICE_NAME = "checkController";
|
||||
|
||||
File renamed without changes.
File renamed without changes.
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { inviteBodyValidation, inviteVerificationBodyValidation } from "../validation/joi.js";
|
||||
import { inviteBodyValidation, inviteVerificationBodyValidation } from "../../validation/joi.js";
|
||||
import BaseController from "./baseController.js";
|
||||
const SERVICE_NAME = "inviteController";
|
||||
|
||||
File renamed without changes.
Executable → Regular
+1
-1
@@ -6,7 +6,7 @@ import {
|
||||
getMaintenanceWindowsByMonitorIdParamValidation,
|
||||
getMaintenanceWindowsByTeamIdQueryValidation,
|
||||
deleteMaintenanceWindowByIdParamValidation,
|
||||
} from "../validation/joi.js";
|
||||
} from "../../validation/joi.js";
|
||||
import BaseController from "./baseController.js";
|
||||
|
||||
const SERVICE_NAME = "maintenanceWindowController";
|
||||
Executable → Regular
+1
-1
@@ -11,7 +11,7 @@ import {
|
||||
getCertificateParamValidation,
|
||||
getHardwareDetailsByIdParamValidation,
|
||||
getHardwareDetailsByIdQueryValidation,
|
||||
} from "../validation/joi.js";
|
||||
} from "../../validation/joi.js";
|
||||
import sslChecker from "ssl-checker";
|
||||
import { fetchMonitorCertificate } from "./controllerUtils.js";
|
||||
import BaseController from "./baseController.js";
|
||||
Executable → Regular
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { createNotificationBodyValidation } from "../validation/joi.js";
|
||||
import { createNotificationBodyValidation } from "../../validation/joi.js";
|
||||
import BaseController from "./baseController.js";
|
||||
|
||||
const SERVICE_NAME = "NotificationController";
|
||||
File renamed without changes.
Executable → Regular
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { updateAppSettingsBodyValidation } from "../validation/joi.js";
|
||||
import { sendTestEmailBodyValidation } from "../validation/joi.js";
|
||||
import { updateAppSettingsBodyValidation } from "../../validation/joi.js";
|
||||
import { sendTestEmailBodyValidation } from "../../validation/joi.js";
|
||||
import BaseController from "./baseController.js";
|
||||
|
||||
const SERVICE_NAME = "SettingsController";
|
||||
Executable → Regular
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { createStatusPageBodyValidation, getStatusPageParamValidation, getStatusPageQueryValidation, imageValidation } from "../validation/joi.js";
|
||||
import { createStatusPageBodyValidation, getStatusPageParamValidation, getStatusPageQueryValidation, imageValidation } from "../../validation/joi.js";
|
||||
import BaseController from "./baseController.js";
|
||||
|
||||
const SERVICE_NAME = "statusPageController";
|
||||
@@ -0,0 +1,150 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import { encode, decode } from "../../utils/JWTUtils.js";
|
||||
import AuthService from "../../service/v2/business/AuthService.js";
|
||||
import ApiError from "../../utils/ApiError.js";
|
||||
import InviteService from "../../service/v2/business/InviteService.js";
|
||||
import { IInvite } from "../../db/v2/models/index.js";
|
||||
|
||||
class AuthController {
|
||||
private authService: AuthService;
|
||||
private inviteService: InviteService;
|
||||
constructor(authService: AuthService, inviteService: InviteService) {
|
||||
this.authService = authService;
|
||||
this.inviteService = inviteService;
|
||||
}
|
||||
|
||||
register = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const { email, firstName, lastName, password } = req.body;
|
||||
|
||||
if (!email || !firstName || !lastName || !password) {
|
||||
throw new Error("Email, firstName, lastName, and password are required");
|
||||
}
|
||||
|
||||
const result = await this.authService.register({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
password,
|
||||
});
|
||||
|
||||
const token = encode(result);
|
||||
|
||||
res.cookie("token", token, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
sameSite: "strict",
|
||||
maxAge: 7 * 24 * 60 * 60 * 1000, // 1 week
|
||||
});
|
||||
|
||||
res.status(201).json({
|
||||
message: "User created successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
registerWithInvite = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const token = req.params.token;
|
||||
if (!token) {
|
||||
throw new ApiError("Invite token is required", 400);
|
||||
}
|
||||
|
||||
const invite: IInvite = await this.inviteService.get(token);
|
||||
|
||||
const { firstName, lastName, password } = req.body;
|
||||
const email = invite?.email;
|
||||
const roles = invite?.roles;
|
||||
|
||||
if (!email || !firstName || !lastName || !password || !roles || roles.length === 0) {
|
||||
throw new Error("Email, firstName, lastName, password, and roles are required");
|
||||
}
|
||||
|
||||
const result = await this.authService.registerWithInvite({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
password,
|
||||
roles,
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
throw new Error("Registration failed");
|
||||
}
|
||||
|
||||
await this.inviteService.delete(invite._id.toString());
|
||||
|
||||
const jwt = encode(result);
|
||||
|
||||
res.cookie("token", jwt, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
sameSite: "strict",
|
||||
maxAge: 7 * 24 * 60 * 60 * 1000, // 1 week
|
||||
});
|
||||
|
||||
res.status(201).json({ message: "User created successfully" });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
login = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const { email, password } = req.body;
|
||||
// Validation
|
||||
if (!email || !password) {
|
||||
return res.status(400).json({ message: "Email and password are required" });
|
||||
}
|
||||
const result = await this.authService.login({ email, password });
|
||||
|
||||
const token = encode(result);
|
||||
|
||||
res.cookie("token", token, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
sameSite: "strict",
|
||||
maxAge: 7 * 24 * 60 * 60 * 1000, // 1 week
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
message: "Login successful",
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
logout = (req: Request, res: Response) => {
|
||||
res.clearCookie("token", {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
sameSite: "strict",
|
||||
});
|
||||
res.status(200).json({ message: "Logout successful" });
|
||||
};
|
||||
|
||||
me = (req: Request, res: Response, next: NextFunction) => {
|
||||
return res.status(200).json({ message: "OK" });
|
||||
};
|
||||
|
||||
cleanup = async (req: Request, res: Response) => {
|
||||
try {
|
||||
await this.authService.cleanup();
|
||||
res.status(200).json({ message: "Cleanup successful" });
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
cleanMonitors = async (req: Request, res: Response) => {
|
||||
try {
|
||||
await this.authService.cleanMonitors();
|
||||
res.status(200).json({ message: "Monitors cleanup successful" });
|
||||
} catch (error) {
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default AuthController;
|
||||
@@ -0,0 +1,62 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import InviteService from "../../service/v2/business/InviteService.js";
|
||||
|
||||
class InviteController {
|
||||
private inviteService: InviteService;
|
||||
constructor(inviteService: InviteService) {
|
||||
this.inviteService = inviteService;
|
||||
}
|
||||
|
||||
create = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
const invite = await this.inviteService.create(tokenizedUser, req.body);
|
||||
res.status(201).json({ message: "OK", data: invite });
|
||||
} catch (error: any) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
getAll = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const invites = await this.inviteService.getAll();
|
||||
res.status(200).json({
|
||||
message: "OK",
|
||||
data: invites,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
get = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const token = req.params.token;
|
||||
if (!token) {
|
||||
return res.status(400).json({ message: "Token parameter is required" });
|
||||
}
|
||||
const invite = await this.inviteService.get(token);
|
||||
res.status(200).json({ message: "OK", data: invite });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
delete = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
return res.status(400).json({ message: "ID parameter is required" });
|
||||
}
|
||||
await this.inviteService.delete(id);
|
||||
res.status(204).json({ message: "OK" });
|
||||
} catch (error: any) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default InviteController;
|
||||
@@ -0,0 +1,96 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import MaintenanceService from "../../service/v2/business/MaintenanceService.js";
|
||||
|
||||
class MaintenanceController {
|
||||
private maintenanceService: MaintenanceService;
|
||||
constructor(maintenanceService: MaintenanceService) {
|
||||
this.maintenanceService = maintenanceService;
|
||||
}
|
||||
|
||||
create = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
const maintenance = await this.maintenanceService.create(tokenizedUser, req.body);
|
||||
res.status(201).json({ message: "OK", data: maintenance });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
getAll = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const maintenances = await this.maintenanceService.getAll();
|
||||
res.status(200).json({
|
||||
message: "OK",
|
||||
data: maintenances,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
toggleActive = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
return res.status(400).json({ message: "ID parameter is required" });
|
||||
}
|
||||
const maintenance = await this.maintenanceService.toggleActive(tokenizedUser, id);
|
||||
res.status(200).json({ message: "OK", data: maintenance });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
update = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
return res.status(400).json({ message: "ID parameter is required" });
|
||||
}
|
||||
const updatedMaintenance = await this.maintenanceService.update(tokenizedUser, id, req.body);
|
||||
res.status(200).json({ message: "OK", data: updatedMaintenance });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
get = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
return res.status(400).json({ message: "ID parameter is required" });
|
||||
}
|
||||
const maintenance = await this.maintenanceService.get(id);
|
||||
res.status(200).json({ message: "OK", data: maintenance });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
delete = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
return res.status(400).json({ message: "ID parameter is required" });
|
||||
}
|
||||
await this.maintenanceService.delete(id);
|
||||
res.status(204).json({ message: "OK" });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default MaintenanceController;
|
||||
@@ -0,0 +1,191 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import ApiError from "../../utils/ApiError.js";
|
||||
import MonitorService from "../../service/v2/business/MonitorService.js";
|
||||
import { MonitorType } from "../../db/v2/models/monitors/Monitor.js";
|
||||
import CheckService from "../../service/v2/business/CheckService.js";
|
||||
class MonitorController {
|
||||
private monitorService: MonitorService;
|
||||
private checkService: CheckService;
|
||||
constructor(monitorService: MonitorService, checkService: CheckService) {
|
||||
this.monitorService = monitorService;
|
||||
this.checkService = checkService;
|
||||
}
|
||||
|
||||
create = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
|
||||
const monitor = await this.monitorService.create(tokenizedUser, req.body);
|
||||
res.status(201).json({
|
||||
message: "Monitor created successfully",
|
||||
data: monitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
getAll = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
|
||||
let monitors;
|
||||
if (req.query.embedChecks === "true") {
|
||||
const page = Math.max(1, Number(req.query.page) || 1);
|
||||
const limit = Math.max(1, Number(req.query.limit) || 10);
|
||||
const type: MonitorType[] = req.query.type as MonitorType[];
|
||||
|
||||
monitors = await this.monitorService.getAllEmbedChecks(page, limit, type);
|
||||
} else {
|
||||
monitors = await this.monitorService.getAll();
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
message: "Monitors retrieved successfully",
|
||||
data: monitors,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
getChecks = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
throw new ApiError("Monitor ID is required", 400);
|
||||
}
|
||||
|
||||
const page = Number(req.query.page);
|
||||
const rowsPerPage = Number(req.query.rowsPerPage);
|
||||
|
||||
if (isNaN(page)) throw new ApiError("Page query parameter must be a number", 400);
|
||||
if (isNaN(rowsPerPage)) throw new ApiError("rowsPerPage query parameter must be a number", 400);
|
||||
|
||||
if (page < 0) throw new ApiError("Page must be greater than 0", 400);
|
||||
if (rowsPerPage < 0) throw new ApiError("rowsPerPage must be greater than 0", 400);
|
||||
|
||||
const { count, checks } = await this.checkService.getChecks(id, page, rowsPerPage);
|
||||
res.status(200).json({
|
||||
message: "Checks retrieved successfully",
|
||||
data: { count, checks },
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
toggleActive = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
throw new ApiError("Monitor ID is required", 400);
|
||||
}
|
||||
|
||||
const monitor = await this.monitorService.toggleActive(id, tokenizedUser);
|
||||
res.status(200).json({
|
||||
message: "Monitor paused/unpaused successfully",
|
||||
data: monitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
get = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
throw new ApiError("Monitor ID is required", 400);
|
||||
}
|
||||
|
||||
const range = req.query.range;
|
||||
if (!range || typeof range !== "string") throw new ApiError("Range query parameter is required", 400);
|
||||
|
||||
let monitor;
|
||||
|
||||
const status = req.query.status;
|
||||
if (status && typeof status !== "string") {
|
||||
throw new ApiError("Status query parameter must be a string", 400);
|
||||
}
|
||||
|
||||
if (req.query.embedChecks === "true") {
|
||||
monitor = await this.monitorService.getEmbedChecks(id, range, status);
|
||||
} else {
|
||||
monitor = await this.monitorService.get(id);
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
message: "Monitor retrieved successfully",
|
||||
data: monitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
update = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
throw new ApiError("Monitor ID is required", 400);
|
||||
}
|
||||
|
||||
const monitor = await this.monitorService.update(tokenizedUser, id, req.body);
|
||||
res.status(200).json({
|
||||
message: "Monitor updated successfully",
|
||||
data: monitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
delete = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
throw new ApiError("Monitor ID is required", 400);
|
||||
}
|
||||
await this.monitorService.delete(id);
|
||||
|
||||
res.status(200).json({
|
||||
message: "Monitor deleted successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default MonitorController;
|
||||
@@ -0,0 +1,96 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import NotificationService from "../../service/v2/business/NotificationChannelService.js";
|
||||
|
||||
class NotificationChannelController {
|
||||
private notificationService: NotificationService;
|
||||
constructor(notificationService: NotificationService) {
|
||||
this.notificationService = notificationService;
|
||||
}
|
||||
|
||||
create = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
const channel = await this.notificationService.create(tokenizedUser, req.body);
|
||||
res.status(201).json({ message: "OK", data: channel });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
getAll = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const notificationChannels = await this.notificationService.getAll();
|
||||
res.status(200).json({
|
||||
message: "OK",
|
||||
data: notificationChannels,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
toggleActive = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
return res.status(400).json({ message: "ID parameter is required" });
|
||||
}
|
||||
const notificationChannel = await this.notificationService.toggleActive(tokenizedUser, id);
|
||||
res.status(200).json({ message: "OK", data: notificationChannel });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
update = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const tokenizedUser = req.user;
|
||||
if (!tokenizedUser) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
return res.status(400).json({ message: "ID parameter is required" });
|
||||
}
|
||||
const updatedChannel = await this.notificationService.update(tokenizedUser, id, req.body);
|
||||
res.status(200).json({ message: "OK", data: updatedChannel });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
get = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
return res.status(400).json({ message: "ID parameter is required" });
|
||||
}
|
||||
const notificationChannel = await this.notificationService.get(id);
|
||||
res.status(200).json({ message: "OK", data: notificationChannel });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
delete = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const id = req.params.id;
|
||||
if (!id) {
|
||||
return res.status(400).json({ message: "ID parameter is required" });
|
||||
}
|
||||
await this.notificationService.delete(id);
|
||||
res.status(204).json({ message: "OK" });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default NotificationChannelController;
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import QueueService from "../../service/v2/business/QueueService.js";
|
||||
class QueueController {
|
||||
private queueService: QueueService;
|
||||
constructor(queueService: QueueService) {
|
||||
this.queueService = queueService;
|
||||
}
|
||||
|
||||
getJobs = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const jobs = await this.queueService.getJobs();
|
||||
res.status(200).json({ message: "ok", data: jobs });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
getMetrics = async (req: Request, res: Response, next: NextFunction) => {
|
||||
const metrics = await this.queueService.getMetrics();
|
||||
res.status(200).json({ message: "ok", data: metrics });
|
||||
};
|
||||
|
||||
flush = async (req: Request, res: Response, next: NextFunction) => {
|
||||
const result = await this.queueService.flush();
|
||||
res.status(200).json({ message: "ok", flushed: result });
|
||||
};
|
||||
}
|
||||
|
||||
export default QueueController;
|
||||
@@ -1,5 +1,5 @@
|
||||
import mongoose from "mongoose";
|
||||
import AppSettings from "../models/AppSettings.js";
|
||||
import AppSettings from "./models/AppSettings.js";
|
||||
import { runMigrations } from "./migration/index.js";
|
||||
class MongoDB {
|
||||
static SERVICE_NAME = "MongoDB";
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import Monitor from "../../models/Monitor.js";
|
||||
import Monitor from "../models/Monitor.js";
|
||||
async function migrateStatusWindowThreshold() {
|
||||
try {
|
||||
const monitors = await Monitor.find({ statusWindowThreshold: { $lt: 1 } });
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,6 +1,5 @@
|
||||
import mongoose from "mongoose";
|
||||
import bcrypt from "bcryptjs";
|
||||
import logger from "../../utils/logger.js";
|
||||
import Monitor from "./Monitor.js";
|
||||
import Team from "./Team.js";
|
||||
import Notification from "./Notification.js";
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
-2
@@ -232,7 +232,7 @@ class MonitorModule {
|
||||
const formatLookup = {
|
||||
recent: "%Y-%m-%dT%H:%M:00Z",
|
||||
day: "%Y-%m-%dT%H:00:00Z",
|
||||
week: "%Y-%m-%dT%H:00:00Z",
|
||||
week: "%Y-%m-%dT00:00:00Z",
|
||||
month: "%Y-%m-%dT00:00:00Z",
|
||||
};
|
||||
|
||||
@@ -308,7 +308,7 @@ class MonitorModule {
|
||||
const formatLookup = {
|
||||
recent: "%Y-%m-%dT%H:%M:00Z",
|
||||
day: "%Y-%m-%dT%H:00:00Z",
|
||||
week: "%Y-%m-%dT%H:00:00Z",
|
||||
week: "%Y-%m-%dT00:00:00Z",
|
||||
month: "%Y-%m-%dT00:00:00Z",
|
||||
};
|
||||
const dateString = formatLookup[dateRange];
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,5 +1,5 @@
|
||||
import Monitor from "../../models/Monitor.js";
|
||||
import Check from "../../models/Check.js";
|
||||
import Monitor from "../models/Monitor.js";
|
||||
import Check from "../models/Check.js";
|
||||
import { logger } from "../../../utils/logger.js";
|
||||
|
||||
const generateRandomUrl = () => {
|
||||
@@ -0,0 +1,25 @@
|
||||
import mongoose from "mongoose";
|
||||
|
||||
const MONGODB_URI = process.env.MONGODB_URI || "mongodb://localhost:27017/checkmate";
|
||||
|
||||
export const connectDatabase = async (): Promise<boolean> => {
|
||||
try {
|
||||
await mongoose.connect(MONGODB_URI);
|
||||
console.log("Connected to MongoDB");
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("MongoDB connection error:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
export const disconnectDatabase = async (): Promise<boolean> => {
|
||||
try {
|
||||
await mongoose.disconnect();
|
||||
console.log("Disconnected from MongoDB");
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("MongoDB disconnection error:", error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
import mongoose, { Schema, Document, Types } from "mongoose";
|
||||
|
||||
export interface IRole extends Document {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
description?: string;
|
||||
permissions: string[];
|
||||
isSystem: boolean;
|
||||
isActive: boolean;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
const roleSchema = new Schema<IRole>(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
maxlength: 50,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
trim: true,
|
||||
maxlength: 200,
|
||||
},
|
||||
|
||||
permissions: [
|
||||
{
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
isSystem: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
roleSchema.index({ name: 1 }, { unique: true });
|
||||
|
||||
export const Role = mongoose.model<IRole>("Role_v2", roleSchema);
|
||||
@@ -0,0 +1,102 @@
|
||||
import mongoose, { Schema, Document, Types } from "mongoose";
|
||||
|
||||
export interface ITokenizedUser {
|
||||
sub: string;
|
||||
roles: string[];
|
||||
}
|
||||
export interface IUser extends Document {
|
||||
_id: Types.ObjectId;
|
||||
email: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
passwordHash: string;
|
||||
roles: Types.ObjectId[];
|
||||
profile: {
|
||||
avatar?: string;
|
||||
bio?: string;
|
||||
timezone: string;
|
||||
locale: string;
|
||||
};
|
||||
preferences: {
|
||||
theme: "light" | "dark" | "system";
|
||||
};
|
||||
lastLoginAt?: Date;
|
||||
isActive: boolean;
|
||||
isVerified: boolean;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
const userSchema = new Schema<IUser>(
|
||||
{
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
trim: true,
|
||||
lowercase: true,
|
||||
},
|
||||
firstName: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
maxlength: 50,
|
||||
},
|
||||
lastName: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
maxlength: 50,
|
||||
},
|
||||
passwordHash: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
roles: [
|
||||
{
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Role_v2",
|
||||
},
|
||||
],
|
||||
profile: {
|
||||
avatar: {
|
||||
type: String,
|
||||
},
|
||||
bio: {
|
||||
type: String,
|
||||
maxlength: 200,
|
||||
},
|
||||
timezone: {
|
||||
type: String,
|
||||
default: "UTC",
|
||||
},
|
||||
locale: {
|
||||
type: String,
|
||||
default: "en",
|
||||
},
|
||||
},
|
||||
preferences: {
|
||||
theme: {
|
||||
type: String,
|
||||
enum: ["light", "dark", "system"],
|
||||
default: "system",
|
||||
},
|
||||
},
|
||||
lastLoginAt: {
|
||||
type: Date,
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
isVerified: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const User = mongoose.model<IUser>("User_v2", userSchema);
|
||||
@@ -0,0 +1,297 @@
|
||||
import mongoose, { Schema, Document, Types } from "mongoose";
|
||||
import { MonitorType, MonitorTypes, MonitorStatus, MonitorStatuses } from "../monitors/Monitor.js";
|
||||
import type { Response } from "got";
|
||||
export type GotTimings = Response["timings"];
|
||||
export interface ITimingPhases {
|
||||
wait: number;
|
||||
dns: number;
|
||||
tcp: number;
|
||||
tls: number;
|
||||
request: number;
|
||||
firstByte: number;
|
||||
download: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface ICpuInfo {
|
||||
physical_core: number;
|
||||
logical_core: number;
|
||||
frequency: number;
|
||||
current_frequency: number;
|
||||
temperature: number[]; // per-core temps
|
||||
free_percent: number;
|
||||
usage_percent: number;
|
||||
}
|
||||
|
||||
export interface IMemoryInfo {
|
||||
total_bytes: number;
|
||||
available_bytes: number;
|
||||
used_bytes: number;
|
||||
usage_percent: number;
|
||||
}
|
||||
|
||||
export interface IHostInfo {
|
||||
os?: string;
|
||||
platform?: string;
|
||||
kernel_version?: string;
|
||||
pretty_name?: string;
|
||||
}
|
||||
|
||||
export interface IDiskInfo {
|
||||
device: string;
|
||||
total_bytes: number;
|
||||
free_bytes: number;
|
||||
used_bytes: number;
|
||||
usage_percent: number;
|
||||
total_inodes?: number;
|
||||
free_inodes?: number;
|
||||
used_inodes?: number;
|
||||
inodes_usage_percent?: number;
|
||||
read_bytes?: number;
|
||||
write_bytes?: number;
|
||||
read_time?: number;
|
||||
write_time?: number;
|
||||
}
|
||||
|
||||
export interface INetInfo {
|
||||
name: string;
|
||||
bytes_sent: number;
|
||||
bytes_recv: number;
|
||||
packets_sent: number;
|
||||
packets_recv: number;
|
||||
err_in: number;
|
||||
err_out: number;
|
||||
drop_in: number;
|
||||
drop_out: number;
|
||||
fifo_in: number;
|
||||
fifo_out: number;
|
||||
}
|
||||
|
||||
export interface ICaptureInfo {
|
||||
version?: string;
|
||||
mode?: string;
|
||||
}
|
||||
|
||||
export interface ISystemInfo {
|
||||
cpu: ICpuInfo;
|
||||
memory: IMemoryInfo;
|
||||
disk: IDiskInfo[];
|
||||
host: IHostInfo;
|
||||
net: INetInfo[];
|
||||
}
|
||||
|
||||
export interface ILighthouseAudit {
|
||||
id?: string;
|
||||
title?: string;
|
||||
score?: number | null;
|
||||
displayValue?: string;
|
||||
numericValue?: number;
|
||||
numericUnit?: string;
|
||||
}
|
||||
export interface ILighthouseCategories {
|
||||
accessibility?: { score?: number | null };
|
||||
"best-practices"?: { score?: number | null };
|
||||
seo?: { score?: number | null };
|
||||
performance?: { score?: number | null };
|
||||
}
|
||||
|
||||
export interface ILighthouseResult {
|
||||
categories?: ILighthouseCategories;
|
||||
audits?: Record<string, ILighthouseAudit>;
|
||||
}
|
||||
|
||||
export interface ICheckLighthouseFields {
|
||||
accessibility: number;
|
||||
bestPractices: number;
|
||||
seo: number;
|
||||
performance: number;
|
||||
audits: {
|
||||
cls: ILighthouseAudit;
|
||||
si: ILighthouseAudit;
|
||||
fcp: ILighthouseAudit;
|
||||
lcp: ILighthouseAudit;
|
||||
tbt: ILighthouseAudit;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ICheck extends Document {
|
||||
_id: Types.ObjectId;
|
||||
monitorId: Types.ObjectId;
|
||||
type: MonitorType;
|
||||
status: MonitorStatus;
|
||||
message: string;
|
||||
responseTime?: number; // in ms
|
||||
timings?: GotTimings;
|
||||
httpStatusCode?: number;
|
||||
errorMessage?: string;
|
||||
ack: boolean;
|
||||
ackAt?: Date;
|
||||
ackBy?: Types.ObjectId;
|
||||
expiry: Date;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
system?: ISystemInfo;
|
||||
capture?: ICaptureInfo;
|
||||
lighthouse?: ICheckLighthouseFields;
|
||||
}
|
||||
|
||||
const CheckSchema = new Schema<ICheck>(
|
||||
{
|
||||
monitorId: { type: Schema.Types.ObjectId, ref: "Monitor_v2", required: true },
|
||||
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: MonitorTypes,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: MonitorStatuses,
|
||||
},
|
||||
message: { type: String, trim: true },
|
||||
responseTime: { type: Number },
|
||||
timings: {
|
||||
start: { type: Date },
|
||||
socket: { type: Date },
|
||||
lookup: { type: Date },
|
||||
connect: { type: Date },
|
||||
secureConnect: { type: Date },
|
||||
response: { type: Date },
|
||||
end: { type: Date },
|
||||
phases: {
|
||||
wait: { type: Number },
|
||||
dns: { type: Number },
|
||||
tcp: { type: Number },
|
||||
tls: { type: Number },
|
||||
request: { type: Number },
|
||||
firstByte: { type: Number },
|
||||
download: { type: Number },
|
||||
total: { type: Number },
|
||||
},
|
||||
},
|
||||
system: {
|
||||
type: {
|
||||
cpu: {
|
||||
physical_core: { type: Number },
|
||||
logical_core: { type: Number },
|
||||
frequency: { type: Number },
|
||||
current_frequency: { type: Number },
|
||||
temperature: [{ type: Number }],
|
||||
free_percent: { type: Number },
|
||||
usage_percent: { type: Number },
|
||||
},
|
||||
memory: {
|
||||
total_bytes: { type: Number },
|
||||
available_bytes: { type: Number },
|
||||
used_bytes: { type: Number },
|
||||
usage_percent: { type: Number },
|
||||
},
|
||||
disk: [
|
||||
{
|
||||
device: { type: String },
|
||||
total_bytes: { type: Number },
|
||||
free_bytes: { type: Number },
|
||||
used_bytes: { type: Number },
|
||||
usage_percent: { type: Number },
|
||||
total_inodes: { type: Number },
|
||||
free_inodes: { type: Number },
|
||||
used_inodes: { type: Number },
|
||||
inodes_usage_percent: { type: Number },
|
||||
read_bytes: { type: Number },
|
||||
write_bytes: { type: Number },
|
||||
read_time: { type: Number },
|
||||
write_time: { type: Number },
|
||||
},
|
||||
],
|
||||
host: {
|
||||
os: { type: String },
|
||||
platform: { type: String },
|
||||
kernel_version: { type: String },
|
||||
pretty_name: { type: String },
|
||||
},
|
||||
net: [
|
||||
{
|
||||
name: { type: String },
|
||||
bytes_sent: { type: Number },
|
||||
bytes_recv: { type: Number },
|
||||
packets_sent: { type: Number },
|
||||
packets_recv: { type: Number },
|
||||
err_in: { type: Number },
|
||||
err_out: { type: Number },
|
||||
drop_in: { type: Number },
|
||||
drop_out: { type: Number },
|
||||
fifo_in: { type: Number },
|
||||
fifo_out: { type: Number },
|
||||
},
|
||||
],
|
||||
},
|
||||
required: false,
|
||||
},
|
||||
|
||||
capture: {
|
||||
type: {
|
||||
version: { type: String },
|
||||
mode: { type: String },
|
||||
},
|
||||
required: false,
|
||||
},
|
||||
lighthouse: {
|
||||
accessibility: { type: Number, required: false },
|
||||
bestPractices: { type: Number, required: false },
|
||||
seo: { type: Number, required: false },
|
||||
performance: { type: Number, required: false },
|
||||
audits: {
|
||||
cls: {
|
||||
type: Object,
|
||||
},
|
||||
si: {
|
||||
type: Object,
|
||||
},
|
||||
fcp: {
|
||||
type: Object,
|
||||
},
|
||||
lcp: {
|
||||
type: Object,
|
||||
},
|
||||
tbt: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
type: {
|
||||
accessibility: { type: Number },
|
||||
bestPractices: { type: Number },
|
||||
seo: { type: Number },
|
||||
performance: { type: Number },
|
||||
audits: {
|
||||
cls: { type: Object },
|
||||
si: { type: Object },
|
||||
fcp: { type: Object },
|
||||
lcp: { type: Object },
|
||||
tbt: { type: Object },
|
||||
},
|
||||
},
|
||||
required: false,
|
||||
},
|
||||
|
||||
httpStatusCode: { type: Number },
|
||||
errorMessage: { type: String, trim: true },
|
||||
ack: { type: Boolean, required: true, default: false },
|
||||
ackAt: { type: Date },
|
||||
ackBy: { type: Schema.Types.ObjectId, ref: "User_v2" },
|
||||
expiry: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
expires: 60 * 60 * 24 * 30,
|
||||
},
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
CheckSchema.index({ monitorId: 1, createdAt: -1 });
|
||||
CheckSchema.index({ status: 1 });
|
||||
CheckSchema.index({ status: 1, ack: 1 });
|
||||
CheckSchema.index({ ack: 1, ackAt: 1 });
|
||||
CheckSchema.index({ createdAt: -1 });
|
||||
|
||||
export const Check = mongoose.model<ICheck>("Check_v2", CheckSchema);
|
||||
@@ -0,0 +1,33 @@
|
||||
export { User } from "./auth/User.js";
|
||||
export type { IUser } from "./auth/User.js";
|
||||
export type { ITokenizedUser } from "./auth/User.js";
|
||||
export { Role } from "./auth/Role.js";
|
||||
export type { IRole } from "./auth/Role.js";
|
||||
export { connectDatabase, disconnectDatabase } from "../index.js";
|
||||
export { Monitor } from "./monitors/Monitor.js";
|
||||
export { MonitorStatuses } from "./monitors/Monitor.js";
|
||||
export type { IMonitor } from "./monitors/Monitor.js";
|
||||
export { Check } from "./checks/Check.js";
|
||||
export type {
|
||||
ICheck,
|
||||
ISystemInfo,
|
||||
ICaptureInfo,
|
||||
INetInfo,
|
||||
IDiskInfo,
|
||||
IHostInfo,
|
||||
IMemoryInfo,
|
||||
ICpuInfo,
|
||||
ILighthouseAudit,
|
||||
ITimingPhases,
|
||||
ILighthouseCategories,
|
||||
ILighthouseResult,
|
||||
ICheckLighthouseFields,
|
||||
} from "./checks/Check.js";
|
||||
export type { IMonitorStats } from "./monitors/MonitorStats.js";
|
||||
export { MonitorStats } from "./monitors/MonitorStats.js";
|
||||
export type { INotificationChannel } from "./notification-channel/NotificationChannel.js";
|
||||
export { NotificationChannel } from "./notification-channel/NotificationChannel.js";
|
||||
export type { IMaintenance } from "./maintenance/Maintenance.js";
|
||||
export { Maintenance } from "./maintenance/Maintenance.js";
|
||||
export type { IInvite } from "./invite/Invite.js";
|
||||
export { Invite } from "./invite/Invite.js";
|
||||
@@ -0,0 +1,43 @@
|
||||
import mongoose, { Schema, Document, Types } from "mongoose";
|
||||
|
||||
export interface IInvite extends Document {
|
||||
_id: Types.ObjectId;
|
||||
email: string;
|
||||
tokenHash: string;
|
||||
roles: Types.ObjectId[];
|
||||
createdBy: Types.ObjectId;
|
||||
updatedBy: Types.ObjectId;
|
||||
expiry: Date;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
const InviteSchema = new Schema<IInvite>(
|
||||
{
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
trim: true,
|
||||
lowercase: true,
|
||||
},
|
||||
roles: [
|
||||
{
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Role_v2",
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
tokenHash: { type: String, required: true, unique: true },
|
||||
expiry: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
expires: 60 * 60 * 24,
|
||||
},
|
||||
createdBy: { type: Schema.Types.ObjectId, ref: "User_v2", required: true },
|
||||
updatedBy: { type: Schema.Types.ObjectId, ref: "User_v2", required: true },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
export const Invite = mongoose.model<IInvite>("Invite_v2", InviteSchema);
|
||||
@@ -0,0 +1,39 @@
|
||||
import mongoose, { Schema, Document, Types } from "mongoose";
|
||||
|
||||
export interface IMaintenance extends Document {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
isActive: boolean;
|
||||
monitors: Types.ObjectId[];
|
||||
startTime: Date;
|
||||
endTime: Date;
|
||||
createdBy: Types.ObjectId;
|
||||
updatedBy: Types.ObjectId;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
const MaintenanceSchema = new Schema<IMaintenance>(
|
||||
{
|
||||
name: { type: String, required: true, trim: true },
|
||||
isActive: { type: Boolean, required: true, default: true },
|
||||
monitors: [
|
||||
{
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Monitor_v2",
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
startTime: { type: Date, required: true },
|
||||
endTime: { type: Date, required: true },
|
||||
createdBy: { type: Schema.Types.ObjectId, ref: "User_v2", required: true },
|
||||
updatedBy: { type: Schema.Types.ObjectId, ref: "User_v2", required: true },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
MaintenanceSchema.index({ isActive: 1 });
|
||||
MaintenanceSchema.index({ startTime: 1 });
|
||||
MaintenanceSchema.index({ endTime: 1 });
|
||||
|
||||
export const Maintenance = mongoose.model<IMaintenance>("Maintenance_v2", MaintenanceSchema);
|
||||
@@ -0,0 +1,96 @@
|
||||
import mongoose, { Schema, Document, Types } from "mongoose";
|
||||
import { Check, MonitorStats } from "../index.js";
|
||||
|
||||
export const MonitorTypes = ["http", "https", "ping", "infrastructure", "pagespeed"] as const;
|
||||
export type MonitorType = (typeof MonitorTypes)[number];
|
||||
|
||||
export const MonitorStatuses = ["up", "down", "paused", "initializing"] as const;
|
||||
export type MonitorStatus = (typeof MonitorStatuses)[number];
|
||||
export interface IMonitor extends Document {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
url: string;
|
||||
secret?: string;
|
||||
type: MonitorType;
|
||||
interval: number; // in ms
|
||||
isActive: boolean;
|
||||
status: MonitorStatus;
|
||||
n: number; // Number of consecutive successes required to change status
|
||||
lastCheckedAt?: Date;
|
||||
latestChecks: {
|
||||
status: MonitorStatus;
|
||||
responseTime: number;
|
||||
checkedAt: Date;
|
||||
}[];
|
||||
notificationChannels?: Types.ObjectId[];
|
||||
createdBy: Types.ObjectId;
|
||||
updatedBy: Types.ObjectId;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
const MonitorSchema = new Schema<IMonitor>(
|
||||
{
|
||||
name: { type: String, required: true, trim: true, maxlength: 100 },
|
||||
url: { type: String, required: true, trim: true },
|
||||
secret: { type: String, required: false },
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: MonitorTypes,
|
||||
},
|
||||
interval: { type: Number, required: true, default: 60000 },
|
||||
isActive: { type: Boolean, required: true, default: true },
|
||||
status: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "initializing",
|
||||
enum: MonitorStatuses,
|
||||
},
|
||||
n: { type: Number, required: true, default: 1 },
|
||||
lastCheckedAt: { type: Date },
|
||||
latestChecks: {
|
||||
type: [
|
||||
{
|
||||
status: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: MonitorStatuses,
|
||||
},
|
||||
responseTime: { type: Number, required: true },
|
||||
checkedAt: { type: Date, required: true },
|
||||
},
|
||||
],
|
||||
default: [],
|
||||
},
|
||||
notificationChannels: {
|
||||
type: [{ type: Schema.Types.ObjectId, ref: "NotificationChannel_v2" }],
|
||||
default: [],
|
||||
},
|
||||
|
||||
createdBy: { type: Schema.Types.ObjectId, ref: "User_v2", required: true },
|
||||
updatedBy: { type: Schema.Types.ObjectId, ref: "User_v2", required: true },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
MonitorSchema.pre("deleteOne", { document: true, query: false }, async function (next) {
|
||||
try {
|
||||
const monitorId = this._id;
|
||||
await Check.deleteMany({ monitorId });
|
||||
await MonitorStats.deleteMany({ monitorId });
|
||||
next();
|
||||
} catch (error: any) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
MonitorSchema.index({ isActive: 1 });
|
||||
MonitorSchema.index({ status: 1 });
|
||||
MonitorSchema.index({ type: 1 });
|
||||
MonitorSchema.index({ lastCheckedAt: 1 });
|
||||
MonitorSchema.index({ isActive: 1, status: 1 });
|
||||
MonitorSchema.index({ createdBy: 1 });
|
||||
MonitorSchema.index({ updatedBy: 1 });
|
||||
|
||||
export const Monitor = mongoose.model<IMonitor>("Monitor_v2", MonitorSchema);
|
||||
@@ -0,0 +1,77 @@
|
||||
import mongoose, { Schema, Document, Types } from "mongoose";
|
||||
import { MonitorStatus, MonitorStatuses } from "./Monitor.js";
|
||||
|
||||
export interface IMonitorStats extends mongoose.Document {
|
||||
monitorId: mongoose.Types.ObjectId;
|
||||
avgResponseTime: number;
|
||||
maxResponseTime: number;
|
||||
totalChecks: number;
|
||||
totalUpChecks: number;
|
||||
totalDownChecks: number;
|
||||
uptimePercentage: number;
|
||||
lastCheckTimestamp: number;
|
||||
lastResponseTime: number;
|
||||
timeOfLastFailure: number;
|
||||
currentStreak: number;
|
||||
currentStreakStatus: MonitorStatus;
|
||||
currentStreakStartedAt: number;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
const MonitorStatsSchema = new Schema<IMonitorStats>(
|
||||
{
|
||||
monitorId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: "Monitor_v2",
|
||||
immutable: true,
|
||||
index: true,
|
||||
},
|
||||
avgResponseTime: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
maxResponseTime: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
lastResponseTime: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
totalChecks: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
totalUpChecks: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
totalDownChecks: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
uptimePercentage: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
lastCheckTimestamp: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
timeOfLastFailure: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
currentStreak: { type: Number, required: false, default: 0 },
|
||||
currentStreakStatus: {
|
||||
type: String,
|
||||
required: false,
|
||||
enum: MonitorStatuses,
|
||||
},
|
||||
currentStreakStartedAt: { type: Number, required: false },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
export const MonitorStats = mongoose.model<IMonitorStats>("MonitorStats_v2", MonitorStatsSchema);
|
||||
@@ -0,0 +1,50 @@
|
||||
import mongoose, { Schema, Document, Types } from "mongoose";
|
||||
export const ChannelTypes = ["email", "slack", "discord", "webhook"] as const;
|
||||
export type ChannelType = (typeof ChannelTypes)[number];
|
||||
|
||||
export interface INotificationChannelConfig {
|
||||
url?: string; // For webhook, slack, discord
|
||||
emailAddress?: string; // For email
|
||||
}
|
||||
|
||||
export interface INotificationChannel {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
type: ChannelType;
|
||||
config: INotificationChannelConfig;
|
||||
isActive: boolean;
|
||||
createdBy: Types.ObjectId;
|
||||
updatedBy: Types.ObjectId;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
const NotificationChannelConfigSchema = new Schema<INotificationChannelConfig>(
|
||||
{
|
||||
url: { type: String, required: false },
|
||||
emailAddress: { type: String, required: false },
|
||||
},
|
||||
{ _id: false, strict: "throw" }
|
||||
);
|
||||
|
||||
const NotificationChannelSchema = new Schema<INotificationChannel>(
|
||||
{
|
||||
name: { type: String, required: true, trim: true },
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: ChannelTypes,
|
||||
},
|
||||
config: { type: NotificationChannelConfigSchema, required: true },
|
||||
isActive: { type: Boolean, required: true, default: true },
|
||||
createdBy: { type: Schema.Types.ObjectId, ref: "User_v2", required: true },
|
||||
updatedBy: { type: Schema.Types.ObjectId, ref: "User_v2", required: true },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
NotificationChannelSchema.index({ isActive: 1 });
|
||||
NotificationChannelSchema.index({ type: 1 });
|
||||
NotificationChannelSchema.index({ type: 1, isActive: 1 });
|
||||
|
||||
export const NotificationChannel = mongoose.model<INotificationChannel>("NotificationChannel_v2", NotificationChannelSchema);
|
||||
+2
-2
@@ -7,8 +7,8 @@ import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
import Logger from "./utils/logger.js";
|
||||
import SettingsService from "./service/system/settingsService.js";
|
||||
import AppSettings from "./db/models/AppSettings.js";
|
||||
import SettingsService from "./service/v1/system/settingsService.js";
|
||||
import AppSettings from "./db/v1/models/AppSettings.js";
|
||||
|
||||
const SERVICE_NAME = "Server";
|
||||
let logger;
|
||||
|
||||
@@ -149,10 +149,12 @@
|
||||
"statusPageByTeamId": "Got status pages by team id successfully",
|
||||
"httpNetworkError": "Network error",
|
||||
"httpNotJson": "Response data is not json",
|
||||
"httpExpectedValueFail": "Expected value did not match",
|
||||
"httpJsonPathError": "Failed to parse json data",
|
||||
"httpEmptyResult": "Result is empty",
|
||||
"httpMatchSuccess": "Response data match successfully",
|
||||
"httpMatchFail": "Failed to match response data",
|
||||
"httpJsonPathFail": "JSONPath did not match expected value",
|
||||
"webhookSendSuccess": "Webhook notification sent successfully",
|
||||
"telegramRequiresBotTokenAndChatId": "Telegram notifications require both botToken and chatId",
|
||||
"webhookUrlRequired": "Webhook URL is required",
|
||||
@@ -162,5 +164,18 @@
|
||||
"monitorDownAlert": "Downtime Alert: One of your monitors went offline.\n📌 Monitor: {monitorName}\n📅 Time: {time}\n⚠️ Status: DOWN\n📟 Status Code: {code}\n\u200B\n",
|
||||
"sendTestEmail": "Test email sent successfully",
|
||||
"errorForValidEmailAddress": "A valid recipient email address is required.",
|
||||
"testEmailSubject": "Test E-mail from Checkmate"
|
||||
"testEmailSubject": "Test E-mail from Checkmate",
|
||||
"discordNotification": {
|
||||
"monitor": "Monitor",
|
||||
"status": "Status",
|
||||
"statusCode": "Status Code",
|
||||
"time": "Time",
|
||||
"up": "UP",
|
||||
"down": "DOWN",
|
||||
"checkmate": "Checkmate",
|
||||
"url": "URL",
|
||||
"unknown": "Unknown",
|
||||
"uptimeAlert": "Uptime Alert: One of your monitors is back online",
|
||||
"downtimeAlert": "Downtime Alert: One of your monitors went offline"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { logger } from "../utils/logger.js";
|
||||
import ServiceRegistry from "../service/system/serviceRegistry.js";
|
||||
import StringService from "../service/system/stringService.js";
|
||||
import { logger } from "../../utils/logger.js";
|
||||
import ServiceRegistry from "../../service/v1/system/serviceRegistry.js";
|
||||
import StringService from "../../service/v1/system/stringService.js";
|
||||
|
||||
const handleErrors = (error, req, res, next) => {
|
||||
const status = error.status || 500;
|
||||
@@ -1,9 +1,9 @@
|
||||
import jwt from "jsonwebtoken";
|
||||
const TOKEN_PREFIX = "Bearer ";
|
||||
const SERVICE_NAME = "allowedRoles";
|
||||
import ServiceRegistry from "../service/system/serviceRegistry.js";
|
||||
import StringService from "../service/system/stringService.js";
|
||||
import SettingsService from "../service/system/settingsService.js";
|
||||
import ServiceRegistry from "../../service/v1/system/serviceRegistry.js";
|
||||
import StringService from "../../service/v1/system/stringService.js";
|
||||
import SettingsService from "../../service/v1/system/settingsService.js";
|
||||
|
||||
const isAllowed = (allowedRoles) => {
|
||||
return (req, res, next) => {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { logger } from "../utils/logger.js";
|
||||
import { logger } from "../../utils/logger.js";
|
||||
|
||||
const languageMiddleware = (stringService, translationService) => async (req, res, next) => {
|
||||
try {
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
import jwt from "jsonwebtoken";
|
||||
import ServiceRegistry from "../service/system/serviceRegistry.js";
|
||||
import SettingsService from "../service/system/settingsService.js";
|
||||
import StringService from "../service/system/stringService.js";
|
||||
import ServiceRegistry from "../../service/v1/system/serviceRegistry.js";
|
||||
import SettingsService from "../../service/v1/system/settingsService.js";
|
||||
import StringService from "../../service/v1/system/stringService.js";
|
||||
const SERVICE_NAME = "verifyJWT";
|
||||
const TOKEN_PREFIX = "Bearer ";
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import { logger } from "../utils/logger.js";
|
||||
import ServiceRegistry from "../service/system/serviceRegistry.js";
|
||||
import StringService from "../service/system/stringService.js";
|
||||
import { logger } from "../../utils/logger.js";
|
||||
import ServiceRegistry from "../../service/v1/system/serviceRegistry.js";
|
||||
import StringService from "../../service/v1/system/stringService.js";
|
||||
import { ObjectId } from "mongodb";
|
||||
|
||||
const SERVICE_NAME = "verifyOwnership";
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
const jwt = require("jsonwebtoken");
|
||||
const logger = require("../utils/logger");
|
||||
const logger = require("../../utils/logger.js");
|
||||
const SERVICE_NAME = "verifyAdmin";
|
||||
const TOKEN_PREFIX = "Bearer ";
|
||||
import ServiceRegistry from "../service/serviceRegistry.js";
|
||||
File renamed without changes.
@@ -0,0 +1,77 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import ApiError from "../../utils/ApiError.js";
|
||||
import { User, IUser, Role, IRole } from "../../db/v2/models/index.js";
|
||||
|
||||
const rolesCache = new Map<string, { roles: IRole[]; timestamp: number }>();
|
||||
// const CACHE_TTL = 30 * 60 * 1000; // 30 minutes
|
||||
const CACHE_TTL = 1; // 30 minutes
|
||||
const MAX_CACHE_SIZE = 1000;
|
||||
|
||||
const getCachedRoles = async (userId: string) => {
|
||||
if (rolesCache.size >= MAX_CACHE_SIZE) {
|
||||
const oldestKey = rolesCache.keys().next().value;
|
||||
if (!oldestKey) return null;
|
||||
rolesCache.delete(oldestKey);
|
||||
}
|
||||
|
||||
const cached = rolesCache.get(userId);
|
||||
|
||||
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
|
||||
return cached.roles;
|
||||
}
|
||||
|
||||
const user: IUser | null = await User.findById(userId);
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const roles = await Role.find({ _id: { $in: user.roles } });
|
||||
rolesCache.set(userId, { roles, timestamp: Date.now() });
|
||||
return roles;
|
||||
};
|
||||
|
||||
const hasPermission = (roles: IRole[], requiredPermissions: string[]) => {
|
||||
const userPermissions = [...new Set(roles.flatMap((role) => role.permissions))];
|
||||
|
||||
if (userPermissions.includes("*")) return true;
|
||||
|
||||
const matches = (requiredPermission: string, userPermission: string) => {
|
||||
if (userPermission === requiredPermission) return true;
|
||||
if (userPermission.endsWith(".*")) {
|
||||
const prefix = userPermission.slice(0, -2);
|
||||
return requiredPermission.startsWith(prefix + ".");
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
return requiredPermissions.every((requiredPermission) => {
|
||||
return userPermissions.some((userPermission) => matches(requiredPermission, userPermission));
|
||||
});
|
||||
};
|
||||
|
||||
const verifyPermission = (resourceActions: string[]) => {
|
||||
return async (req: Request, res: Response, next: NextFunction) => {
|
||||
const tokenizedUser = req.user;
|
||||
|
||||
if (!tokenizedUser) {
|
||||
throw new ApiError("No user", 400);
|
||||
}
|
||||
|
||||
const userId = tokenizedUser.sub;
|
||||
if (!userId) {
|
||||
throw new ApiError("No user ID", 400);
|
||||
}
|
||||
|
||||
const userRoles = await getCachedRoles(userId);
|
||||
if (!userRoles) {
|
||||
throw new ApiError("User roles not found", 400);
|
||||
}
|
||||
const allowed = hasPermission(userRoles, resourceActions);
|
||||
if (!allowed) {
|
||||
throw new ApiError("Insufficient permissions", 403);
|
||||
}
|
||||
next();
|
||||
};
|
||||
};
|
||||
|
||||
export { verifyPermission };
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import { decode } from "../../utils/JWTUtils.js";
|
||||
import ApiError from "../../utils/ApiError.js";
|
||||
const verifyToken = (req: Request, res: Response, next: NextFunction) => {
|
||||
const token = req.cookies.token;
|
||||
|
||||
if (!token) {
|
||||
const error = new ApiError("No token provided", 401);
|
||||
return next(error);
|
||||
}
|
||||
|
||||
try {
|
||||
const decoded = decode(token);
|
||||
req.user = decoded;
|
||||
next();
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
export { verifyToken };
|
||||
File renamed without changes.
@@ -1,9 +1,7 @@
|
||||
import { Router } from "express";
|
||||
import { verifyJWT } from "../middleware/verifyJWT.js";
|
||||
import { verifyOwnership } from "../middleware/verifyOwnership.js";
|
||||
import { isAllowed } from "../middleware/isAllowed.js";
|
||||
import { verifyJWT } from "../../middleware/v1/verifyJWT.js";
|
||||
import { isAllowed } from "../../middleware/v1/isAllowed.js";
|
||||
import multer from "multer";
|
||||
import User from "../db/models/User.js";
|
||||
|
||||
const upload = multer();
|
||||
|
||||
@@ -27,6 +25,7 @@ class AuthRoutes {
|
||||
this.router.get("/users", verifyJWT, isAllowed(["admin", "superadmin"]), this.authController.getAllUsers);
|
||||
this.router.get("/users/:userId", verifyJWT, isAllowed(["superadmin"]), this.authController.getUserById);
|
||||
this.router.put("/users/:userId", verifyJWT, isAllowed(["superadmin"]), this.authController.editUserById);
|
||||
this.router.put("/users/:userId/password", verifyJWT, isAllowed(["superadmin"]), this.authController.editUserPasswordById);
|
||||
|
||||
this.router.put("/user", verifyJWT, upload.single("profileImage"), this.authController.editUser);
|
||||
this.router.delete("/user", verifyJWT, this.authController.deleteUser);
|
||||
@@ -1,9 +1,6 @@
|
||||
import { Router } from "express";
|
||||
import { verifyOwnership } from "../middleware/verifyOwnership.js";
|
||||
import { verifyTeamAccess } from "../middleware/verifyTeamAccess.js";
|
||||
import { isAllowed } from "../middleware/isAllowed.js";
|
||||
import Monitor from "../db/models/Monitor.js";
|
||||
import Check from "../db/models/Check.js";
|
||||
|
||||
import { isAllowed } from "../../middleware/v1/isAllowed.js";
|
||||
|
||||
class CheckRoutes {
|
||||
constructor(checkController) {
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router } from "express";
|
||||
import { verifyJWT } from "../middleware/verifyJWT.js";
|
||||
import { isAllowed } from "../middleware/isAllowed.js";
|
||||
import { verifyJWT } from "../../middleware/v1/verifyJWT.js";
|
||||
import { isAllowed } from "../../middleware/v1/isAllowed.js";
|
||||
|
||||
class DiagnosticRoutes {
|
||||
constructor(diagnosticController) {
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router } from "express";
|
||||
import { verifyJWT } from "../middleware/verifyJWT.js";
|
||||
import { isAllowed } from "../middleware/isAllowed.js";
|
||||
import { verifyJWT } from "../../middleware/v1/verifyJWT.js";
|
||||
import { isAllowed } from "../../middleware/v1/isAllowed.js";
|
||||
|
||||
class InviteRoutes {
|
||||
constructor(inviteController) {
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Router } from "express";
|
||||
import { isAllowed } from "../middleware/isAllowed.js";
|
||||
import { isAllowed } from "../../middleware/v1/isAllowed.js";
|
||||
class LogRoutes {
|
||||
constructor(logController) {
|
||||
this.router = Router();
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { Router } from "express";
|
||||
import MaintenanceWindow from "../db/models/MaintenanceWindow.js";
|
||||
import MaintenanceWindow from "../../db/v1/models/MaintenanceWindow.js";
|
||||
class MaintenanceWindowRoutes {
|
||||
constructor(maintenanceWindowController) {
|
||||
this.router = Router();
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Router } from "express";
|
||||
import { isAllowed } from "../middleware/isAllowed.js";
|
||||
import { isAllowed } from "../../middleware/v1/isAllowed.js";
|
||||
import multer from "multer";
|
||||
import { fetchMonitorCertificate } from "../controllers/controllerUtils.js";
|
||||
import { fetchMonitorCertificate } from "../../controllers/v1/controllerUtils.js";
|
||||
const upload = multer({
|
||||
storage: multer.memoryStorage(), // Store file in memory as Buffer
|
||||
});
|
||||
File renamed without changes.
@@ -1,5 +1,5 @@
|
||||
import { Router } from "express";
|
||||
import { isAllowed } from "../middleware/isAllowed.js";
|
||||
import { isAllowed } from "../../middleware/v1/isAllowed.js";
|
||||
class QueueRoutes {
|
||||
constructor(queueController) {
|
||||
this.router = Router();
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Router } from "express";
|
||||
import { isAllowed } from "../middleware/isAllowed.js";
|
||||
import { isAllowed } from "../../middleware/v1/isAllowed.js";
|
||||
|
||||
class SettingsRoutes {
|
||||
constructor(settingsController) {
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Router } from "express";
|
||||
import { verifyJWT } from "../middleware/verifyJWT.js";
|
||||
import { verifyJWT } from "../../middleware/v1/verifyJWT.js";
|
||||
import multer from "multer";
|
||||
const upload = multer();
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Router } from "express";
|
||||
|
||||
import express from "express";
|
||||
import AuthController from "../../controllers/v2/AuthController.js";
|
||||
import { verifyToken } from "../../middleware/v2/VerifyToken.js";
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
class AuthRoutes {
|
||||
private controller: AuthController;
|
||||
private router: Router;
|
||||
constructor(authController: AuthController) {
|
||||
this.controller = authController;
|
||||
this.router = Router();
|
||||
this.initRoutes();
|
||||
}
|
||||
|
||||
initRoutes = () => {
|
||||
this.router.post("/register", this.controller.register);
|
||||
this.router.post("/register/invite/:token", this.controller.registerWithInvite);
|
||||
this.router.post("/login", this.controller.login);
|
||||
this.router.post("/logout", this.controller.logout);
|
||||
this.router.get("/me", verifyToken, this.controller.me);
|
||||
this.router.post("/cleanup", this.controller.cleanup);
|
||||
this.router.post("/cleanup-monitors", this.controller.cleanMonitors);
|
||||
};
|
||||
|
||||
getRouter() {
|
||||
return this.router;
|
||||
}
|
||||
}
|
||||
|
||||
export default AuthRoutes;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Router } from "express";
|
||||
import InviteController from "../../controllers/v2/InviteController.js";
|
||||
import { verifyToken } from "../../middleware/v2/VerifyToken.js";
|
||||
import { verifyPermission } from "../../middleware/v2/VerifyPermissions.js";
|
||||
|
||||
class InviteRoutes {
|
||||
private router;
|
||||
private controller;
|
||||
constructor(inviteController: InviteController) {
|
||||
this.router = Router();
|
||||
this.controller = inviteController;
|
||||
this.initRoutes();
|
||||
}
|
||||
|
||||
initRoutes = () => {
|
||||
this.router.post("/", verifyToken, verifyPermission(["invite.create"]), this.controller.create);
|
||||
|
||||
this.router.get("/", verifyToken, verifyPermission(["invite.view"]), this.controller.getAll);
|
||||
|
||||
this.router.get("/:token", verifyToken, verifyPermission(["invite.view"]), this.controller.get);
|
||||
|
||||
this.router.delete("/:id", verifyToken, verifyPermission(["invite.delete"]), this.controller.delete);
|
||||
};
|
||||
|
||||
getRouter() {
|
||||
return this.router;
|
||||
}
|
||||
}
|
||||
|
||||
export default InviteRoutes;
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Router } from "express";
|
||||
import MaintenanceController from "../../controllers/v2/MaintenanceController.js";
|
||||
import { verifyToken } from "../../middleware/v2/VerifyToken.js";
|
||||
import { verifyPermission } from "../../middleware/v2/VerifyPermissions.js";
|
||||
|
||||
class MaintenanceRoutes {
|
||||
private router;
|
||||
private controller;
|
||||
constructor(maintenanceController: MaintenanceController) {
|
||||
this.router = Router();
|
||||
this.controller = maintenanceController;
|
||||
this.initRoutes();
|
||||
}
|
||||
|
||||
initRoutes = () => {
|
||||
this.router.post("/", verifyToken, verifyPermission(["maintenance.create"]), this.controller.create);
|
||||
|
||||
this.router.get("/", verifyToken, verifyPermission(["maintenance.view"]), this.controller.getAll);
|
||||
|
||||
this.router.patch("/:id/active", verifyToken, verifyPermission(["maintenance.update"]), this.controller.toggleActive);
|
||||
|
||||
this.router.patch("/:id", verifyToken, verifyPermission(["maintenance.update"]), this.controller.update);
|
||||
|
||||
this.router.get("/:id", verifyToken, verifyPermission(["maintenance.view"]), this.controller.get);
|
||||
|
||||
this.router.delete("/:id", verifyToken, verifyPermission(["maintenance.delete"]), this.controller.delete);
|
||||
};
|
||||
|
||||
getRouter() {
|
||||
return this.router;
|
||||
}
|
||||
}
|
||||
|
||||
export default MaintenanceRoutes;
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Router } from "express";
|
||||
import MonitorController from "../../controllers/v2/MonitorController.js";
|
||||
import { verifyToken } from "../../middleware/v2/VerifyToken.js";
|
||||
import { verifyPermission } from "../../middleware/v2/VerifyPermissions.js";
|
||||
|
||||
class MonitorRoutes {
|
||||
private router;
|
||||
private controller;
|
||||
constructor(monitorController: MonitorController) {
|
||||
this.router = Router();
|
||||
this.controller = monitorController;
|
||||
this.initRoutes();
|
||||
}
|
||||
|
||||
initRoutes = () => {
|
||||
this.router.post("/", verifyToken, verifyPermission(["monitors.create"]), this.controller.create);
|
||||
|
||||
this.router.get("/", verifyToken, verifyPermission(["monitors.view"]), this.controller.getAll);
|
||||
|
||||
this.router.get("/:id/checks", verifyToken, verifyPermission(["monitors.view"]), this.controller.getChecks);
|
||||
|
||||
this.router.patch("/:id/active", verifyToken, verifyPermission(["monitors.update"]), this.controller.toggleActive);
|
||||
|
||||
this.router.get("/:id", verifyToken, verifyPermission(["monitors.view"]), this.controller.get);
|
||||
|
||||
this.router.patch("/:id", verifyToken, verifyPermission(["monitors.update"]), this.controller.update);
|
||||
|
||||
this.router.delete("/:id", verifyToken, verifyPermission(["monitors.delete"]), this.controller.delete);
|
||||
};
|
||||
|
||||
getRouter() {
|
||||
return this.router;
|
||||
}
|
||||
}
|
||||
|
||||
export default MonitorRoutes;
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Router } from "express";
|
||||
import NotificationController from "../../controllers/v2/NotificationChannelController.js";
|
||||
import { verifyToken } from "../../middleware/v2/VerifyToken.js";
|
||||
import { verifyPermission } from "../../middleware/v2/VerifyPermissions.js";
|
||||
|
||||
class NotificationChannelRoutes {
|
||||
private router;
|
||||
private controller;
|
||||
constructor(notificationController: NotificationController) {
|
||||
this.router = Router();
|
||||
this.controller = notificationController;
|
||||
this.initRoutes();
|
||||
}
|
||||
|
||||
initRoutes = () => {
|
||||
this.router.post("/", verifyToken, verifyPermission(["notifications.create"]), this.controller.create);
|
||||
|
||||
this.router.get("/", verifyToken, verifyPermission(["notifications.view"]), this.controller.getAll);
|
||||
|
||||
this.router.patch("/:id/active", verifyToken, verifyPermission(["notifications.update"]), this.controller.toggleActive);
|
||||
|
||||
this.router.patch("/:id", verifyToken, verifyPermission(["notifications.update"]), this.controller.update);
|
||||
|
||||
this.router.get("/:id", verifyToken, verifyPermission(["notifications.view"]), this.controller.get);
|
||||
|
||||
this.router.delete("/:id", verifyToken, verifyPermission(["notifications.delete"]), this.controller.delete);
|
||||
};
|
||||
|
||||
getRouter() {
|
||||
return this.router;
|
||||
}
|
||||
}
|
||||
|
||||
export default NotificationChannelRoutes;
|
||||
@@ -0,0 +1,24 @@
|
||||
import QueueController from "../../controllers/v2/QueueController.js";
|
||||
import { Router } from "express";
|
||||
|
||||
class QueueRoutes {
|
||||
private router;
|
||||
private controller;
|
||||
constructor(queueController: QueueController) {
|
||||
this.router = Router();
|
||||
this.controller = queueController;
|
||||
this.initRoutes();
|
||||
}
|
||||
|
||||
initRoutes() {
|
||||
this.router.get("/jobs", this.controller.getJobs);
|
||||
this.router.get("/metrics", this.controller.getMetrics);
|
||||
this.router.post("/flush", this.controller.flush);
|
||||
}
|
||||
|
||||
getRouter() {
|
||||
return this.router;
|
||||
}
|
||||
}
|
||||
|
||||
export default QueueRoutes;
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 602 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user