Merge pull request #1709 from Cihatata/i18n-support-backend

I18n support for server
This commit is contained in:
Alexander Holliday authored and GitHub committed 2025-02-11 09:02:24 -08:00
commit 8b1f32d827
27 files changed
+879 -371

No files matched your search

+21 -19
View File
@@ -8,7 +8,6 @@ import {
newPasswordValidation,
} from "../validation/joi.js";
import logger from "../utils/logger.js";
import { errorMessages, successMessages } from "../utils/messages.js";
import jwt from "jsonwebtoken";
import { getTokenFromHeaders, tokenType } from "../utils/utils.js";
import crypto from "crypto";
@@ -16,11 +15,12 @@ import { handleValidationError, handleError } from "./controllerUtils.js";
const SERVICE_NAME = "authController";
class AuthController {
constructor(db, settingsService, emailService, jobQueue) {
constructor(db, settingsService, emailService, jobQueue, stringService) {
this.db = db;
this.settingsService = settingsService;
this.emailService = emailService;
this.jobQueue = jobQueue;
this.stringService = stringService;
}
/**
@@ -85,7 +85,7 @@ class AuthController {
const newUser = await this.db.insertUser({ ...req.body }, req.file);
logger.info({
message: successMessages.AUTH_CREATE_USER,
message: this.stringService.authCreateUser,
service: SERVICE_NAME,
details: newUser._id,
});
@@ -116,7 +116,7 @@ class AuthController {
});
res.success({
msg: successMessages.AUTH_CREATE_USER,
msg: this.stringService.authCreateUser,
data: { user: newUser, token: token, refreshToken: refreshToken },
});
} catch (error) {
@@ -153,7 +153,7 @@ class AuthController {
// Compare password
const match = await user.comparePassword(password);
if (match !== true) {
const error = new Error(errorMessages.AUTH_INCORRECT_PASSWORD);
const error = new Error(this.stringService.authIncorrectPassword);
error.status = 401;
next(error);
return;
@@ -176,7 +176,7 @@ class AuthController {
userWithoutPassword.avatarImage = user.avatarImage;
return res.success({
msg: successMessages.AUTH_LOGIN_USER,
msg: this.stringService.authLoginUser,
data: {
user: userWithoutPassword,
token: token,
@@ -200,13 +200,14 @@ class AuthController {
* @throws {Error} If there is an error during the process such as any of the token is not received
*/
refreshAuthToken = async (req, res, next) => {
try {
// check for refreshToken
const refreshToken = req.headers["x-refresh-token"];
if (!refreshToken) {
// No refresh token provided
const error = new Error(errorMessages.NO_REFRESH_TOKEN);
const error = new Error(this.stringService.noRefreshToken);
error.status = 401;
error.service = SERVICE_NAME;
error.method = "refreshAuthToken";
@@ -221,8 +222,8 @@ class AuthController {
// Invalid or expired refresh token, trigger logout
const errorMessage =
refreshErr.name === "TokenExpiredError"
? errorMessages.EXPIRED_REFRESH_TOKEN
: errorMessages.INVALID_REFRESH_TOKEN;
? this.stringService.expiredAuthToken
: this.stringService.invalidAuthToken;
const error = new Error(errorMessage);
error.status = 401;
error.service = SERVICE_NAME;
@@ -243,7 +244,7 @@ class AuthController {
);
return res.success({
msg: successMessages.AUTH_TOKEN_REFRESHED,
msg: this.stringService.authTokenRefreshed,
data: { user: payloadData, token: newAuthToken, refreshToken: refreshToken },
});
} catch (error) {
@@ -265,6 +266,7 @@ class AuthController {
* @throws {Error} If there is an error during the process, especially if there is a validation error (422), the user is unauthorized (401), or the password is incorrect (403).
*/
editUser = async (req, res, next) => {
try {
await editUserParamValidation.validateAsync(req.params);
await editUserBodyValidation.validateAsync(req.body);
@@ -276,7 +278,7 @@ class AuthController {
// TODO is this neccessary any longer? Verify ownership middleware should handle this
if (req.params.userId !== req.user._id.toString()) {
const error = new Error(errorMessages.AUTH_UNAUTHORIZED);
const error = new Error(this.stringService.unauthorized);
error.status = 401;
error.service = SERVICE_NAME;
next(error);
@@ -300,7 +302,7 @@ class AuthController {
// If not a match, throw a 403
// 403 instead of 401 to avoid triggering axios interceptor
if (!match) {
const error = new Error(errorMessages.AUTH_INCORRECT_PASSWORD);
const error = new Error(this.stringService.authIncorrectPassword);
error.status = 403;
next(error);
return;
@@ -311,7 +313,7 @@ class AuthController {
const updatedUser = await this.db.updateUser(req, res);
res.success({
msg: successMessages.AUTH_UPDATE_USER,
msg: this.stringService.authUpdateUser,
data: updatedUser,
});
} catch (error) {
@@ -333,7 +335,7 @@ class AuthController {
const superAdminExists = await this.db.checkSuperadmin(req, res);
return res.success({
msg: successMessages.AUTH_ADMIN_EXISTS,
msg: this.stringService.authAdminExists,
data: superAdminExists,
});
} catch (error) {
@@ -379,7 +381,7 @@ class AuthController {
);
return res.success({
msg: successMessages.AUTH_CREATE_RECOVERY_TOKEN,
msg: this.stringService.authCreateRecoveryToken,
data: msgId,
});
} catch (error) {
@@ -410,7 +412,7 @@ class AuthController {
await this.db.validateRecoveryToken(req, res);
return res.success({
msg: successMessages.AUTH_VERIFY_RECOVERY_TOKEN,
msg: this.stringService.authVerifyRecoveryToken,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "validateRecoveryTokenController"));
@@ -443,7 +445,7 @@ class AuthController {
const token = this.issueToken(user._doc, tokenType.ACCESS_TOKEN, appSettings);
return res.success({
msg: successMessages.AUTH_RESET_PASSWORD,
msg: this.stringService.authResetPassword,
data: { user, token },
});
} catch (error) {
@@ -497,7 +499,7 @@ class AuthController {
await this.db.deleteUser(user._id);
return res.success({
msg: successMessages.AUTH_DELETE_USER,
msg: this.stringService.authDeleteUser,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "deleteUserController"));
@@ -509,7 +511,7 @@ class AuthController {
const allUsers = await this.db.getAllUsers(req, res);
return res.success({
msg: successMessages.AUTH_GET_ALL_USERS,
msg: this.stringService.authGetAllUsers,
data: allUsers,
});
} catch (error) {
+8 -8
View File
@@ -9,7 +9,6 @@ import {
deleteChecksByTeamIdParamValidation,
updateChecksTTLBodyValidation,
} from "../validation/joi.js";
import { successMessages } from "../utils/messages.js";
import jwt from "jsonwebtoken";
import { getTokenFromHeaders } from "../utils/utils.js";
import { handleValidationError, handleError } from "./controllerUtils.js";
@@ -17,9 +16,10 @@ import { handleValidationError, handleError } from "./controllerUtils.js";
const SERVICE_NAME = "checkController";
class CheckController {
constructor(db, settingsService) {
constructor(db, settingsService, stringService) {
this.db = db;
this.settingsService = settingsService;
this.stringService = stringService;
}
createCheck = async (req, res, next) => {
@@ -36,7 +36,7 @@ class CheckController {
const check = await this.db.createCheck(checkData);
return res.success({
msg: successMessages.CHECK_CREATE,
msg: this.stringService.checkCreate,
data: check,
});
} catch (error) {
@@ -57,7 +57,7 @@ class CheckController {
const result = await this.db.getChecksByMonitor(req);
return res.success({
msg: successMessages.CHECK_GET,
msg: this.stringService.checkGet,
data: result,
});
} catch (error) {
@@ -77,7 +77,7 @@ class CheckController {
const checkData = await this.db.getChecksByTeam(req);
return res.success({
msg: successMessages.CHECK_GET,
msg: this.stringService.checkGet,
data: checkData,
});
} catch (error) {
@@ -97,7 +97,7 @@ class CheckController {
const deletedCount = await this.db.deleteChecks(req.params.monitorId);
return res.success({
msg: successMessages.CHECK_DELETE,
msg: this.stringService.checkDelete,
data: { deletedCount },
});
} catch (error) {
@@ -117,7 +117,7 @@ class CheckController {
const deletedCount = await this.db.deleteChecksByTeamId(req.params.teamId);
return res.success({
msg: successMessages.CHECK_DELETE,
msg: this.stringService.checkDelete,
data: { deletedCount },
});
} catch (error) {
@@ -144,7 +144,7 @@ class CheckController {
await this.db.updateChecksTTL(teamId, ttl);
return res.success({
msg: successMessages.CHECK_UPDATE_TTL,
msg: this.stringService.checkUpdateTTL,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "updateTTL"));
+5 -4
View File
@@ -7,14 +7,15 @@ import logger from "../utils/logger.js";
import jwt from "jsonwebtoken";
import { handleError, handleValidationError } from "./controllerUtils.js";
import { getTokenFromHeaders } from "../utils/utils.js";
import { successMessages } from "../utils/messages.js";
const SERVICE_NAME = "inviteController";
class InviteController {
constructor(db, settingsService, emailService) {
constructor(db, settingsService, emailService, stringService) {
this.db = db;
this.settingsService = settingsService;
this.emailService = emailService;
this.stringService = stringService;
}
/**
@@ -66,7 +67,7 @@ class InviteController {
});
return res.success({
msg: successMessages.INVITE_ISSUED,
msg: this.stringService.inviteIssued,
data: inviteToken,
});
} catch (error) {
@@ -86,7 +87,7 @@ class InviteController {
const invite = await this.db.getInviteToken(req.body.token);
return res.success({
msg: successMessages.INVITE_VERIFIED,
msg: this.stringService.inviteVerified,
data: invite,
});
} catch (error) {
@@ -9,14 +9,15 @@ import {
} from "../validation/joi.js";
import jwt from "jsonwebtoken";
import { getTokenFromHeaders } from "../utils/utils.js";
import { successMessages } from "../utils/messages.js";
import { handleValidationError, handleError } from "./controllerUtils.js";
const SERVICE_NAME = "maintenanceWindowController";
class MaintenanceWindowController {
constructor(db, settingsService) {
constructor(db, settingsService, stringService) {
this.db = db;
this.settingsService = settingsService;
this.stringService = stringService;
}
createMaintenanceWindows = async (req, res, next) => {
@@ -45,7 +46,7 @@ class MaintenanceWindowController {
await Promise.all(dbTransactions);
return res.success({
msg: successMessages.MAINTENANCE_WINDOW_CREATE,
msg: this.stringService.maintenanceWindowCreate,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "createMaintenanceWindow"));
@@ -63,7 +64,7 @@ class MaintenanceWindowController {
const maintenanceWindow = await this.db.getMaintenanceWindowById(req.params.id);
return res.success({
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_ID,
msg: this.stringService.maintenanceWindowGetById,
data: maintenanceWindow,
});
} catch (error) {
@@ -89,7 +90,7 @@ class MaintenanceWindowController {
);
return res.success({
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_TEAM,
msg: this.stringService.maintenanceWindowGetByTeam,
data: maintenanceWindows,
});
} catch (error) {
@@ -111,7 +112,7 @@ class MaintenanceWindowController {
);
return res.success({
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_USER,
msg: this.stringService.maintenanceWindowGetByUser,
data: maintenanceWindows,
});
} catch (error) {
@@ -129,7 +130,7 @@ class MaintenanceWindowController {
try {
await this.db.deleteMaintenanceWindowById(req.params.id);
return res.success({
msg: successMessages.MAINTENANCE_WINDOW_DELETE,
msg: this.stringService.maintenanceWindowDelete,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "deleteMaintenanceWindow"));
@@ -150,7 +151,7 @@ class MaintenanceWindowController {
req.body
);
return res.success({
msg: successMessages.MAINTENANCE_WINDOW_EDIT,
msg: this.stringService.maintenanceWindowEdit,
data: editedMaintenanceWindow,
});
} catch (error) {
+20 -20
View File
@@ -14,7 +14,6 @@ import {
getHardwareDetailsByIdQueryValidation,
} from "../validation/joi.js";
import sslChecker from "ssl-checker";
import { successMessages } from "../utils/messages.js";
import jwt from "jsonwebtoken";
import { getTokenFromHeaders } from "../utils/utils.js";
import logger from "../utils/logger.js";
@@ -24,10 +23,11 @@ import seedDb from "../db/mongo/utils/seedDb.js";
const SERVICE_NAME = "monitorController";
class MonitorController {
constructor(db, settingsService, jobQueue) {
constructor(db, settingsService, jobQueue, stringService) {
this.db = db;
this.settingsService = settingsService;
this.jobQueue = jobQueue;
this.stringService = stringService;
}
/**
@@ -43,7 +43,7 @@ class MonitorController {
try {
const monitors = await this.db.getAllMonitors();
return res.success({
msg: successMessages.MONITOR_GET_ALL,
msg: this.stringService.monitorGetAll,
data: monitors,
});
} catch (error) {
@@ -64,7 +64,7 @@ class MonitorController {
try {
const monitors = await this.db.getAllMonitorsWithUptimeStats();
return res.success({
msg: successMessages.MONITOR_GET_ALL,
msg: this.stringService.monitorGetAll,
data: monitors,
});
} catch (error) {
@@ -76,7 +76,7 @@ class MonitorController {
try {
const monitor = await this.db.getUptimeDetailsById(req);
return res.success({
msg: successMessages.MONITOR_GET_BY_ID,
msg: this.stringService.monitorGetById,
data: monitor,
});
} catch (error) {
@@ -105,7 +105,7 @@ class MonitorController {
try {
const monitorStats = await this.db.getMonitorStatsById(req);
return res.success({
msg: successMessages.MONITOR_STATS_BY_ID,
msg: this.stringService.monitorStatsById,
data: monitorStats,
});
} catch (error) {
@@ -133,7 +133,7 @@ class MonitorController {
try {
const monitor = await this.db.getHardwareDetailsById(req);
return res.success({
msg: successMessages.MONITOR_GET_BY_ID,
msg: this.stringService.monitorGetById,
data: monitor,
});
} catch (error) {
@@ -154,7 +154,7 @@ class MonitorController {
const certificate = await fetchMonitorCertificate(sslChecker, monitor);
return res.success({
msg: successMessages.MONITOR_CERTIFICATE,
msg: this.stringService.monitorCertificate,
data: {
certificateDate: new Date(certificate.validTo),
},
@@ -187,7 +187,7 @@ class MonitorController {
try {
const monitor = await this.db.getMonitorById(req.params.monitorId);
return res.success({
msg: successMessages.MONITOR_GET_BY_ID,
msg: this.stringService.monitorGetById,
data: monitor,
});
} catch (error) {
@@ -231,7 +231,7 @@ class MonitorController {
// Add monitor to job queue
this.jobQueue.addJob(monitor._id, monitor);
return res.success({
msg: successMessages.MONITOR_CREATE,
msg: this.stringService.monitorCreate,
data: monitor,
});
} catch (error) {
@@ -309,7 +309,7 @@ class MonitorController {
stack: error.stack,
});
}
return res.success({ msg: successMessages.MONITOR_DELETE });
return res.success({ msg: this.stringService.monitorDelete });
} catch (error) {
next(handleError(error, SERVICE_NAME, "deleteMonitor"));
}
@@ -390,10 +390,10 @@ class MonitorController {
await Promise.all(
notifications &&
notifications.map(async (notification) => {
notification.monitorId = editedMonitor._id;
await this.db.createNotification(notification);
})
notifications.map(async (notification) => {
notification.monitorId = editedMonitor._id;
await this.db.createNotification(notification);
})
);
// Delete the old job(editedMonitor has the same ID as the old monitor)
@@ -401,7 +401,7 @@ class MonitorController {
// Add the new job back to the queue
await this.jobQueue.addJob(editedMonitor._id, editedMonitor);
return res.success({
msg: successMessages.MONITOR_EDIT,
msg: this.stringService.monitorEdit,
data: editedMonitor,
});
} catch (error) {
@@ -438,8 +438,8 @@ class MonitorController {
monitor.save();
return res.success({
msg: monitor.isActive
? successMessages.MONITOR_RESUME
: successMessages.MONITOR_PAUSE,
? this.stringService.monitorResume
: this.stringService.monitorPause,
data: monitor,
});
} catch (error) {
@@ -469,7 +469,7 @@ class MonitorController {
);
return res.success({
msg: successMessages.MONITOR_DEMO_ADDED,
msg: this.stringService.monitorDemoAdded,
data: demoMonitors.length,
});
} catch (error) {
@@ -488,7 +488,7 @@ class MonitorController {
try {
const monitors = await this.db.getMonitorsByTeamId(req);
return res.success({
msg: successMessages.MONITOR_GET_BY_TEAM_ID,
msg: this.stringService.monitorGetByTeamId,
data: monitors,
});
} catch (error) {
+6 -6
View File
@@ -1,18 +1,18 @@
import { handleError } from "./controllerUtils.js";
import { successMessages } from "../utils/messages.js";
const SERVICE_NAME = "JobQueueController";
class JobQueueController {
constructor(jobQueue) {
constructor(jobQueue, stringService) {
this.jobQueue = jobQueue;
this.stringService = stringService;
}
getMetrics = async (req, res, next) => {
try {
const metrics = await this.jobQueue.getMetrics();
res.success({
msg: successMessages.QUEUE_GET_METRICS,
msg: this.stringService.queueGetMetrics,
data: metrics,
});
} catch (error) {
@@ -25,7 +25,7 @@ class JobQueueController {
try {
const jobs = await this.jobQueue.getJobStats();
return res.success({
msg: successMessages.QUEUE_GET_METRICS,
msg: this.stringService.queueGetMetrics,
data: jobs,
});
} catch (error) {
@@ -38,7 +38,7 @@ class JobQueueController {
try {
await this.jobQueue.addJob(Math.random().toString(36).substring(7));
return res.success({
msg: successMessages.QUEUE_ADD_JOB,
msg: this.stringService.queueAddJob,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "addJob"));
@@ -50,7 +50,7 @@ class JobQueueController {
try {
await this.jobQueue.obliterate();
return res.success({
msg: successMessages.QUEUE_OBLITERATE,
msg: this.stringService.queueObliterate,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "obliterateQueue"));
+5 -4
View File
@@ -1,12 +1,13 @@
import { successMessages } from "../utils/messages.js";
import { updateAppSettingsBodyValidation } from "../validation/joi.js";
import { handleValidationError, handleError } from "./controllerUtils.js";
const SERVICE_NAME = "SettingsController";
class SettingsController {
constructor(db, settingsService) {
constructor(db, settingsService, stringService) {
this.db = db;
this.settingsService = settingsService;
this.stringService = stringService;
}
getAppSettings = async (req, res, next) => {
@@ -14,7 +15,7 @@ class SettingsController {
const settings = { ...(await this.settingsService.getSettings()) };
delete settings.jwtSecret;
return res.success({
msg: successMessages.GET_APP_SETTINGS,
msg: this.stringService.getAppSettings,
data: settings,
});
} catch (error) {
@@ -35,7 +36,7 @@ class SettingsController {
const updatedSettings = { ...(await this.settingsService.reloadSettings()) };
delete updatedSettings.jwtSecret;
return res.success({
msg: successMessages.UPDATE_APP_SETTINGS,
msg: this.stringService.updateAppSettings,
data: updatedSettings,
});
} catch (error) {
+9 -9
View File
@@ -5,13 +5,13 @@ import {
getStatusPageQueryValidation,
imageValidation,
} from "../validation/joi.js";
import { successMessages, errorMessages } from "../utils/messages.js";
const SERVICE_NAME = "statusPageController";
class StatusPageController {
constructor(db) {
constructor(db, stringService) {
this.db = db;
this.stringService = stringService;
}
createStatusPage = async (req, res, next) => {
@@ -26,7 +26,7 @@ class StatusPageController {
try {
const statusPage = await this.db.createStatusPage(req.body, req.file);
return res.success({
msg: successMessages.STATUS_PAGE_CREATE,
msg: this.stringService.statusPageCreate,
data: statusPage,
});
} catch (error) {
@@ -46,12 +46,12 @@ class StatusPageController {
try {
const statusPage = await this.db.updateStatusPage(req.body, req.file);
if (statusPage === null) {
const error = new Error(errorMessages.STATUS_PAGE_NOT_FOUND);
const error = new Error(this.stringService.statusPageNotFound);
error.status = 404;
throw error;
}
return res.success({
msg: successMessages.STATUS_PAGE_UPDATE,
msg: this.stringService.statusPageUpdate,
data: statusPage,
});
} catch (error) {
@@ -63,7 +63,7 @@ class StatusPageController {
try {
const statusPage = await this.db.getStatusPage();
return res.success({
msg: successMessages.STATUS_PAGE,
msg: this.stringService.statusPageByUrl,
data: statusPage,
});
} catch (error) {
@@ -83,7 +83,7 @@ class StatusPageController {
try {
const statusPage = await this.db.getStatusPageByUrl(req.params.url, req.query.type);
return res.success({
msg: successMessages.STATUS_PAGE_BY_URL,
msg: this.stringService.statusPageByUrl,
data: statusPage,
});
} catch (error) {
@@ -97,7 +97,7 @@ class StatusPageController {
const statusPages = await this.db.getStatusPagesByTeamId(teamId);
return res.success({
msg: successMessages.STATUS_PAGE_BY_TEAM_ID,
msg: this.stringService.statusPageByTeamId,
data: statusPages,
});
} catch (error) {
@@ -109,7 +109,7 @@ class StatusPageController {
try {
await this.db.deleteStatusPage(req.params.url);
return res.success({
msg: successMessages.STATUS_PAGE_DELETE,
msg: this.stringService.statusPageDelete,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "deleteStatusPage"));
+6 -3
View File
@@ -1,6 +1,7 @@
import InviteToken from "../../models/InviteToken.js";
import crypto from "crypto";
import { errorMessages } from "../../../utils/messages.js";
import ServiceRegistry from "../../../service/serviceRegistry.js";
import StringService from "../../../service/stringService.js";
const SERVICE_NAME = "inviteModule";
/**
@@ -42,12 +43,13 @@ const requestInviteToken = async (userData) => {
* @throws {Error} If the invite token is not found or there is another error.
*/
const getInviteToken = async (token) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
const invite = await InviteToken.findOne({
token,
});
if (invite === null) {
throw new Error(errorMessages.AUTH_INVITE_NOT_FOUND);
throw new Error(stringService.authInviteNotFound);
}
return invite;
} catch (error) {
@@ -68,12 +70,13 @@ const getInviteToken = async (token) => {
* @throws {Error} If the invite token is not found or there is another error.
*/
const getInviteTokenAndDelete = async (token) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
const invite = await InviteToken.findOneAndDelete({
token,
});
if (invite === null) {
throw new Error(errorMessages.AUTH_INVITE_NOT_FOUND);
throw new Error(stringService.authInviteNotFound);
}
return invite;
} catch (error) {
+81 -75
View File
@@ -3,9 +3,10 @@ import Check from "../../models/Check.js";
import PageSpeedCheck from "../../models/PageSpeedCheck.js";
import HardwareCheck from "../../models/HardwareCheck.js";
import DistributedUptimeCheck from "../../models/DistributedUptimeCheck.js";
import { errorMessages } from "../../../utils/messages.js";
import Notification from "../../models/Notification.js";
import { NormalizeData, NormalizeDataUptimeDetails } from "../../../utils/dataUtils.js";
import ServiceRegistry from "../../../service/serviceRegistry.js";
import StringService from "../../../service/stringService.js";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
@@ -312,7 +313,7 @@ const calculateGroupStats = (group) => {
avgResponseTime:
checksWithResponseTime.length > 0
? checksWithResponseTime.reduce((sum, check) => sum + check.responseTime, 0) /
checksWithResponseTime.length
checksWithResponseTime.length
: 0,
};
};
@@ -326,11 +327,12 @@ const calculateGroupStats = (group) => {
* @throws {Error}
*/
const getUptimeDetailsById = async (req) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
const { monitorId } = req.params;
const monitor = await Monitor.findById(monitorId);
if (monitor === null || monitor === undefined) {
throw new Error(errorMessages.DB_FIND_MONITOR_BY_ID(monitorId));
throw new Error(stringService.dbFindMonitorById(monitorId));
}
const { dateRange, normalize } = req.query;
@@ -373,7 +375,7 @@ const getDistributedUptimeDetailsById = async (req) => {
const { monitorId } = req.params;
const monitor = await Monitor.findById(monitorId);
if (monitor === null || monitor === undefined) {
throw new Error(errorMessages.DB_FIND_MONITOR_BY_ID(monitorId));
throw new Error(this.stringService.dbFindMonitorById(monitorId));
}
const { dateRange, normalize } = req.query;
@@ -419,13 +421,14 @@ const getDistributedUptimeDetailsById = async (req) => {
* @throws {Error}
*/
const getMonitorStatsById = async (req) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
const { monitorId } = req.params;
// Get monitor, if we can't find it, abort with error
const monitor = await Monitor.findById(monitorId);
if (monitor === null || monitor === undefined) {
throw new Error(errorMessages.DB_FIND_MONITOR_BY_ID(monitorId));
throw new Error(stringService.getDbFindMonitorById(monitorId));
}
// Get query params
@@ -516,10 +519,11 @@ const getHardwareDetailsById = async (req) => {
* @throws {Error}
*/
const getMonitorById = async (monitorId) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
const monitor = await Monitor.findById(monitorId);
if (monitor === null || monitor === undefined) {
const error = new Error(errorMessages.DB_FIND_MONITOR_BY_ID(monitorId));
const error = new Error(stringService.getDbFindMonitorById(monitorId));
error.status = 404;
throw error;
}
@@ -601,98 +605,98 @@ const getMonitorsByTeamId = async (req) => {
filteredMonitors: [
...(filter !== undefined
? [
{
$match: {
$or: [
{ name: { $regex: filter, $options: "i" } },
{ url: { $regex: filter, $options: "i" } },
],
},
{
$match: {
$or: [
{ name: { $regex: filter, $options: "i" } },
{ url: { $regex: filter, $options: "i" } },
],
},
]
},
]
: []),
{ $sort: sort },
{ $skip: skip },
...(rowsPerPage ? [{ $limit: rowsPerPage }] : []),
...(limit
? [
{
$lookup: {
from: "checks",
let: { monitorId: "$_id" },
pipeline: [
{
$match: {
$expr: { $eq: ["$monitorId", "$$monitorId"] },
},
{
$lookup: {
from: "checks",
let: { monitorId: "$_id" },
pipeline: [
{
$match: {
$expr: { $eq: ["$monitorId", "$$monitorId"] },
},
{ $sort: { createdAt: -1 } },
...(limit ? [{ $limit: limit }] : []),
],
as: "standardchecks",
},
},
{ $sort: { createdAt: -1 } },
...(limit ? [{ $limit: limit }] : []),
],
as: "standardchecks",
},
]
},
]
: []),
...(limit
? [
{
$lookup: {
from: "pagespeedchecks",
let: { monitorId: "$_id" },
pipeline: [
{
$match: {
$expr: { $eq: ["$monitorId", "$$monitorId"] },
},
{
$lookup: {
from: "pagespeedchecks",
let: { monitorId: "$_id" },
pipeline: [
{
$match: {
$expr: { $eq: ["$monitorId", "$$monitorId"] },
},
{ $sort: { createdAt: -1 } },
...(limit ? [{ $limit: limit }] : []),
],
as: "pagespeedchecks",
},
},
{ $sort: { createdAt: -1 } },
...(limit ? [{ $limit: limit }] : []),
],
as: "pagespeedchecks",
},
]
},
]
: []),
...(limit
? [
{
$lookup: {
from: "hardwarechecks",
let: { monitorId: "$_id" },
pipeline: [
{
$match: {
$expr: { $eq: ["$monitorId", "$$monitorId"] },
},
{
$lookup: {
from: "hardwarechecks",
let: { monitorId: "$_id" },
pipeline: [
{
$match: {
$expr: { $eq: ["$monitorId", "$$monitorId"] },
},
{ $sort: { createdAt: -1 } },
...(limit ? [{ $limit: limit }] : []),
],
as: "hardwarechecks",
},
},
{ $sort: { createdAt: -1 } },
...(limit ? [{ $limit: limit }] : []),
],
as: "hardwarechecks",
},
]
},
]
: []),
...(limit
? [
{
$lookup: {
from: "distributeduptimechecks",
let: { monitorId: "$_id" },
pipeline: [
{
$match: {
$expr: { $eq: ["$monitorId", "$$monitorId"] },
},
{
$lookup: {
from: "distributeduptimechecks",
let: { monitorId: "$_id" },
pipeline: [
{
$match: {
$expr: { $eq: ["$monitorId", "$$monitorId"] },
},
{ $sort: { createdAt: -1 } },
...(limit ? [{ $limit: limit }] : []),
],
as: "distributeduptimechecks",
},
},
{ $sort: { createdAt: -1 } },
...(limit ? [{ $limit: limit }] : []),
],
as: "distributeduptimechecks",
},
]
},
]
: []),
{
@@ -783,11 +787,13 @@ const createMonitor = async (req, res) => {
* @throws {Error}
*/
const deleteMonitor = async (req, res) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
const monitorId = req.params.monitorId;
try {
const monitor = await Monitor.findByIdAndDelete(monitorId);
if (!monitor) {
throw new Error(errorMessages.DB_FIND_MONITOR_BY_ID(monitorId));
throw new Error(stringService.getDbFindMonitorById(monitorId));
}
return monitor;
} catch (error) {
+7 -4
View File
@@ -1,7 +1,8 @@
import UserModel from "../../models/User.js";
import RecoveryToken from "../../models/RecoveryToken.js";
import crypto from "crypto";
import { errorMessages } from "../../../utils/messages.js";
import serviceRegistry from "../../../service/serviceRegistry.js";
import StringService from "../../../service/stringService.js";
const SERVICE_NAME = "recoveryModule";
@@ -31,6 +32,7 @@ const requestRecoveryToken = async (req, res) => {
};
const validateRecoveryToken = async (req, res) => {
const stringService = serviceRegistry.get(StringService.SERVICE_NAME);
try {
const candidateToken = req.body.recoveryToken;
const recoveryToken = await RecoveryToken.findOne({
@@ -39,7 +41,7 @@ const validateRecoveryToken = async (req, res) => {
if (recoveryToken !== null) {
return recoveryToken;
} else {
throw new Error(errorMessages.DB_TOKEN_NOT_FOUND);
throw new Error(stringService.dbTokenNotFound);
}
} catch (error) {
error.service = SERVICE_NAME;
@@ -49,6 +51,7 @@ const validateRecoveryToken = async (req, res) => {
};
const resetPassword = async (req, res) => {
const stringService = serviceRegistry.get(StringService.SERVICE_NAME);
try {
const newPassword = req.body.password;
@@ -57,12 +60,12 @@ const resetPassword = async (req, res) => {
const user = await UserModel.findOne({ email: recoveryToken.email });
if (user === null) {
throw new Error(errorMessages.DB_USER_NOT_FOUND);
throw new Error(stringService.dbUserNotFound);
}
const match = await user.comparePassword(newPassword);
if (match === true) {
throw new Error(errorMessages.DB_RESET_PASSWORD_BAD_MATCH);
throw new Error(stringService.dbResetPasswordBadMatch);
}
user.password = newPassword;
+10 -3
View File
@@ -1,10 +1,13 @@
import StatusPage from "../../models/StatusPage.js";
import { errorMessages } from "../../../utils/messages.js";
import { NormalizeData } from "../../../utils/dataUtils.js";
import ServiceRegistry from "../../../service/serviceRegistry.js";
import StringService from "../../../service/stringService.js";
const SERVICE_NAME = "statusPageModule";
const createStatusPage = async (statusPageData, image) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
const statusPage = new StatusPage({ ...statusPageData });
if (image) {
@@ -19,7 +22,7 @@ const createStatusPage = async (statusPageData, image) => {
if (error?.code === 11000) {
// Handle duplicate URL errors
error.status = 400;
error.message = errorMessages.STATUS_PAGE_URL_NOT_UNIQUE;
error.message = stringService.statusPageUrlNotUnique;
}
error.service = SERVICE_NAME;
error.method = "createStatusPage";
@@ -67,6 +70,8 @@ const getStatusPageByUrl = async (url, type) => {
};
const getStatusPagesByTeamId = async (teamId) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
const statusPages = await StatusPage.find({ teamId });
return statusPages;
@@ -78,6 +83,8 @@ const getStatusPagesByTeamId = async (teamId) => {
};
const getStatusPage = async (url) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
const statusPageQuery = await StatusPage.aggregate([
{ $match: { url: url } },
@@ -151,7 +158,7 @@ const getStatusPage = async (url) => {
},
]);
if (!statusPageQuery.length) {
const error = new Error(errorMessages.STATUS_PAGE_NOT_FOUND);
const error = new Error(stringService.statusPageNotFound);
error.status = 404;
throw error;
}
+10 -4
View File
@@ -1,10 +1,11 @@
import UserModel from "../../models/User.js";
import TeamModel from "../../models/Team.js";
import { errorMessages } from "../../../utils/messages.js";
import { GenerateAvatarImage } from "../../../utils/imageProcessing.js";
const DUPLICATE_KEY_CODE = 11000; // MongoDB error code for duplicate key
import { ParseBoolean } from "../../../utils/utils.js";
import ServiceRegistry from "../../../service/serviceRegistry.js";
import StringService from "../../../service/stringService.js";
const SERVICE_NAME = "userModule";
/**
@@ -20,6 +21,7 @@ const insertUser = async (
imageFile,
generateAvatarImage = GenerateAvatarImage
) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
if (imageFile) {
// 1. Save the full size image
@@ -50,7 +52,7 @@ const insertUser = async (
.select("-profileImage"); // .select() doesn't work with create, need to save then find
} catch (error) {
if (error.code === DUPLICATE_KEY_CODE) {
error.message = errorMessages.DB_USER_EXISTS;
error.message = stringService.dbUserExists;
}
error.service = SERVICE_NAME;
error.method = "insertUser";
@@ -70,12 +72,14 @@ const insertUser = async (
* @throws {Error}
*/
const getUserByEmail = async (email) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
// Need the password to be able to compare, removed .select()
// We can strip the hash before returning the user
const user = await UserModel.findOne({ email: email }).select("-profileImage");
if (!user) {
throw new Error(errorMessages.DB_USER_NOT_FOUND);
throw new Error(stringService.dbUserNotFound);
}
return user;
} catch (error) {
@@ -150,10 +154,12 @@ const updateUser = async (
* @throws {Error}
*/
const deleteUser = async (userId) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
const deletedUser = await UserModel.findByIdAndDelete(userId);
if (!deletedUser) {
throw new Error(errorMessages.DB_USER_NOT_FOUND);
throw new Error(stringService.dbUserNotFound);
}
return deletedUser;
} catch (error) {
+36 -13
View File
@@ -74,6 +74,10 @@ import MongoDB from "./db/mongo/MongoDB.js";
import IORedis from "ioredis";
import TranslationService from './service/translationService.js';
import languageMiddleware from './middleware/languageMiddleware.js';
import StringService from './service/stringService.js';
const SERVICE_NAME = "Server";
const SHUTDOWN_TIMEOUT = 1000;
let isShuttingDown = false;
@@ -156,11 +160,17 @@ const startApp = async () => {
}
}
// Create and Register Primary services
const translationService = new TranslationService(logger);
const stringService = new StringService(translationService);
ServiceRegistry.register(StringService.SERVICE_NAME, stringService);
// Create DB
const db = new MongoDB();
await db.connect();
// Create services
const networkService = new NetworkService(axios, ping, logger, http, Docker, net, stringService);
const settingsService = new SettingsService(AppSettings);
await settingsService.loadSettings();
const emailService = new EmailService(
@@ -172,16 +182,17 @@ const startApp = async () => {
nodemailer,
logger
);
const networkService = new NetworkService(axios, ping, logger, http, Docker, net);
const statusService = new StatusService(db, logger);
const notificationService = new NotificationService(emailService, db, logger);
const jobQueue = new JobQueue(
db,
statusService,
networkService,
notificationService,
settingsService,
stringService,
logger,
Queue,
Worker
@@ -195,6 +206,10 @@ const startApp = async () => {
ServiceRegistry.register(NetworkService.SERVICE_NAME, networkService);
ServiceRegistry.register(StatusService.SERVICE_NAME, statusService);
ServiceRegistry.register(NotificationService.SERVICE_NAME, notificationService);
ServiceRegistry.register(TranslationService.SERVICE_NAME, translationService);
await translationService.initialize();
server = app.listen(PORT, () => {
logger.info({ message: `server started on port:${PORT}` });
});
@@ -208,40 +223,50 @@ const startApp = async () => {
ServiceRegistry.get(MongoDB.SERVICE_NAME),
ServiceRegistry.get(SettingsService.SERVICE_NAME),
ServiceRegistry.get(EmailService.SERVICE_NAME),
ServiceRegistry.get(JobQueue.SERVICE_NAME)
ServiceRegistry.get(JobQueue.SERVICE_NAME),
ServiceRegistry.get(StringService.SERVICE_NAME)
);
const monitorController = new MonitorController(
ServiceRegistry.get(MongoDB.SERVICE_NAME),
ServiceRegistry.get(SettingsService.SERVICE_NAME),
ServiceRegistry.get(JobQueue.SERVICE_NAME)
ServiceRegistry.get(JobQueue.SERVICE_NAME),
ServiceRegistry.get(StringService.SERVICE_NAME)
);
const settingsController = new SettingsController(
ServiceRegistry.get(MongoDB.SERVICE_NAME),
ServiceRegistry.get(SettingsService.SERVICE_NAME)
ServiceRegistry.get(SettingsService.SERVICE_NAME),
ServiceRegistry.get(StringService.SERVICE_NAME)
);
const checkController = new CheckController(
ServiceRegistry.get(MongoDB.SERVICE_NAME),
ServiceRegistry.get(SettingsService.SERVICE_NAME)
ServiceRegistry.get(SettingsService.SERVICE_NAME),
ServiceRegistry.get(StringService.SERVICE_NAME)
);
const inviteController = new InviteController(
ServiceRegistry.get(MongoDB.SERVICE_NAME),
ServiceRegistry.get(SettingsService.SERVICE_NAME),
ServiceRegistry.get(EmailService.SERVICE_NAME)
ServiceRegistry.get(EmailService.SERVICE_NAME),
ServiceRegistry.get(StringService.SERVICE_NAME)
);
const maintenanceWindowController = new MaintenanceWindowController(
ServiceRegistry.get(MongoDB.SERVICE_NAME),
ServiceRegistry.get(SettingsService.SERVICE_NAME)
ServiceRegistry.get(SettingsService.SERVICE_NAME),
ServiceRegistry.get(StringService.SERVICE_NAME)
);
const queueController = new QueueController(ServiceRegistry.get(JobQueue.SERVICE_NAME));
const queueController = new QueueController(
ServiceRegistry.get(JobQueue.SERVICE_NAME),
ServiceRegistry.get(StringService.SERVICE_NAME)
);
const statusPageController = new StatusPageController(
ServiceRegistry.get(MongoDB.SERVICE_NAME)
ServiceRegistry.get(MongoDB.SERVICE_NAME),
ServiceRegistry.get(StringService.SERVICE_NAME)
);
const distributedUptimeController = new DistributedUptimeController(
@@ -267,12 +292,10 @@ const startApp = async () => {
// Init job queue
await jobQueue.initJobQueue();
// Middleware
app.use(
cors()
//We will add configuration later
);
app.use(cors());
app.use(express.json());
app.use(helmet());
app.use(languageMiddleware(stringService, translationService));
// Swagger UI
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(openApiSpec));
+148
View File
@@ -0,0 +1,148 @@
{
"dontHaveAccount": "Don't have account",
"email": "E-mail",
"forgotPassword": "Forgot Password",
"password": "password",
"signUp": "Sign up",
"submit": "Submit",
"title": "Title",
"continue": "Continue",
"enterEmail": "Enter your email",
"authLoginTitle": "Log In",
"authLoginEnterPassword": "Enter your password",
"commonPassword": "Password",
"commonBack": "Back",
"authForgotPasswordTitle": "Forgot password?",
"authForgotPasswordResetPassword": "Reset password",
"createPassword": "Create your password",
"createAPassword": "Create a password",
"authRegisterAlreadyHaveAccount": "Already have an account?",
"commonAppName": "BlueWave Uptime",
"authLoginEnterEmail": "Enter your email",
"authRegisterTitle": "Create an account",
"authRegisterStepOneTitle": "Create your account",
"authRegisterStepOneDescription": "Enter your details to get started",
"authRegisterStepTwoTitle": "Set up your profile",
"authRegisterStepTwoDescription": "Tell us more about yourself",
"authRegisterStepThreeTitle": "Almost done!",
"authRegisterStepThreeDescription": "Review your information",
"authForgotPasswordDescription": "No worries, we'll send you reset instructions.",
"authForgotPasswordSendInstructions": "Send instructions",
"authForgotPasswordBackTo": "Back to",
"authCheckEmailTitle": "Check your email",
"authCheckEmailDescription": "We sent a password reset link to {{email}}",
"authCheckEmailResendEmail": "Resend email",
"authCheckEmailBackTo": "Back to",
"goBackTo": "Go back to",
"authCheckEmailDidntReceiveEmail": "Didn't receive the email?",
"authCheckEmailClickToResend": "Click to resend",
"authSetNewPasswordTitle": "Set new password",
"authSetNewPasswordDescription": "Your new password must be different from previously used passwords.",
"authSetNewPasswordNewPassword": "New password",
"authSetNewPasswordConfirmPassword": "Confirm password",
"confirmPassword": "Confirm your password",
"authSetNewPasswordResetPassword": "Reset password",
"authSetNewPasswordBackTo": "Back to",
"authPasswordMustBeAtLeast": "Must be at least",
"authPasswordCharactersLong": "8 characters long",
"authPasswordMustContainAtLeast": "Must contain at least",
"authPasswordSpecialCharacter": "one special character",
"authPasswordOneNumber": "one number",
"authPasswordUpperCharacter": "one upper character",
"authPasswordLowerCharacter": "one lower character",
"authPasswordConfirmAndPassword": "Confirm password and password",
"authPasswordMustMatch": "must match",
"friendlyError": "Something went wrong...",
"unknownError": "An unknown error occurred",
"unauthorized": "Unauthorized access",
"authAdminExists": "Admin already exists",
"authInviteNotFound": "Invite not found",
"unknownService": "Unknown service",
"noAuthToken": "No auth token provided",
"invalidAuthToken": "Invalid auth token",
"expiredAuthToken": "Token expired",
"noRefreshToken": "No refresh token provided",
"invalidRefreshToken": "Invalid refresh token",
"expiredRefreshToken": "Refresh token expired",
"requestNewAccessToken": "Request new access token",
"invalidPayload": "Invalid payload",
"verifyOwnerNotFound": "Document not found",
"verifyOwnerUnauthorized": "Unauthorized access",
"insufficientPermissions": "Insufficient permissions",
"dbUserExists": "User already exists",
"dbUserNotFound": "User not found",
"dbTokenNotFound": "Token not found",
"dbResetPasswordBadMatch": "New password must be different from old password",
"dbFindMonitorById": "Monitor with id ${monitorId} not found",
"dbDeleteChecks": "No checks found for monitor with id ${monitorId}",
"authIncorrectPassword": "Incorrect password",
"authUnauthorized": "Unauthorized access",
"monitorGetById": "Monitor not found",
"monitorGetByUserId": "No monitors found for user",
"jobQueueWorkerClose": "Error closing worker",
"jobQueueDeleteJob": "Job not found in queue",
"jobQueueObliterate": "Error obliterating queue",
"pingCannotResolve": "No response",
"statusPageNotFound": "Status page not found",
"statusPageUrlNotUnique": "Status page url must be unique",
"dockerFail": "Failed to fetch Docker container information",
"dockerNotFound": "Docker container not found",
"portFail": "Failed to connect to port",
"alertCreate": "Alert created successfully",
"alertGetByUser": "Got alerts successfully",
"alertGetByMonitor": "Got alerts by Monitor successfully",
"alertGetById": "Got alert by Id successfully",
"alertEdit": "Alert edited successfully",
"alertDelete": "Alert deleted successfully",
"authCreateUser": "User created successfully",
"authLoginUser": "User logged in successfully",
"authLogoutUser": "User logged out successfully",
"authUpdateUser": "User updated successfully",
"authCreateRecoveryToken": "Recovery token created successfully",
"authVerifyRecoveryToken": "Recovery token verified successfully",
"authResetPassword": "Password reset successfully",
"authAdminCheck": "Admin check completed successfully",
"authDeleteUser": "User deleted successfully",
"authTokenRefreshed": "Auth token is refreshed",
"authGetAllUsers": "Got all users successfully",
"inviteIssued": "Invite sent successfully",
"inviteVerified": "Invite verified successfully",
"checkCreate": "Check created successfully",
"checkGet": "Got checks successfully",
"checkDelete": "Checks deleted successfully",
"checkUpdateTtl": "Checks TTL updated successfully",
"monitorGetAll": "Got all monitors successfully",
"monitorStatsById": "Got monitor stats by Id successfully",
"monitorGetByIdSuccess": "Got monitor by Id successfully",
"monitorGetByTeamId": "Got monitors by Team Id successfully",
"monitorGetByUserIdSuccess": "Got monitor for ${userId} successfully",
"monitorCreate": "Monitor created successfully",
"monitorDelete": "Monitor deleted successfully",
"monitorEdit": "Monitor edited successfully",
"monitorCertificate": "Got monitor certificate successfully",
"monitorDemoAdded": "Successfully added demo monitors",
"queueGetMetrics": "Got metrics successfully",
"queueAddJob": "Job added successfully",
"queueObliterate": "Queue obliterated",
"jobQueueDeleteJobSuccess": "Job removed successfully",
"jobQueuePauseJob": "Job paused successfully",
"jobQueueResumeJob": "Job resumed successfully",
"maintenanceWindowGetById": "Got Maintenance Window by Id successfully",
"maintenanceWindowCreate": "Maintenance Window created successfully",
"maintenanceWindowGetByTeam": "Got Maintenance Windows by Team successfully",
"maintenanceWindowDelete": "Maintenance Window deleted successfully",
"maintenanceWindowEdit": "Maintenance Window edited successfully",
"pingSuccess": "Success",
"getAppSettings": "Got app settings successfully",
"updateAppSettings": "Updated app settings successfully",
"statusPageByUrl": "Got status page by url successfully",
"statusPageCreate": "Status page created successfully",
"newTermsAdded": "New terms added to POEditor",
"dockerSuccess": "Docker container status fetched successfully",
"portSuccess": "Port connected successfully",
"monitorPause": "Monitor paused successfully",
"monitorResume": "Monitor resumed successfully",
"statusPageDelete": "Status page deleted successfully",
"statusPageUpdate": "Status page updated successfully",
"statusPageByTeamId": "Got status pages by team id successfully"
}
+5 -3
View File
@@ -1,10 +1,12 @@
import logger from "../utils/logger.js";
import { errorMessages } from "../utils/messages.js";
import ServiceRegistry from "../service/serviceRegistry.js";
import StringService from "../service/stringService.js";
const handleErrors = (error, req, res, next) => {
const status = error.status || 500;
const message = error.message || errorMessages.FRIENDLY_ERROR;
const service = error.service || errorMessages.UNKNOWN_SERVICE;
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
const message = error.message || stringService.friendlyError;
const service = error.service || stringService.unknownService;
logger.error({
message: message,
service: service,
+5 -5
View File
@@ -2,17 +2,17 @@ import jwt from "jsonwebtoken";
const TOKEN_PREFIX = "Bearer ";
const SERVICE_NAME = "allowedRoles";
import ServiceRegistry from "../service/serviceRegistry.js";
import StringService from "../service/stringService.js";
import SettingsService from "../service/settingsService.js";
import { errorMessages } from "../utils/messages.js";
const isAllowed = (allowedRoles) => {
return (req, res, next) => {
const token = req.headers["authorization"];
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
// If no token is pressent, return an error
if (!token) {
const error = new Error(errorMessages.NO_AUTH_TOKEN);
const error = new Error(stringService.noAuthToken);
error.status = 401;
error.service = SERVICE_NAME;
next(error);
@@ -21,7 +21,7 @@ const isAllowed = (allowedRoles) => {
// If the token is improperly formatted, return an error
if (!token.startsWith(TOKEN_PREFIX)) {
const error = new Error(errorMessages.INVALID_AUTH_TOKEN);
const error = new Error(stringService.invalidAuthToken);
error.status = 400;
error.service = SERVICE_NAME;
next(error);
@@ -41,7 +41,7 @@ const isAllowed = (allowedRoles) => {
next();
return;
} else {
const error = new Error(errorMessages.INSUFFICIENT_PERMISSIONS);
const error = new Error(stringService.insufficientPermissions);
error.status = 401;
error.service = SERVICE_NAME;
next(error);
+11
View File
@@ -0,0 +1,11 @@
const languageMiddleware = (stringService, translationService) => (req, res, next) => {
const acceptLanguage = req.headers['accept-language'] || 'en';
const language = acceptLanguage.split(',')[0].slice(0, 2).toLowerCase();
translationService.setLanguage(language);
stringService.setLanguage(language);
next();
};
export default languageMiddleware;
+10 -8
View File
@@ -1,7 +1,7 @@
import jwt from "jsonwebtoken";
import { errorMessages } from "../utils/messages.js";
import ServiceRegistry from "../service/serviceRegistry.js";
import SettingsService from "../service/settingsService.js";
import StringService from "../service/stringService.js";
const SERVICE_NAME = "verifyJWT";
const TOKEN_PREFIX = "Bearer ";
@@ -14,10 +14,11 @@ const TOKEN_PREFIX = "Bearer ";
* @returns {express.Response}
*/
const verifyJWT = (req, res, next) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
const token = req.headers["authorization"];
// Make sure a token is provided
if (!token) {
const error = new Error(errorMessages.NO_AUTH_TOKEN);
const error = new Error(stringService.noAuthToken);
error.status = 401;
error.service = SERVICE_NAME;
next(error);
@@ -25,7 +26,7 @@ const verifyJWT = (req, res, next) => {
}
// Make sure it is properly formatted
if (!token.startsWith(TOKEN_PREFIX)) {
const error = new Error(errorMessages.INVALID_AUTH_TOKEN); // Instantiate a new Error object for improperly formatted token
const error = new Error(stringService.invalidAuthToken); // Instantiate a new Error object for improperly formatted token
error.status = 400;
error.service = SERVICE_NAME;
error.method = "verifyJWT";
@@ -43,7 +44,7 @@ const verifyJWT = (req, res, next) => {
handleExpiredJwtToken(req, res, next);
} else {
// Invalid token (signature or token altered or other issue)
const errorMessage = errorMessages.INVALID_AUTH_TOKEN;
const errorMessage = stringService.invalidAuthToken;
return res.status(401).json({ success: false, msg: errorMessage });
}
} else {
@@ -55,12 +56,13 @@ const verifyJWT = (req, res, next) => {
};
function handleExpiredJwtToken(req, res, next) {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
// check for refreshToken
const refreshToken = req.headers["x-refresh-token"];
if (!refreshToken) {
// No refresh token provided
const error = new Error(errorMessages.NO_REFRESH_TOKEN);
const error = new Error(stringService.noRefreshToken);
error.status = 401;
error.service = SERVICE_NAME;
error.method = "handleExpiredJwtToken";
@@ -76,8 +78,8 @@ function handleExpiredJwtToken(req, res, next) {
// Invalid or expired refresh token, trigger logout
const errorMessage =
refreshErr.name === "TokenExpiredError"
? errorMessages.EXPIRED_REFRESH_TOKEN
: errorMessages.INVALID_REFRESH_TOKEN;
? stringService.expiredRefreshToken
: stringService.invalidRefreshToken;
const error = new Error(errorMessage);
error.status = 401;
error.service = SERVICE_NAME;
@@ -87,7 +89,7 @@ function handleExpiredJwtToken(req, res, next) {
// Refresh token is valid and unexpired, request for new access token
res.status(403).json({
success: false,
msg: errorMessages.REQUEST_NEW_ACCESS_TOKEN,
msg: stringService.requestNewAccessToken,
});
});
}
+7 -5
View File
@@ -1,8 +1,10 @@
import logger from "../utils/logger.js";
import { errorMessages } from "../utils/messages.js";
import ServiceRegistry from "../service/serviceRegistry.js";
import StringService from "../service/stringService.js";
const SERVICE_NAME = "verifyOwnership";
const verifyOwnership = (Model, paramName) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
return async (req, res, next) => {
const userId = req.user._id;
const documentId = req.params[paramName];
@@ -11,11 +13,11 @@ const verifyOwnership = (Model, paramName) => {
//If the document is not found, return a 404 error
if (!doc) {
logger.error({
message: errorMessages.VERIFY_OWNER_NOT_FOUND,
message: stringService.verifyOwnerNotFound,
service: SERVICE_NAME,
method: "verifyOwnership",
});
const error = new Error(errorMessages.VERIFY_OWNER_NOT_FOUND);
const error = new Error(stringService.verifyOwnerNotFound);
error.status = 404;
throw error;
}
@@ -23,7 +25,7 @@ const verifyOwnership = (Model, paramName) => {
// Special case for User model, as it will not have a `userId` field as other docs will
if (Model.modelName === "User") {
if (userId.toString() !== doc._id.toString()) {
const error = new Error(errorMessages.VERIFY_OWNER_UNAUTHORIZED);
const error = new Error(stringService.verifyOwnerUnauthorized);
error.status = 403;
throw error;
}
@@ -33,7 +35,7 @@ const verifyOwnership = (Model, paramName) => {
// If the userID does not match the document's userID, return a 403 error
if (userId.toString() !== doc.userId.toString()) {
const error = new Error(errorMessages.VERIFY_OWNER_UNAUTHORIZED);
const error = new Error(stringService.verifyOwnerUnauthorized);
error.status = 403;
throw error;
}
+8 -7
View File
@@ -2,9 +2,9 @@ const jwt = require("jsonwebtoken");
const logger = require("../utils/logger");
const SERVICE_NAME = "verifyAdmin";
const TOKEN_PREFIX = "Bearer ";
const { errorMessages } = require("../utils/messages");
import ServiceRegistry from "../service/serviceRegistry.js";
import SettingsService from "../service/settingsService.js";
import StringService from "../service/stringService.js";
/**
* Verifies the JWT token
* @function
@@ -14,10 +14,11 @@ import SettingsService from "../service/settingsService.js";
* @returns {express.Response}
*/
const verifySuperAdmin = (req, res, next) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
const token = req.headers["authorization"];
// Make sure a token is provided
if (!token) {
const error = new Error(errorMessages.NO_AUTH_TOKEN);
const error = new Error(stringService.noAuthToken);
error.status = 401;
error.service = SERVICE_NAME;
next(error);
@@ -25,7 +26,7 @@ const verifySuperAdmin = (req, res, next) => {
}
// Make sure it is properly formatted
if (!token.startsWith(TOKEN_PREFIX)) {
const error = new Error(errorMessages.INVALID_AUTH_TOKEN); // Instantiate a new Error object for improperly formatted token
const error = new Error(stringService.invalidAuthToken); // Instantiate a new Error object for improperly formatted token
error.status = 400;
error.service = SERVICE_NAME;
error.method = "verifySuperAdmin";
@@ -44,21 +45,21 @@ const verifySuperAdmin = (req, res, next) => {
service: SERVICE_NAME,
method: "verifySuperAdmin",
stack: err.stack,
details: errorMessages.INVALID_AUTH_TOKEN,
details: stringService.invalidAuthToken,
});
return res
.status(401)
.json({ success: false, msg: errorMessages.INVALID_AUTH_TOKEN });
.json({ success: false, msg: stringService.invalidAuthToken });
}
if (decoded.role.includes("superadmin") === false) {
logger.error({
message: errorMessages.INVALID_AUTH_TOKEN,
message: stringService.invalidAuthToken,
service: SERVICE_NAME,
method: "verifySuperAdmin",
stack: err.stack,
});
return res.status(401).json({ success: false, msg: errorMessages.UNAUTHORIZED });
return res.status(401).json({ success: false, msg: stringService.unauthorized });
}
next();
});
+12
View File
@@ -0,0 +1,12 @@
{
"ignore": [
"locales/*",
"*.log",
"node_modules/*"
],
"watch": [
"*.js",
"*.json"
],
"ext": "js,json"
}
+6 -4
View File
@@ -12,7 +12,7 @@ const QUEUE_LOOKUP = {
};
const getSchedulerId = (monitor) => `scheduler:${monitor.type}:${monitor._id}`;
import { successMessages, errorMessages } from "../utils/messages.js";
class NewJobQueue {
static SERVICE_NAME = SERVICE_NAME;
@@ -22,6 +22,7 @@ class NewJobQueue {
networkService,
notificationService,
settingsService,
stringService,
logger,
Queue,
Worker
@@ -44,6 +45,7 @@ class NewJobQueue {
this.settingsService = settingsService;
this.logger = logger;
this.Worker = Worker;
this.stringService = stringService;
QUEUE_NAMES.forEach((name) => {
this.queues[name] = new Queue(name, { connection });
@@ -455,7 +457,7 @@ class NewJobQueue {
if (wasDeleted === true) {
this.logger.info({
message: successMessages.JOB_QUEUE_DELETE_JOB,
message: this.stringService.jobQueueDeleteJob,
service: SERVICE_NAME,
method: "deleteJob",
details: `Deleted job ${monitor._id}`,
@@ -464,7 +466,7 @@ class NewJobQueue {
await this.scaleWorkers(workerStats, queue);
} else {
this.logger.error({
message: errorMessages.JOB_QUEUE_DELETE_JOB,
message: this.stringService.jobQueueDeleteJob,
service: SERVICE_NAME,
method: "deleteJob",
details: `Failed to delete job ${monitor._id}`,
@@ -587,7 +589,7 @@ class NewJobQueue {
const metrics = await this.getMetrics();
this.logger.info({
message: successMessages.JOB_QUEUE_OBLITERATE,
message: this.stringService.jobQueueObliterate,
service: SERVICE_NAME,
method: "obliterate",
details: metrics,
+10 -9
View File
@@ -1,4 +1,3 @@
import { errorMessages, successMessages } from "../utils/messages.js";
const SERVICE_NAME = "NetworkService";
const UPROCK_ENDPOINT = "https://api.uprock.com/checkmate/push";
@@ -13,7 +12,8 @@ const UPROCK_ENDPOINT = "https://api.uprock.com/checkmate/push";
*/
class NetworkService {
static SERVICE_NAME = SERVICE_NAME;
constructor(axios, ping, logger, http, Docker, net) {
constructor(axios, ping, logger, http, Docker, net, stringService) {
this.TYPE_PING = "ping";
this.TYPE_HTTP = "http";
this.TYPE_PAGESPEED = "pagespeed";
@@ -30,6 +30,7 @@ class NetworkService {
this.http = http;
this.Docker = Docker;
this.net = net;
this.stringService = stringService;
}
/**
@@ -87,13 +88,13 @@ class NetworkService {
if (error) {
pingResponse.status = false;
pingResponse.code = this.PING_ERROR;
pingResponse.message = errorMessages.PING_CANNOT_RESOLVE;
pingResponse.message = "No response";
return pingResponse;
}
pingResponse.code = 200;
pingResponse.status = response.alive;
pingResponse.message = successMessages.PING_SUCCESS;
pingResponse.message = "Success";
return pingResponse;
} catch (error) {
error.service = this.SERVICE_NAME;
@@ -240,7 +241,7 @@ class NetworkService {
const containers = await docker.listContainers({ all: true });
const containerExists = containers.some((c) => c.Id.startsWith(job.data.url));
if (!containerExists) {
throw new Error(errorMessages.DOCKER_NOT_FOUND);
throw new Error(this.stringService.dockerNotFound);
}
const container = docker.getContainer(job.data.url);
@@ -257,12 +258,12 @@ class NetworkService {
if (error) {
dockerResponse.status = false;
dockerResponse.code = error.statusCode || this.NETWORK_ERROR;
dockerResponse.message = error.reason || errorMessages.DOCKER_FAIL;
dockerResponse.message = error.reason || "Failed to fetch Docker container information";
return dockerResponse;
}
dockerResponse.status = response?.State?.Status === "running" ? true : false;
dockerResponse.code = 200;
dockerResponse.message = successMessages.DOCKER_SUCCESS;
dockerResponse.message = "Docker container status fetched successfully";
return dockerResponse;
} catch (error) {
error.service = this.SERVICE_NAME;
@@ -310,13 +311,13 @@ class NetworkService {
if (error) {
portResponse.status = false;
portResponse.code = this.NETWORK_ERROR;
portResponse.message = errorMessages.PORT_FAIL;
portResponse.message = this.stringService.portFail;
return portResponse;
}
portResponse.status = response.success;
portResponse.code = 200;
portResponse.message = successMessages.PORT_SUCCESS;
portResponse.message = this.stringService.portSuccess;
return portResponse;
} catch (error) {
error.service = this.SERVICE_NAME;
+334
View File
@@ -0,0 +1,334 @@
class StringService {
static SERVICE_NAME = "StringService";
constructor(translationService) {
if (StringService.instance) {
return StringService.instance;
}
this.translationService = translationService;
this._language = 'en'; // default language
StringService.instance = this;
}
setLanguage(language) {
this._language = language;
}
get language() {
return this._language;
}
// Auth Messages
get dontHaveAccount() {
return this.translationService.getTranslation('dontHaveAccount');
}
get email() {
return this.translationService.getTranslation('email');
}
get forgotPassword() {
return this.translationService.getTranslation('forgotPassword');
}
get password() {
return this.translationService.getTranslation('password');
}
get signUp() {
return this.translationService.getTranslation('signUp');
}
get submit() {
return this.translationService.getTranslation('submit');
}
get title() {
return this.translationService.getTranslation('title');
}
get continue() {
return this.translationService.getTranslation('continue');
}
get enterEmail() {
return this.translationService.getTranslation('enterEmail');
}
get authLoginTitle() {
return this.translationService.getTranslation('authLoginTitle');
}
get authLoginEnterPassword() {
return this.translationService.getTranslation('authLoginEnterPassword');
}
get commonPassword() {
return this.translationService.getTranslation('commonPassword');
}
get commonBack() {
return this.translationService.getTranslation('commonBack');
}
get authForgotPasswordTitle() {
return this.translationService.getTranslation('authForgotPasswordTitle');
}
get authForgotPasswordResetPassword() {
return this.translationService.getTranslation('authForgotPasswordResetPassword');
}
get createPassword() {
return this.translationService.getTranslation('createPassword');
}
get createAPassword() {
return this.translationService.getTranslation('createAPassword');
}
get authRegisterAlreadyHaveAccount() {
return this.translationService.getTranslation('authRegisterAlreadyHaveAccount');
}
get commonAppName() {
return this.translationService.getTranslation('commonAppName');
}
get authLoginEnterEmail() {
return this.translationService.getTranslation('authLoginEnterEmail');
}
get authRegisterTitle() {
return this.translationService.getTranslation('authRegisterTitle');
}
get monitorGetAll() {
return this.translationService.getTranslation('monitorGetAll');
}
get monitorGetById() {
return this.translationService.getTranslation('monitorGetById');
}
get monitorCreate() {
return this.translationService.getTranslation('monitorCreate');
}
get monitorEdit() {
return this.translationService.getTranslation('monitorEdit');
}
get monitorDelete() {
return this.translationService.getTranslation('monitorDelete');
}
get monitorPause() {
return this.translationService.getTranslation('monitorPause');
}
get monitorResume() {
return this.translationService.getTranslation('monitorResume');
}
get monitorDemoAdded() {
return this.translationService.getTranslation('monitorDemoAdded');
}
get monitorStatsById() {
return this.translationService.getTranslation('monitorStatsById');
}
get monitorCertificate() {
return this.translationService.getTranslation('monitorCertificate');
}
// Maintenance Window Messages
get maintenanceWindowCreate() {
return this.translationService.getTranslation('maintenanceWindowCreate');
}
get maintenanceWindowGetById() {
return this.translationService.getTranslation('maintenanceWindowGetById');
}
get maintenanceWindowGetByTeam() {
return this.translationService.getTranslation('maintenanceWindowGetByTeam');
}
get maintenanceWindowDelete() {
return this.translationService.getTranslation('maintenanceWindowDelete');
}
get maintenanceWindowEdit() {
return this.translationService.getTranslation('maintenanceWindowEdit');
}
// Error Messages
get unknownError() {
return this.translationService.getTranslation('unknownError');
}
get friendlyError() {
return this.translationService.getTranslation('friendlyError');
}
get authIncorrectPassword() {
return this.translationService.getTranslation('authIncorrectPassword');
}
get unauthorized() {
return this.translationService.getTranslation('unauthorized');
}
get authAdminExists() {
return this.translationService.getTranslation('authAdminExists');
}
get authInviteNotFound() {
return this.translationService.getTranslation('authInviteNotFound');
}
get unknownService() {
return this.translationService.getTranslation('unknownService');
}
get noAuthToken() {
return this.translationService.getTranslation('noAuthToken');
}
get invalidAuthToken() {
return this.translationService.getTranslation('invalidAuthToken');
}
get expiredAuthToken() {
return this.translationService.getTranslation('expiredAuthToken');
}
// Queue Messages
get queueGetMetrics() {
return this.translationService.getTranslation('queueGetMetrics');
}
get queueAddJob() {
return this.translationService.getTranslation('queueAddJob');
}
get queueObliterate() {
return this.translationService.getTranslation('queueObliterate');
}
// Job Queue Messages
get jobQueueDeleteJobSuccess() {
return this.translationService.getTranslation('jobQueueDeleteJobSuccess');
}
get jobQueuePauseJob() {
return this.translationService.getTranslation('jobQueuePauseJob');
}
get jobQueueResumeJob() {
return this.translationService.getTranslation('jobQueueResumeJob');
}
// Status Page Messages
get statusPageByUrl() {
return this.translationService.getTranslation('statusPageByUrl');
}
get statusPageCreate() {
return this.translationService.getTranslation('statusPageCreate');
}
get statusPageDelete() {
return this.translationService.getTranslation('statusPageDelete');
}
get statusPageUpdate() {
return this.translationService.getTranslation('statusPageUpdate');
}
get statusPageNotFound() {
return this.translationService.getTranslation('statusPageNotFound');
}
get statusPageByTeamId() {
return this.translationService.getTranslation('statusPageByTeamId');
}
get statusPageUrlNotUnique() {
return this.translationService.getTranslation('statusPageUrlNotUnique');
}
// Docker Messages
get dockerFail() {
return this.translationService.getTranslation('dockerFail');
}
get dockerNotFound() {
return this.translationService.getTranslation('dockerNotFound');
}
get dockerSuccess() {
return this.translationService.getTranslation('dockerSuccess');
}
// Port Messages
get portFail() {
return this.translationService.getTranslation('portFail');
}
get portSuccess() {
return this.translationService.getTranslation('portSuccess');
}
// Alert Messages
get alertCreate() {
return this.translationService.getTranslation('alertCreate');
}
get alertGetByUser() {
return this.translationService.getTranslation('alertGetByUser');
}
get alertGetByMonitor() {
return this.translationService.getTranslation('alertGetByMonitor');
}
get alertGetById() {
return this.translationService.getTranslation('alertGetById');
}
get alertEdit() {
return this.translationService.getTranslation('alertEdit');
}
get alertDelete() {
return this.translationService.getTranslation('alertDelete');
}
getDeletedCount(count) {
return this.translationService.getTranslation('deletedCount')
.replace('{count}', count);
}
get pingSuccess() {
return this.translationService.getTranslation('pingSuccess');
}
get getAppSettings() {
return this.translationService.getTranslation('getAppSettings');
}
get updateAppSettings() {
return this.translationService.getTranslation('updateAppSettings');
}
getDbFindMonitorById(monitorId) {
return this.translationService.getTranslation('dbFindMonitorById')
.replace('${monitorId}', monitorId);
}
}
export default StringService;
+90
View File
@@ -0,0 +1,90 @@
import fs from 'fs';
import path from 'path';
class TranslationService {
static SERVICE_NAME = 'TranslationService';
constructor(logger) {
this.logger = logger;
this.translations = {};
this._language = 'en';
this.localesDir = path.join(process.cwd(), 'locales');
}
setLanguage(language) {
this._language = language;
}
get language() {
return this._language;
}
async initialize() {
try {
await this.loadFromFiles();
} catch (error) {
this.logger.error({
message: error.message,
service: 'TranslationService',
method: 'initialize',
stack: error.stack
});
}
}
async loadFromFiles() {
try {
if (!fs.existsSync(this.localesDir)) {
return false;
}
const files = fs.readdirSync(this.localesDir).filter(file => file.endsWith('.json'));
if (files.length === 0) {
return false;
}
for (const file of files) {
const language = file.replace('.json', '');
const filePath = path.join(this.localesDir, file);
const content = fs.readFileSync(filePath, 'utf8');
this.translations[language] = JSON.parse(content);
}
this.logger.info({
message: 'Translations loaded from files successfully',
service: 'TranslationService',
method: 'loadFromFiles'
});
return true;
} catch (error) {
this.logger.error({
message: error.message,
service: 'TranslationService',
method: 'loadFromFiles',
stack: error.stack
});
return false;
}
}
getTranslation(key) {
let language = this._language;
try {
return this.translations[language]?.[key] || this.translations['en']?.[key] || key;
} catch (error) {
this.logger.error({
message: error.message,
service: 'TranslationService',
method: 'getTranslation',
stack: error.stack
});
return key;
}
}
}
export default TranslationService;
-150
View File
@@ -1,150 +0,0 @@
const errorMessages = {
// General Errors:
FRIENDLY_ERROR: "Something went wrong...",
UNKNOWN_ERROR: "An unknown error occurred",
// Auth Controller
UNAUTHORIZED: "Unauthorized access",
AUTH_ADMIN_EXISTS: "Admin already exists",
AUTH_INVITE_NOT_FOUND: "Invite not found",
//Error handling middleware
UNKNOWN_SERVICE: "Unknown service",
NO_AUTH_TOKEN: "No auth token provided",
INVALID_AUTH_TOKEN: "Invalid auth token",
EXPIRED_AUTH_TOKEN: "Token expired",
NO_REFRESH_TOKEN: "No refresh token provided",
INVALID_REFRESH_TOKEN: "Invalid refresh token",
EXPIRED_REFRESH_TOKEN: "Refresh token expired",
REQUEST_NEW_ACCESS_TOKEN: "Request new access token",
//Payload
INVALID_PAYLOAD: "Invalid payload",
//Ownership Middleware
VERIFY_OWNER_NOT_FOUND: "Document not found",
VERIFY_OWNER_UNAUTHORIZED: "Unauthorized access",
//Permissions Middleware
INSUFFICIENT_PERMISSIONS: "Insufficient permissions",
//DB Errors
DB_USER_EXISTS: "User already exists",
DB_USER_NOT_FOUND: "User not found",
DB_TOKEN_NOT_FOUND: "Token not found",
DB_RESET_PASSWORD_BAD_MATCH: "New password must be different from old password",
DB_FIND_MONITOR_BY_ID: (monitorId) => `Monitor with id ${monitorId} not found`,
DB_DELETE_CHECKS: (monitorId) => `No checks found for monitor with id ${monitorId}`,
//Auth errors
AUTH_INCORRECT_PASSWORD: "Incorrect password",
AUTH_UNAUTHORIZED: "Unauthorized access",
// Monitor Errors
MONITOR_GET_BY_ID: "Monitor not found",
MONITOR_GET_BY_USER_ID: "No monitors found for user",
// Job Queue Errors
JOB_QUEUE_WORKER_CLOSE: "Error closing worker",
JOB_QUEUE_DELETE_JOB: "Job not found in queue",
JOB_QUEUE_OBLITERATE: "Error obliterating queue",
// PING Operations
PING_CANNOT_RESOLVE: "No response",
// Status Page Errors
STATUS_PAGE_NOT_FOUND: "Status page not found",
STATUS_PAGE_URL_NOT_UNIQUE: "Status page url must be unique",
// Docker
DOCKER_FAIL: "Failed to fetch Docker container information",
DOCKER_NOT_FOUND: "Docker container not found",
// Port
PORT_FAIL: "Failed to connect to port",
};
const successMessages = {
//Alert Controller
ALERT_CREATE: "Alert created successfully",
ALERT_GET_BY_USER: "Got alerts successfully",
ALERT_GET_BY_MONITOR: "Got alerts by Monitor successfully",
ALERT_GET_BY_ID: "Got alert by Id successfully",
ALERT_EDIT: "Alert edited successfully",
ALERT_DELETE: "Alert deleted successfully",
// Auth Controller
AUTH_CREATE_USER: "User created successfully",
AUTH_LOGIN_USER: "User logged in successfully",
AUTH_LOGOUT_USER: "User logged out successfully",
AUTH_UPDATE_USER: "User updated successfully",
AUTH_CREATE_RECOVERY_TOKEN: "Recovery token created successfully",
AUTH_VERIFY_RECOVERY_TOKEN: "Recovery token verified successfully",
AUTH_RESET_PASSWORD: "Password reset successfully",
AUTH_ADMIN_CHECK: "Admin check completed successfully",
AUTH_DELETE_USER: "User deleted successfully",
AUTH_TOKEN_REFRESHED: "Auth token is refreshed",
AUTH_GET_ALL_USERS: "Got all users successfully",
// Invite Controller
INVITE_ISSUED: "Invite sent successfully",
INVITE_VERIFIED: "Invite verified successfully",
// Check Controller
CHECK_CREATE: "Check created successfully",
CHECK_GET: "Got checks successfully",
CHECK_DELETE: "Checks deleted successfully",
CHECK_UPDATE_TTL: "Checks TTL updated successfully",
//Monitor Controller
MONITOR_GET_ALL: "Got all monitors successfully",
MONITOR_STATS_BY_ID: "Got monitor stats by Id successfully",
MONITOR_GET_BY_ID: "Got monitor by Id successfully",
MONITOR_GET_BY_TEAM_ID: "Got monitors by Team Id successfully",
MONITOR_GET_BY_USER_ID: (userId) => `Got monitor for ${userId} successfully"`,
MONITOR_CREATE: "Monitor created successfully",
MONITOR_DELETE: "Monitor deleted successfully",
MONITOR_EDIT: "Monitor edited successfully",
MONITOR_CERTIFICATE: "Got monitor certificate successfully",
MONITOR_DEMO_ADDED: "Successfully added demo monitors",
// Queue Controller
QUEUE_GET_METRICS: "Got metrics successfully",
QUEUE_ADD_JOB: "Job added successfully",
QUEUE_OBLITERATE: "Queue obliterated",
//Job Queue
JOB_QUEUE_DELETE_JOB: "Job removed successfully",
JOB_QUEUE_OBLITERATE: "Queue OBLITERATED!!!",
JOB_QUEUE_PAUSE_JOB: "Job paused successfully",
JOB_QUEUE_RESUME_JOB: "Job resumed successfully",
//Maintenance Window Controller
MAINTENANCE_WINDOW_GET_BY_ID: "Got Maintenance Window by Id successfully",
MAINTENANCE_WINDOW_CREATE: "Maintenance Window created successfully",
MAINTENANCE_WINDOW_GET_BY_TEAM: "Got Maintenance Windows by Team successfully",
MAINTENANCE_WINDOW_DELETE: "Maintenance Window deleted successfully",
MAINTENANCE_WINDOW_EDIT: "Maintenance Window edited successfully",
//Ping Operations
PING_SUCCESS: "Success",
// App Settings
GET_APP_SETTINGS: "Got app settings successfully",
UPDATE_APP_SETTINGS: "Updated app settings successfully",
// Status Page
STATUS_PAGE_BY_URL: "Got status page by url successfully",
STATUS_PAGE: "Got status page successfully",
STATUS_PAGE_CREATE: "Status page created successfully",
STATUS_PAGE_DELETE: "Status page deleted successfully",
STATUS_PAGE_UPDATE: "Status page updated successfully",
STATUS_PAGE_BY_TEAM_ID: "Got status pages by team id successfully",
// Docker
DOCKER_SUCCESS: "Docker container status fetched successfully",
// Port
PORT_SUCCESS: "Port connected successfully",
};
export { errorMessages, successMessages };