fix: use new structure

This commit is contained in:
cihatata
2025-01-30 00:41:31 +03:00
committed by cihat
parent a98a3dd7a3
commit 88df88891c
22 changed files with 193 additions and 146 deletions

View File

@@ -21,6 +21,8 @@ services:
environment:
- DB_CONNECTION_STRING=mongodb://mongodb:27017/uptime_db
- REDIS_HOST=redis
- POEDITOR_API_TOKEN=
- POEDITOR_PROJECT_ID=
# volumes:
# - /var/run/docker.sock:/var/run/docker.sock:ro
redis:

View File

@@ -8,7 +8,6 @@ import {
newPasswordValidation,
} from "../validation/joi.js";
import logger from "../utils/logger.js";
import { successMessages } from "../utils/messages.js";
import jwt from "jsonwebtoken";
import { getTokenFromHeaders, tokenType } from "../utils/utils.js";
import crypto from "crypto";
@@ -23,6 +22,7 @@ class AuthController {
this.settingsService = settingsService;
this.emailService = emailService;
this.jobQueue = jobQueue;
this.stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
}
/**
@@ -78,7 +78,7 @@ class AuthController {
// If superAdmin exists, a token should be attached to all further register requests
const superAdminExists = await this.db.checkSuperadmin(req, res);
if (superAdminExists) {
await this.db.getInviteTokenAndDelete(inviteToken, req.language);
await this.db.getInviteTokenAndDelete(inviteToken);
} else {
// This is the first account, create JWT secret to use if one is not supplied by env
const jwtSecret = crypto.randomBytes(64).toString("hex");
@@ -87,7 +87,7 @@ class AuthController {
const newUser = await this.db.insertUser({ ...req.body }, req.file);
logger.info({
message: successMessages.AUTH_CREATE_USER(req.language),
message: this.stringService.authCreateUser,
service: SERVICE_NAME,
details: newUser._id,
});
@@ -118,7 +118,7 @@ class AuthController {
});
res.success({
msg: successMessages.AUTH_CREATE_USER(req.language),
msg: this.stringService.authCreateUser,
data: { user: newUser, token: token, refreshToken: refreshToken },
});
} catch (error) {
@@ -139,7 +139,6 @@ class AuthController {
* @throws {Error} If there is an error during the process, especially if there is a validation error (422) or the password is incorrect.
*/
loginUser = async (req, res, next) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
await loginValidation.validateAsync(req.body);
} catch (error) {
@@ -151,12 +150,12 @@ class AuthController {
const { email, password } = req.body;
// Check if user exists
const user = await this.db.getUserByEmail(email, req.language);
const user = await this.db.getUserByEmail(email);
// Compare password
const match = await user.comparePassword(password);
if (match !== true) {
const error = new Error(stringService.authIncorrectPassword);
const error = new Error(this.stringService.authIncorrectPassword);
error.status = 401;
next(error);
return;
@@ -179,7 +178,7 @@ class AuthController {
userWithoutPassword.avatarImage = user.avatarImage;
return res.success({
msg: successMessages.AUTH_LOGIN_USER(req.language),
msg: this.stringService.authLoginUser,
data: {
user: userWithoutPassword,
token: token,
@@ -203,7 +202,6 @@ 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) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
// check for refreshToken
@@ -211,7 +209,7 @@ class AuthController {
if (!refreshToken) {
// No refresh token provided
const error = new Error(stringService.noRefreshToken);
const error = new Error(this.stringService.noRefreshToken);
error.status = 401;
error.service = SERVICE_NAME;
error.method = "refreshAuthToken";
@@ -226,8 +224,8 @@ class AuthController {
// Invalid or expired refresh token, trigger logout
const errorMessage =
refreshErr.name === "TokenExpiredError"
? stringService.expiredAuthToken
: stringService.invalidAuthToken;
? this.stringService.expiredAuthToken
: this.stringService.invalidAuthToken;
const error = new Error(errorMessage);
error.status = 401;
error.service = SERVICE_NAME;
@@ -248,7 +246,7 @@ class AuthController {
);
return res.success({
msg: successMessages.AUTH_TOKEN_REFRESHED(req.language),
msg: this.stringService.authTokenRefreshed,
data: { user: payloadData, token: newAuthToken, refreshToken: refreshToken },
});
} catch (error) {
@@ -270,7 +268,6 @@ 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) => {
const stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
try {
await editUserParamValidation.validateAsync(req.params);
@@ -283,7 +280,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(stringService.unauthorized);
const error = new Error(this.stringService.unauthorized);
error.status = 401;
error.service = SERVICE_NAME;
next(error);
@@ -301,13 +298,13 @@ class AuthController {
// Add user email to body for DB operation
req.body.email = email;
// Get user
const user = await this.db.getUserByEmail(email, req.language);
const user = await this.db.getUserByEmail(email);
// Compare passwords
const match = await user.comparePassword(req.body.password);
// If not a match, throw a 403
// 403 instead of 401 to avoid triggering axios interceptor
if (!match) {
const error = new Error(stringService.authIncorrectPassword);
const error = new Error(this.stringService.authIncorrectPassword);
error.status = 403;
next(error);
return;
@@ -318,7 +315,7 @@ class AuthController {
const updatedUser = await this.db.updateUser(req, res);
res.success({
msg: successMessages.AUTH_UPDATE_USER(req.language),
msg: this.stringService.authUpdateUser,
data: updatedUser,
});
} catch (error) {
@@ -340,7 +337,7 @@ class AuthController {
const superAdminExists = await this.db.checkSuperadmin(req, res);
return res.success({
msg: successMessages.AUTH_ADMIN_EXISTS(req.language),
msg: this.stringService.authAdminExists,
data: superAdminExists,
});
} catch (error) {
@@ -369,7 +366,7 @@ class AuthController {
try {
const { email } = req.body;
const user = await this.db.getUserByEmail(email, req.language);
const user = await this.db.getUserByEmail(email);
const recoveryToken = await this.db.requestRecoveryToken(req, res);
const name = user.firstName;
const { clientHost } = this.settingsService.getSettings();
@@ -386,7 +383,7 @@ class AuthController {
);
return res.success({
msg: successMessages.AUTH_CREATE_RECOVERY_TOKEN(req.language),
msg: this.stringService.authCreateRecoveryToken,
data: msgId,
});
} catch (error) {
@@ -417,7 +414,7 @@ class AuthController {
await this.db.validateRecoveryToken(req, res);
return res.success({
msg: successMessages.AUTH_VERIFY_RECOVERY_TOKEN(req.language),
msg: this.stringService.authVerifyRecoveryToken,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "validateRecoveryTokenController"));
@@ -450,7 +447,7 @@ class AuthController {
const token = this.issueToken(user._doc, tokenType.ACCESS_TOKEN, appSettings);
return res.success({
msg: successMessages.AUTH_RESET_PASSWORD(req.language),
msg: this.stringService.authResetPassword,
data: { user, token },
});
} catch (error) {
@@ -474,7 +471,7 @@ class AuthController {
const { email } = decodedToken;
// Check if the user exists
const user = await this.db.getUserByEmail(email, req.language);
const user = await this.db.getUserByEmail(email);
// 1. Find all the monitors associated with the team ID if superadmin
const result = await this.db.getMonitorsByTeamId({
@@ -501,10 +498,10 @@ class AuthController {
await this.db.deleteMonitorsByUserId(user._id);
}
// 6. Delete the user by id
await this.db.deleteUser(user._id, req.language);
await this.db.deleteUser(user._id);
return res.success({
msg: successMessages.AUTH_DELETE_USER(req.language),
msg: this.stringService.authDeleteUser,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "deleteUserController"));
@@ -516,7 +513,7 @@ class AuthController {
const allUsers = await this.db.getAllUsers(req, res);
return res.success({
msg: successMessages.AUTH_GET_ALL_USERS(req.language),
msg: this.stringService.authGetAllUsers,
data: allUsers,
});
} catch (error) {

View File

@@ -9,10 +9,11 @@ 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";
import ServiceRegistry from "../service/serviceRegistry.js";
import StringService from "../service/stringService.js";
const SERVICE_NAME = "checkController";
@@ -20,6 +21,7 @@ class CheckController {
constructor(db, settingsService) {
this.db = db;
this.settingsService = settingsService;
this.stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
}
createCheck = async (req, res, next) => {
@@ -36,7 +38,7 @@ class CheckController {
const check = await this.db.createCheck(checkData);
return res.success({
msg: successMessages.CHECK_CREATE(req.language),
msg: this.stringService.checkCreate,
data: check,
});
} catch (error) {
@@ -57,7 +59,7 @@ class CheckController {
const result = await this.db.getChecksByMonitor(req);
return res.success({
msg: successMessages.CHECK_GET(req.language),
msg: this.stringService.checkGet,
data: result,
});
} catch (error) {
@@ -77,7 +79,7 @@ class CheckController {
const checkData = await this.db.getChecksByTeam(req);
return res.success({
msg: successMessages.CHECK_GET(req.language),
msg: this.stringService.checkGet,
data: checkData,
});
} catch (error) {
@@ -97,7 +99,7 @@ class CheckController {
const deletedCount = await this.db.deleteChecks(req.params.monitorId);
return res.success({
msg: successMessages.CHECK_DELETE(req.language),
msg: this.stringService.checkDelete,
data: { deletedCount },
});
} catch (error) {
@@ -117,7 +119,7 @@ class CheckController {
const deletedCount = await this.db.deleteChecksByTeamId(req.params.teamId);
return res.success({
msg: successMessages.CHECK_DELETE(req.language),
msg: this.stringService.checkDelete,
data: { deletedCount },
});
} catch (error) {
@@ -144,7 +146,7 @@ class CheckController {
await this.db.updateChecksTTL(teamId, ttl);
return res.success({
msg: successMessages.CHECK_UPDATE_TTL(req.language),
msg: this.stringService.checkUpdateTTL,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "updateTTL"));

View File

@@ -7,7 +7,9 @@ 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";
import ServiceRegistry from "../service/serviceRegistry.js";
import StringService from "../service/stringService.js";
const SERVICE_NAME = "inviteController";
class InviteController {
@@ -15,6 +17,7 @@ class InviteController {
this.db = db;
this.settingsService = settingsService;
this.emailService = emailService;
this.stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
}
/**
@@ -66,7 +69,7 @@ class InviteController {
});
return res.success({
msg: successMessages.INVITE_ISSUED(req.language),
msg: this.stringService.inviteIssued,
data: inviteToken,
});
} catch (error) {
@@ -83,10 +86,10 @@ class InviteController {
}
try {
const invite = await this.db.getInviteToken(req.body.token, req.language);
const invite = await this.db.getInviteToken(req.body.token);
return res.success({
msg: successMessages.INVITE_VERIFIED(req.language),
msg: this.stringService.inviteVerified,
data: invite,
});
} catch (error) {

View File

@@ -9,14 +9,17 @@ 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";
import ServiceRegistry from "../service/serviceRegistry.js";
import StringService from "../service/stringService.js";
const SERVICE_NAME = "maintenanceWindowController";
class MaintenanceWindowController {
constructor(db, settingsService) {
this.db = db;
this.settingsService = settingsService;
this.stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
}
createMaintenanceWindows = async (req, res, next) => {
@@ -45,7 +48,7 @@ class MaintenanceWindowController {
await Promise.all(dbTransactions);
return res.success({
msg: successMessages.MAINTENANCE_WINDOW_CREATE(req.language),
msg: this.stringService.maintenanceWindowCreate,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "createMaintenanceWindow"));
@@ -63,7 +66,7 @@ class MaintenanceWindowController {
const maintenanceWindow = await this.db.getMaintenanceWindowById(req.params.id);
return res.success({
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_ID(req.language),
msg: this.stringService.maintenanceWindowGetById,
data: maintenanceWindow,
});
} catch (error) {
@@ -89,7 +92,7 @@ class MaintenanceWindowController {
);
return res.success({
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_TEAM(req.language),
msg: this.stringService.maintenanceWindowGetByTeam,
data: maintenanceWindows,
});
} catch (error) {
@@ -111,7 +114,7 @@ class MaintenanceWindowController {
);
return res.success({
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_USER(req.language),
msg: this.stringService.maintenanceWindowGetByUser,
data: maintenanceWindows,
});
} catch (error) {
@@ -129,7 +132,7 @@ class MaintenanceWindowController {
try {
await this.db.deleteMaintenanceWindowById(req.params.id);
return res.success({
msg: successMessages.MAINTENANCE_WINDOW_DELETE(req.language),
msg: this.stringService.maintenanceWindowDelete,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "deleteMaintenanceWindow"));
@@ -150,7 +153,7 @@ class MaintenanceWindowController {
req.body
);
return res.success({
msg: successMessages.MAINTENANCE_WINDOW_EDIT(req.language),
msg: this.stringService.maintenanceWindowEdit,
data: editedMaintenanceWindow,
});
} catch (error) {

View File

@@ -14,13 +14,14 @@ 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";
import { handleError, handleValidationError } from "./controllerUtils.js";
import axios from "axios";
import seedDb from "../db/mongo/utils/seedDb.js";
import ServiceRegistry from "../service/serviceRegistry.js";
import StringService from "../service/stringService.js";
const SERVICE_NAME = "monitorController";
class MonitorController {
@@ -28,6 +29,7 @@ class MonitorController {
this.db = db;
this.settingsService = settingsService;
this.jobQueue = jobQueue;
this.stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
}
/**
@@ -43,7 +45,7 @@ class MonitorController {
try {
const monitors = await this.db.getAllMonitors();
return res.success({
msg: successMessages.MONITOR_GET_ALL(req.language),
msg: this.stringService.monitorGetAll,
data: monitors,
});
} catch (error) {
@@ -64,7 +66,7 @@ class MonitorController {
try {
const monitors = await this.db.getAllMonitorsWithUptimeStats();
return res.success({
msg: successMessages.MONITOR_GET_ALL(req.language),
msg: this.stringService.monitorGetAll,
data: monitors,
});
} catch (error) {
@@ -76,7 +78,7 @@ class MonitorController {
try {
const monitor = await this.db.getUptimeDetailsById(req);
return res.success({
msg: successMessages.MONITOR_GET_BY_ID(req.language),
msg: this.stringService.monitorGetById,
data: monitor,
});
} catch (error) {
@@ -105,7 +107,7 @@ class MonitorController {
try {
const monitorStats = await this.db.getMonitorStatsById(req);
return res.success({
msg: successMessages.MONITOR_STATS_BY_ID(req.language),
msg: this.stringService.monitorStatsById,
data: monitorStats,
});
} catch (error) {
@@ -133,7 +135,7 @@ class MonitorController {
try {
const monitor = await this.db.getHardwareDetailsById(req);
return res.success({
msg: successMessages.MONITOR_GET_BY_ID(req.language),
msg: this.stringService.monitorGetById,
data: monitor,
});
} catch (error) {
@@ -154,7 +156,7 @@ class MonitorController {
const certificate = await fetchMonitorCertificate(sslChecker, monitor);
return res.success({
msg: successMessages.MONITOR_CERTIFICATE(req.language),
msg: this.stringService.monitorCertificate,
data: {
certificateDate: new Date(certificate.validTo),
},
@@ -187,7 +189,7 @@ class MonitorController {
try {
const monitor = await this.db.getMonitorById(req.params.monitorId);
return res.success({
msg: successMessages.MONITOR_GET_BY_ID(req.language),
msg: this.stringService.monitorGetById,
data: monitor,
});
} catch (error) {
@@ -231,7 +233,7 @@ class MonitorController {
// Add monitor to job queue
this.jobQueue.addJob(monitor._id, monitor);
return res.success({
msg: successMessages.MONITOR_CREATE(req.language),
msg: this.stringService.monitorCreate,
data: monitor,
});
} catch (error) {
@@ -309,7 +311,7 @@ class MonitorController {
stack: error.stack,
});
}
return res.success({ msg: successMessages.MONITOR_DELETE(req.language) });
return res.success({ msg: this.stringService.monitorDelete });
} catch (error) {
next(handleError(error, SERVICE_NAME, "deleteMonitor"));
}
@@ -401,7 +403,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(req.language),
msg: this.stringService.monitorEdit,
data: editedMonitor,
});
} catch (error) {
@@ -438,8 +440,8 @@ class MonitorController {
monitor.save();
return res.success({
msg: monitor.isActive
? successMessages.MONITOR_RESUME(req.language)
: successMessages.MONITOR_PAUSE(req.language),
? this.stringService.monitorResume
: this.stringService.monitorPause,
data: monitor,
});
} catch (error) {
@@ -469,7 +471,7 @@ class MonitorController {
);
return res.success({
msg: successMessages.MONITOR_DEMO_ADDED(req.language),
msg: this.stringService.monitorDemoAdded,
data: demoMonitors.length,
});
} catch (error) {
@@ -488,7 +490,7 @@ class MonitorController {
try {
const monitors = await this.db.getMonitorsByTeamId(req);
return res.success({
msg: successMessages.MONITOR_GET_BY_TEAM_ID(req.language),
msg: this.stringService.monitorGetByTeamId,
data: monitors,
});
} catch (error) {

View File

@@ -1,18 +1,20 @@
import { handleError } from "./controllerUtils.js";
import { successMessages } from "../utils/messages.js";
import ServiceRegistry from "../service/serviceRegistry.js";
import StringService from "../service/stringService.js";
const SERVICE_NAME = "JobQueueController";
class JobQueueController {
constructor(jobQueue) {
this.jobQueue = jobQueue;
this.stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
}
getMetrics = async (req, res, next) => {
try {
const metrics = await this.jobQueue.getMetrics();
res.success({
msg: successMessages.QUEUE_GET_METRICS(req.language),
msg: this.stringService.queueGetMetrics,
data: metrics,
});
} catch (error) {
@@ -25,7 +27,7 @@ class JobQueueController {
try {
const jobs = await this.jobQueue.getJobStats();
return res.success({
msg: successMessages.QUEUE_GET_METRICS(req.language),
msg: this.stringService.queueGetMetrics,
data: jobs,
});
} catch (error) {
@@ -38,7 +40,7 @@ class JobQueueController {
try {
await this.jobQueue.addJob(Math.random().toString(36).substring(7));
return res.success({
msg: successMessages.QUEUE_ADD_JOB(req.language),
msg: this.stringService.queueAddJob,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "addJob"));
@@ -50,7 +52,7 @@ class JobQueueController {
try {
await this.jobQueue.obliterate();
return res.success({
msg: successMessages.QUEUE_OBLITERATE(req.language),
msg: this.stringService.queueObliterate,
});
} catch (error) {
next(handleError(error, SERVICE_NAME, "obliterateQueue"));

View File

@@ -1,12 +1,15 @@
import { successMessages } from "../utils/messages.js";
import ServiceRegistry from "../service/serviceRegistry.js";
import StringService from "../service/stringService.js";
import { updateAppSettingsBodyValidation } from "../validation/joi.js";
import { handleValidationError, handleError } from "./controllerUtils.js";
const SERVICE_NAME = "SettingsController";
class SettingsController {
constructor(db, settingsService) {
this.db = db;
this.settingsService = settingsService;
this.stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
}
getAppSettings = async (req, res, next) => {
@@ -14,7 +17,7 @@ class SettingsController {
const settings = { ...(await this.settingsService.getSettings()) };
delete settings.jwtSecret;
return res.success({
msg: successMessages.GET_APP_SETTINGS(req.language),
msg: this.stringService.getAppSettings,
data: settings,
});
} catch (error) {
@@ -35,7 +38,7 @@ class SettingsController {
const updatedSettings = { ...(await this.settingsService.reloadSettings()) };
delete updatedSettings.jwtSecret;
return res.success({
msg: successMessages.UPDATE_APP_SETTINGS(req.language),
msg: this.stringService.updateAppSettings,
data: updatedSettings,
});
} catch (error) {

View File

@@ -12,6 +12,7 @@ const SERVICE_NAME = "statusPageController";
class StatusPageController {
constructor(db) {
this.db = db;
this.stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
}
createStatusPage = async (req, res, next) => {
@@ -26,7 +27,7 @@ class StatusPageController {
try {
const statusPage = await this.db.createStatusPage(req.body, req.file);
return res.success({
msg: successMessages.STATUS_PAGE_CREATE(req.language),
msg: this.stringService.statusPageCreate,
data: statusPage,
});
} catch (error) {
@@ -63,7 +64,7 @@ class StatusPageController {
try {
const statusPage = await this.db.getStatusPage();
return res.success({
msg: successMessages.STATUS_PAGE_BY_URL(req.language),
msg: this.stringService.statusPageByUrl,
data: statusPage,
});
} catch (error) {

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";
/**
@@ -41,13 +42,14 @@ const requestInviteToken = async (userData) => {
* @returns {Promise<InviteToken>} The invite token data.
* @throws {Error} If the invite token is not found or there is another error.
*/
const getInviteToken = async (token, language) => {
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(language));
throw new Error(stringService.authInviteNotFound);
}
return invite;
} catch (error) {
@@ -67,13 +69,14 @@ const getInviteToken = async (token, language) => {
* @returns {Promise<InviteToken>} The invite token data.
* @throws {Error} If the invite token is not found or there is another error.
*/
const getInviteTokenAndDelete = async (token, language) => {
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(language));
throw new Error(stringService.authInviteNotFound);
}
return invite;
} catch (error) {

View File

@@ -6,6 +6,8 @@ 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";
@@ -326,11 +328,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, req.language));
throw new Error(stringService.dbFindMonitorById(monitorId));
}
const { dateRange, normalize } = req.query;
@@ -419,13 +422,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 +520,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;
}
@@ -676,23 +681,23 @@ const getMonitorsByTeamId = async (req) => {
: []),
...(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 +788,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, req.language));
throw new Error(stringService.getDbFindMonitorById(monitorId));
}
return monitor;
} catch (error) {

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(req.language));
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(req.language));
throw new Error(stringService.dbUserNotFound);
}
const match = await user.comparePassword(newPassword);
if (match === true) {
throw new Error(errorMessages.DB_RESET_PASSWORD_BAD_MATCH(req.language));
throw new Error(stringService.dbResetPasswordBadMatch);
}
user.password = newPassword;

View File

@@ -19,7 +19,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";

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";
@@ -69,13 +71,15 @@ const insertUser = async (
* @returns {Promise<UserModel>}
* @throws {Error}
*/
const getUserByEmail = async (email, language) => {
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(language));
throw new Error(stringService.dbUserNotFound);
}
return user;
} catch (error) {
@@ -149,11 +153,13 @@ const updateUser = async (
* @returns {Promise<UserModel>}
* @throws {Error}
*/
const deleteUser = async (userId, language) => {
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(language));
throw new Error(stringService.dbUserNotFound);
}
return deletedUser;
} catch (error) {

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,

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(req.language));
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(req.language));
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(req.language));
const error = new Error(stringService.insufficientPermissions);
error.status = 401;
error.service = SERVICE_NAME;
next(error);

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(req.language));
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(req.language)); // 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(req.language);
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(req.language));
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,
});
});
}

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(req.language));
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(req.language));
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(req.language));
const error = new Error(stringService.verifyOwnerUnauthorized);
error.status = 403;
throw error;
}

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(req.language));
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(req.language)); // 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();
});

View File

@@ -12,7 +12,9 @@ const QUEUE_LOOKUP = {
};
const getSchedulerId = (monitor) => `scheduler:${monitor.type}:${monitor._id}`;
import { successMessages, errorMessages } from "../utils/messages.js";
import ServiceRegistry from "../service/serviceRegistry.js";
import StringService from "../service/stringService.js";
class NewJobQueue {
static SERVICE_NAME = SERVICE_NAME;
@@ -44,6 +46,7 @@ class NewJobQueue {
this.settingsService = settingsService;
this.logger = logger;
this.Worker = Worker;
this.stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
QUEUE_NAMES.forEach((name) => {
this.queues[name] = new Queue(name, { connection });
@@ -455,7 +458,7 @@ class NewJobQueue {
if (wasDeleted === true) {
this.logger.info({
message: successMessages.JOB_QUEUE_DELETE_JOB('en'),
message: this.stringService.jobQueueDeleteJob,
service: SERVICE_NAME,
method: "deleteJob",
details: `Deleted job ${monitor._id}`,
@@ -464,7 +467,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 +590,7 @@ class NewJobQueue {
const metrics = await this.getMetrics();
this.logger.info({
message: successMessages.JOB_QUEUE_OBLITERATE('en'),
message: this.stringService.jobQueueObliterate,
service: SERVICE_NAME,
method: "obliterate",
details: metrics,

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";
@@ -32,9 +31,11 @@ class NetworkService {
this.http = http;
this.Docker = Docker;
this.net = net;
this.stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
this.apiToken = process.env.POEDITOR_API_TOKEN;
this.projectId = process.env.POEDITOR_PROJECT_ID;
this.stringService = ServiceRegistry.get(StringService.SERVICE_NAME);
if (!this.apiToken || !this.projectId) {
this.logger.error({
@@ -100,13 +101,13 @@ class NetworkService {
if (error) {
pingResponse.status = false;
pingResponse.code = this.PING_ERROR;
pingResponse.message = errorMessages.PING_CANNOT_RESOLVE;
pingResponse.message = this.stringService.pingCannotResolve;
return pingResponse;
}
pingResponse.code = 200;
pingResponse.status = response.alive;
pingResponse.message = successMessages.PING_SUCCESS('en');
pingResponse.message = this.stringService.pingSuccess;
return pingResponse;
} catch (error) {
error.service = this.SERVICE_NAME;
@@ -253,7 +254,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('en'));
throw new Error(this.stringService.dockerNotFound);
}
const container = docker.getContainer(job.data.url);
@@ -270,12 +271,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 || this.stringService.dockerFail;
return dockerResponse;
}
dockerResponse.status = response?.State?.Status === "running" ? true : false;
dockerResponse.code = 200;
dockerResponse.message = successMessages.DOCKER_SUCCESS('en');
dockerResponse.message = this.stringService.dockerSuccess;
return dockerResponse;
} catch (error) {
error.service = this.SERVICE_NAME;
@@ -323,13 +324,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('en');
portResponse.message = this.stringService.portSuccess;
return portResponse;
} catch (error) {
error.service = this.SERVICE_NAME;

View File

@@ -139,5 +139,7 @@
"statusPageCreate": "Status page created successfully",
"newTermsAdded": "New terms added to POEditor",
"dockerSuccess": "Docker container status fetched successfully",
"portSuccess": "Port connected successfully"
"portSuccess": "Port connected successfully",
"monitorPause": "Monitor paused successfully",
"monitorResume": "Monitor resumed successfully"
}