refactor service dir structure
This commit is contained in:
1 parent
0b4ec46f79
commit
06fa79e09d
28 files changed
+251
-42
No files matched your search
@@ -1,7 +1,7 @@
|
||||
import InviteToken from "../../models/InviteToken.js";
|
||||
import crypto from "crypto";
|
||||
import ServiceRegistry from "../../../service/serviceRegistry.js";
|
||||
import StringService from "../../../service/stringService.js";
|
||||
import ServiceRegistry from "../../../service/system/serviceRegistry.js";
|
||||
import StringService from "../../../service/system/stringService.js";
|
||||
|
||||
const SERVICE_NAME = "inviteModule";
|
||||
/**
|
||||
|
||||
@@ -4,8 +4,8 @@ import Check from "../../models/Check.js";
|
||||
import PageSpeedCheck from "../../models/PageSpeedCheck.js";
|
||||
import HardwareCheck from "../../models/HardwareCheck.js";
|
||||
import { NormalizeData, NormalizeDataUptimeDetails } from "../../../utils/dataUtils.js";
|
||||
import ServiceRegistry from "../../../service/serviceRegistry.js";
|
||||
import StringService from "../../../service/stringService.js";
|
||||
import ServiceRegistry from "../../../service/system/serviceRegistry.js";
|
||||
import StringService from "../../../service/system/stringService.js";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import UserModel from "../../models/User.js";
|
||||
import RecoveryToken from "../../models/RecoveryToken.js";
|
||||
import serviceRegistry from "../../../service/serviceRegistry.js";
|
||||
import StringService from "../../../service/stringService.js";
|
||||
import crypto from "crypto";
|
||||
import serviceRegistry from "../../../service/system/serviceRegistry.js";
|
||||
import StringService from "../../../service/system/stringService.js";
|
||||
|
||||
const SERVICE_NAME = "recoveryModule";
|
||||
|
||||
@@ -53,7 +54,7 @@ const resetPassword = async (password, candidateToken) => {
|
||||
const newPassword = password;
|
||||
|
||||
// Validate token again
|
||||
const recoveryToken = await validateRecoveryToken(req, res);
|
||||
const recoveryToken = await validateRecoveryToken(candidateToken);
|
||||
const user = await UserModel.findOne({ email: recoveryToken.email });
|
||||
|
||||
if (user === null) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import StatusPage from "../../models/StatusPage.js";
|
||||
import { NormalizeData } from "../../../utils/dataUtils.js";
|
||||
import ServiceRegistry from "../../../service/serviceRegistry.js";
|
||||
import StringService from "../../../service/stringService.js";
|
||||
import ServiceRegistry from "../../../service/system/serviceRegistry.js";
|
||||
import StringService from "../../../service/system/stringService.js";
|
||||
|
||||
const SERVICE_NAME = "statusPageModule";
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ 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";
|
||||
import ServiceRegistry from "../../../service/system/serviceRegistry.js";
|
||||
import StringService from "../../../service/system/stringService.js";
|
||||
const SERVICE_NAME = "userModule";
|
||||
|
||||
const checkSuperadmin = async () => {
|
||||
|
||||
+18
-18
@@ -47,58 +47,58 @@ import DiagnosticRoutes from "./routes/diagnosticRoute.js";
|
||||
import DiagnosticController from "./controllers/diagnosticController.js";
|
||||
|
||||
//JobQueue service and dependencies
|
||||
import JobQueue from "./service/JobQueue/JobQueue.js";
|
||||
import JobQueueHelper from "./service/JobQueue/JobQueueHelper.js";
|
||||
import JobQueue from "./service/infrastructure/JobQueue/JobQueue.js";
|
||||
import JobQueueHelper from "./service/infrastructure/JobQueue/JobQueueHelper.js";
|
||||
import { Queue, Worker } from "bullmq";
|
||||
|
||||
import PulseQueue from "./service/PulseQueue/PulseQueue.js";
|
||||
import PulseQueueHelper from "./service/PulseQueue/PulseQueueHelper.js";
|
||||
import PulseQueue from "./service/infrastructure/PulseQueue/PulseQueue.js";
|
||||
import PulseQueueHelper from "./service/infrastructure/PulseQueue/PulseQueueHelper.js";
|
||||
|
||||
import SuperSimpleQueue from "./service/SuperSimpleQueue/SuperSimpleQueue.js";
|
||||
import SuperSimpleQueueHelper from "./service/SuperSimpleQueue/SuperSimpleQueueHelper.js";
|
||||
import SuperSimpleQueue from "./service/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js";
|
||||
import SuperSimpleQueueHelper from "./service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js";
|
||||
|
||||
import UserService from "./service/userService.js";
|
||||
import UserService from "./service/business/userService.js";
|
||||
|
||||
//Network service and dependencies
|
||||
import NetworkService from "./service/networkService.js";
|
||||
import NetworkService from "./service/infrastructure/networkService.js";
|
||||
import axios from "axios";
|
||||
import ping from "ping";
|
||||
import http from "http";
|
||||
import Docker from "dockerode";
|
||||
import net from "net";
|
||||
// Email service and dependencies
|
||||
import EmailService from "./service/emailService.js";
|
||||
import EmailService from "./service/infrastructure/emailService.js";
|
||||
import nodemailer from "nodemailer";
|
||||
import pkg from "handlebars";
|
||||
const { compile } = pkg;
|
||||
import mjml2html from "mjml";
|
||||
|
||||
// Settings Service and dependencies
|
||||
import SettingsService from "./service/settingsService.js";
|
||||
import SettingsService from "./service/system/settingsService.js";
|
||||
import AppSettings from "./db/models/AppSettings.js";
|
||||
|
||||
// Status Service and dependencies
|
||||
import StatusService from "./service/statusService.js";
|
||||
import StatusService from "./service/infrastructure/statusService.js";
|
||||
|
||||
// Notification Service and dependencies
|
||||
import NotificationService from "./service/notificationService.js";
|
||||
import NotificationUtils from "./service/notificationUtils.js";
|
||||
import NotificationService from "./service/infrastructure/notificationService.js";
|
||||
import NotificationUtils from "./service/infrastructure/notificationUtils.js";
|
||||
|
||||
// Buffer Service and dependencies
|
||||
import BufferService from "./service/bufferService.js";
|
||||
import BufferService from "./service/infrastructure/bufferService.js";
|
||||
|
||||
// Service Registry
|
||||
import ServiceRegistry from "./service/serviceRegistry.js";
|
||||
import ServiceRegistry from "./service/system/serviceRegistry.js";
|
||||
|
||||
import MongoDB from "./db/mongo/MongoDB.js";
|
||||
|
||||
// Redis Service and dependencies
|
||||
import IORedis from "ioredis";
|
||||
import RedisService from "./service/redisService.js";
|
||||
import RedisService from "./service/data/redisService.js";
|
||||
|
||||
import TranslationService from "./service/translationService.js";
|
||||
import TranslationService from "./service/system/translationService.js";
|
||||
import languageMiddleware from "./middleware/languageMiddleware.js";
|
||||
import StringService from "./service/stringService.js";
|
||||
import StringService from "./service/system/stringService.js";
|
||||
|
||||
const SERVICE_NAME = "Server";
|
||||
const SHUTDOWN_TIMEOUT = 1000;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import logger from "../utils/logger.js";
|
||||
import ServiceRegistry from "../service/serviceRegistry.js";
|
||||
import StringService from "../service/stringService.js";
|
||||
import ServiceRegistry from "../service/system/serviceRegistry.js";
|
||||
import StringService from "../service/system/stringService.js";
|
||||
|
||||
const handleErrors = (error, req, res, next) => {
|
||||
console.log("ERROR", error);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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 ServiceRegistry from "../service/system/serviceRegistry.js";
|
||||
import StringService from "../service/system/stringService.js";
|
||||
import SettingsService from "../service/system/settingsService.js";
|
||||
|
||||
const isAllowed = (allowedRoles) => {
|
||||
return (req, res, next) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import jwt from "jsonwebtoken";
|
||||
import ServiceRegistry from "../service/serviceRegistry.js";
|
||||
import SettingsService from "../service/settingsService.js";
|
||||
import StringService from "../service/stringService.js";
|
||||
import ServiceRegistry from "../service/system/serviceRegistry.js";
|
||||
import SettingsService from "../service/system/settingsService.js";
|
||||
import StringService from "../service/system/stringService.js";
|
||||
const SERVICE_NAME = "verifyJWT";
|
||||
const TOKEN_PREFIX = "Bearer ";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import logger from "../utils/logger.js";
|
||||
import ServiceRegistry from "../service/serviceRegistry.js";
|
||||
import StringService from "../service/stringService.js";
|
||||
import ServiceRegistry from "../service/system/serviceRegistry.js";
|
||||
import StringService from "../service/system/stringService.js";
|
||||
import { ObjectId } from "mongodb";
|
||||
|
||||
const SERVICE_NAME = "verifyOwnership";
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
const SERVICE_NAME = "userService";
|
||||
import { createAuthError, createError } from "../../utils/errorUtils.js";
|
||||
|
||||
class UserService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
constructor({ db, emailService, settingsService, logger, stringService, jwt }) {
|
||||
this.db = db;
|
||||
this.emailService = emailService;
|
||||
this.settingsService = settingsService;
|
||||
this.logger = logger;
|
||||
this.stringService = stringService;
|
||||
this.jwt = jwt;
|
||||
}
|
||||
|
||||
issueToken = (payload, appSettings) => {
|
||||
const tokenTTL = appSettings?.jwtTTL ?? "2h";
|
||||
const tokenSecret = appSettings?.jwtSecret;
|
||||
const payloadData = payload;
|
||||
return this.jwt.sign(payloadData, tokenSecret, { expiresIn: tokenTTL });
|
||||
};
|
||||
|
||||
registerUser = async (user, file) => {
|
||||
// Create a new user
|
||||
// If superAdmin exists, a token should be attached to all further register requests
|
||||
const superAdminExists = await this.db.checkSuperadmin();
|
||||
if (superAdminExists) {
|
||||
const invitedUser = await this.db.getInviteTokenAndDelete(user.inviteToken);
|
||||
user.role = invitedUser.role;
|
||||
user.teamId = invitedUser.teamId;
|
||||
} 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");
|
||||
await this.db.updateAppSettings({ jwtSecret });
|
||||
}
|
||||
|
||||
const newUser = await this.db.insertUser({ ...user }, file);
|
||||
|
||||
this.logger.debug({
|
||||
message: "New user created",
|
||||
service: SERVICE_NAME,
|
||||
method: "registerUser",
|
||||
details: newUser._id,
|
||||
});
|
||||
|
||||
const userForToken = { ...newUser._doc };
|
||||
delete userForToken.profileImage;
|
||||
delete userForToken.avatarImage;
|
||||
|
||||
const appSettings = await this.settingsService.getSettings();
|
||||
|
||||
const token = this.issueToken(userForToken, appSettings);
|
||||
|
||||
try {
|
||||
const html = await this.emailService.buildEmail("welcomeEmailTemplate", {
|
||||
name: newUser.firstName,
|
||||
});
|
||||
this.emailService.sendEmail(newUser.email, "Welcome to Uptime Monitor", html).catch((error) => {
|
||||
this.logger.warn({
|
||||
message: error.message,
|
||||
service: SERVICE_NAME,
|
||||
method: "registerUser",
|
||||
stack: error.stack,
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.warn({
|
||||
message: error.message,
|
||||
service: SERVICE_NAME,
|
||||
method: "registerUser",
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
|
||||
return { user: newUser, token };
|
||||
};
|
||||
|
||||
loginUser = async (email, password) => {
|
||||
// Check if user exists
|
||||
const user = await this.db.getUserByEmail(email);
|
||||
// Compare password
|
||||
const match = await user.comparePassword(password);
|
||||
if (match !== true) {
|
||||
throw createAuthError(this.stringService.authIncorrectPassword);
|
||||
}
|
||||
|
||||
// Remove password from user object. Should this be abstracted to DB layer?
|
||||
const userWithoutPassword = { ...user._doc };
|
||||
delete userWithoutPassword.password;
|
||||
delete userWithoutPassword.avatarImage;
|
||||
|
||||
// Happy path, return token
|
||||
const appSettings = await this.settingsService.getSettings();
|
||||
const token = this.issueToken(userWithoutPassword, appSettings);
|
||||
// reset avatar image
|
||||
userWithoutPassword.avatarImage = user.avatarImage;
|
||||
return { user: userWithoutPassword, token };
|
||||
};
|
||||
|
||||
editUser = async (updates, file, currentUser) => {
|
||||
// Change Password check
|
||||
if (updates?.password && updates?.newPassword) {
|
||||
// Get user's email
|
||||
// Add user email to body for DB operation
|
||||
updates.email = currentUser.email;
|
||||
// Get user
|
||||
const user = await this.db.getUserByEmail(currentUser.email);
|
||||
// Compare passwords
|
||||
const match = await user.comparePassword(updates?.password);
|
||||
// If not a match, throw a 403
|
||||
// 403 instead of 401 to avoid triggering axios interceptor
|
||||
if (!match) {
|
||||
throw createError(this.stringService.authIncorrectPassword, 403);
|
||||
}
|
||||
// If a match, update the password
|
||||
updates.password = updates.newPassword;
|
||||
}
|
||||
|
||||
const updatedUser = await this.db.updateUser({ userId: currentUser?._id, user: updates, file: file });
|
||||
return updatedUser;
|
||||
};
|
||||
|
||||
checkSuperadminExists = async () => {
|
||||
const superAdminExists = await this.db.checkSuperadmin();
|
||||
return superAdminExists;
|
||||
};
|
||||
|
||||
requestRecovery = async (email) => {
|
||||
const user = await this.db.getUserByEmail(email);
|
||||
const recoveryToken = await this.db.requestRecoveryToken(email);
|
||||
const name = user.firstName;
|
||||
const { clientHost } = this.settingsService.getSettings();
|
||||
const url = `${clientHost}/set-new-password/${recoveryToken.token}`;
|
||||
|
||||
const html = await this.emailService.buildEmail("passwordResetTemplate", {
|
||||
name,
|
||||
email,
|
||||
url,
|
||||
});
|
||||
const msgId = await this.emailService.sendEmail(email, "Checkmate Password Reset", html);
|
||||
return msgId;
|
||||
};
|
||||
|
||||
validateRecovery = async (recoveryToken) => {
|
||||
await this.db.validateRecoveryToken(recoveryToken);
|
||||
};
|
||||
|
||||
resetPassword = async (password, recoveryToken) => {
|
||||
const user = await this.db.resetPassword(password, recoveryToken);
|
||||
const appSettings = await this.settingsService.getSettings();
|
||||
const token = this.issueToken(user._doc, appSettings);
|
||||
return { user, token };
|
||||
};
|
||||
|
||||
deleteUser = async (user) => {
|
||||
const email = user?.email;
|
||||
if (!email) {
|
||||
throw new Error("No email in request");
|
||||
}
|
||||
|
||||
const teamId = user?.teamId;
|
||||
const userId = user?._id;
|
||||
|
||||
if (!teamId) {
|
||||
throw new Error("No team ID in request");
|
||||
}
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("No user ID in request");
|
||||
}
|
||||
|
||||
const roles = user?.role;
|
||||
if (roles.includes("demo")) {
|
||||
throw new Error("Demo user cannot be deleted");
|
||||
}
|
||||
|
||||
// 1. Find all the monitors associated with the team ID if superadmin
|
||||
const result = await this.db.getMonitorsByTeamId({
|
||||
teamId: teamId,
|
||||
});
|
||||
|
||||
if (roles.includes("superadmin")) {
|
||||
// 2. Remove all jobs, delete checks and alerts
|
||||
result?.monitors.length > 0 &&
|
||||
(await Promise.all(
|
||||
result.monitors.map(async (monitor) => {
|
||||
await this.jobQueue.deleteJob(monitor);
|
||||
})
|
||||
));
|
||||
}
|
||||
// 6. Delete the user by id
|
||||
await this.db.deleteUser(userId);
|
||||
};
|
||||
|
||||
getAllUsers = async () => {
|
||||
const users = await this.db.getAllUsers();
|
||||
return users;
|
||||
};
|
||||
|
||||
getUserById = async (roles, userId) => {
|
||||
const user = await this.db.getUserById(roles, userId);
|
||||
return user;
|
||||
};
|
||||
|
||||
editUserById = async (userId, user) => {
|
||||
await this.db.editUserById(userId, user);
|
||||
};
|
||||
}
|
||||
export default UserService;
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,5 +1,5 @@
|
||||
import MonitorStats from "../db/models/MonitorStats.js";
|
||||
import { safelyParseFloat } from "../utils/dataUtils.js";
|
||||
import MonitorStats from "../../db/models/MonitorStats.js";
|
||||
import { safelyParseFloat } from "../../utils/dataUtils.js";
|
||||
const SERVICE_NAME = "StatusService";
|
||||
|
||||
class StatusService {
|
||||
@@ -1,5 +1,5 @@
|
||||
const SERVICE_NAME = "ServiceRegistry";
|
||||
import logger from "../utils/logger.js";
|
||||
import logger from "../../utils/logger.js";
|
||||
class ServiceRegistry {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
constructor() {
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user