From 48cf8a5e73c4c256eb699ddd5622ff402287509e Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Wed, 30 Jul 2025 15:34:03 -0700 Subject: [PATCH] module -> class --- server/src/config/services.js | 4 + server/src/db/mongo/MongoDB.js | 3 +- server/src/db/mongo/modules/recoveryModule.js | 152 +++++++++--------- server/src/service/business/userService.js | 6 +- 4 files changed, 86 insertions(+), 79 deletions(-) diff --git a/server/src/config/services.js b/server/src/config/services.js index 93ad0ce46..21608fd59 100644 --- a/server/src/config/services.js +++ b/server/src/config/services.js @@ -53,6 +53,7 @@ import MaintenanceWindow from "../db/models/MaintenanceWindow.js"; import MonitorStats from "../db/models/MonitorStats.js"; import NetworkCheck from "../db/models/NetworkCheck.js"; import Notification from "../db/models/Notification.js"; +import RecoveryToken from "../db/models/RecoveryToken.js"; import InviteModule from "../db/mongo/modules/inviteModule.js"; import CheckModule from "../db/mongo/modules/checkModule.js"; @@ -64,6 +65,7 @@ import MonitorModule from "../db/mongo/modules/monitorModule.js"; import NetworkCheckModule from "../db/mongo/modules/networkCheckModule.js"; import NotificationModule from "../db/mongo/modules/notificationModule.js"; import PageSpeedCheckModule from "../db/mongo/modules/pageSpeedCheckModule.js"; +import RecoveryModule from "../db/mongo/modules/recoveryModule.js"; export const initializeServices = async ({ logger, envSettings, settingsService }) => { const serviceRegistry = new ServiceRegistry({ logger }); @@ -98,6 +100,7 @@ export const initializeServices = async ({ logger, envSettings, settingsService const networkCheckModule = new NetworkCheckModule({ NetworkCheck }); const notificationModule = new NotificationModule({ Notification, Monitor }); const pageSpeedCheckModule = new PageSpeedCheckModule({ PageSpeedCheck }); + const recoveryModule = new RecoveryModule({ User, RecoveryToken, crypto, stringService }); const db = new MongoDB({ logger, @@ -112,6 +115,7 @@ export const initializeServices = async ({ logger, envSettings, settingsService networkCheckModule, notificationModule, pageSpeedCheckModule, + recoveryModule, }); await db.connect(); diff --git a/server/src/db/mongo/MongoDB.js b/server/src/db/mongo/MongoDB.js index de6ca0c4e..49d54fc48 100755 --- a/server/src/db/mongo/MongoDB.js +++ b/server/src/db/mongo/MongoDB.js @@ -43,12 +43,13 @@ class MongoDB { networkCheckModule, notificationModule, pageSpeedCheckModule, + recoveryModule, }) { this.logger = logger; this.envSettings = envSettings; this.userModule = userModule; this.inviteModule = inviteModule; - Object.assign(this, recoveryModule); + this.recoveryModule = recoveryModule; Object.assign(this, monitorModule); this.pageSpeedCheckModule = pageSpeedCheckModule; this.hardwareCheckModule = hardwareCheckModule; diff --git a/server/src/db/mongo/modules/recoveryModule.js b/server/src/db/mongo/modules/recoveryModule.js index 2678f49c4..81e4a5a97 100755 --- a/server/src/db/mongo/modules/recoveryModule.js +++ b/server/src/db/mongo/modules/recoveryModule.js @@ -1,86 +1,88 @@ -import UserModel from "../../models/User.js"; -import RecoveryToken from "../../models/RecoveryToken.js"; -import crypto from "crypto"; -import serviceRegistry from "../../../service/system/serviceRegistry.js"; -import StringService from "../../../service/system/stringService.js"; +// import UserModel from "../../models/User.js"; +// import RecoveryToken from "../../models/RecoveryToken.js"; +// import crypto from "crypto"; +// import serviceRegistry from "../../../service/system/serviceRegistry.js"; +// import StringService from "../../../service/system/stringService.js"; const SERVICE_NAME = "recoveryModule"; -/** - * Request a recovery token - * @async - * @param {string} email - * @returns {Promise} - * @throws {Error} - */ -const requestRecoveryToken = async (email) => { - try { - // Delete any existing tokens - await RecoveryToken.deleteMany({ email }); - let recoveryToken = new RecoveryToken({ - email, - token: crypto.randomBytes(32).toString("hex"), - }); - await recoveryToken.save(); - return recoveryToken; - } catch (error) { - error.service = SERVICE_NAME; - error.method = "requestRecoveryToken"; - throw error; +class RecoveryModule { + constructor({ User, RecoveryToken, crypto, stringService }) { + this.User = User; + this.RecoveryToken = RecoveryToken; + this.crypto = crypto; + this.stringService = stringService; } -}; -const validateRecoveryToken = async (candidateToken) => { - const stringService = serviceRegistry.get(StringService.SERVICE_NAME); - try { - const recoveryToken = await RecoveryToken.findOne({ - token: candidateToken, - }); - if (recoveryToken !== null) { + requestRecoveryToken = async (email) => { + try { + // Delete any existing tokens + await this.RecoveryToken.deleteMany({ email }); + let recoveryToken = new this.RecoveryToken({ + email, + token: this.crypto.randomBytes(32).toString("hex"), + }); + await recoveryToken.save(); return recoveryToken; - } else { - throw new Error(stringService.dbTokenNotFound); + } catch (error) { + error.service = SERVICE_NAME; + error.method = "requestRecoveryToken"; + throw error; } - } catch (error) { - error.service = SERVICE_NAME; - error.method = "validateRecoveryToken"; - throw error; - } -}; - -const resetPassword = async (password, candidateToken) => { - const stringService = serviceRegistry.get(StringService.SERVICE_NAME); - try { - const newPassword = password; - - // Validate token again - const recoveryToken = await validateRecoveryToken(candidateToken); - const user = await UserModel.findOne({ email: recoveryToken.email }); - - if (user === null) { - throw new Error(stringService.dbUserNotFound); + }; + validateRecoveryToken = async (candidateToken) => { + try { + const recoveryToken = await this.RecoveryToken.findOne({ + token: candidateToken, + }); + if (recoveryToken !== null) { + return recoveryToken; + } else { + throw new Error(this.stringService.dbTokenNotFound); + } + } catch (error) { + error.service = SERVICE_NAME; + error.method = "validateRecoveryToken"; + throw error; } + }; - const match = await user.comparePassword(newPassword); - if (match === true) { - throw new Error(stringService.dbResetPasswordBadMatch); + resetPassword = async (password, candidateToken) => { + try { + const newPassword = password; + + // Validate token again + const recoveryToken = await this.validateRecoveryToken(candidateToken); + const user = await this.User.findOne({ email: recoveryToken.email }); + + if (user === null) { + console.log("WTF2"); + throw new Error(this.stringService.dbUserNotFound); + } + + const match = await user.comparePassword(newPassword); + + if (match === true) { + console.log("WTF"); + throw new Error("Password cannot be the same as the old password"); + } + + user.password = newPassword; + await user.save(); + await this.RecoveryToken.deleteMany({ email: recoveryToken.email }); + // Fetch the user again without the password + const userWithoutPassword = await this.User.findOne({ + email: recoveryToken.email, + }) + .select("-password") + .select("-profileImage"); + return userWithoutPassword; + } catch (error) { + error.service = SERVICE_NAME; + error.method = "resetPassword"; + throw error; } + }; +} - user.password = newPassword; - await user.save(); - await RecoveryToken.deleteMany({ email: recoveryToken.email }); - // Fetch the user again without the password - const userWithoutPassword = await UserModel.findOne({ - email: recoveryToken.email, - }) - .select("-password") - .select("-profileImage"); - return userWithoutPassword; - } catch (error) { - error.service = SERVICE_NAME; - error.method = "resetPassword"; - throw error; - } -}; - -export { requestRecoveryToken, validateRecoveryToken, resetPassword }; +export default RecoveryModule; diff --git a/server/src/service/business/userService.js b/server/src/service/business/userService.js index 3ffa4c957..d439a942b 100644 --- a/server/src/service/business/userService.js +++ b/server/src/service/business/userService.js @@ -133,7 +133,7 @@ class UserService { requestRecovery = async (email) => { const user = await this.db.userModule.getUserByEmail(email); - const recoveryToken = await this.db.requestRecoveryToken(email); + const recoveryToken = await this.db.recoveryModule.requestRecoveryToken(email); const name = user.firstName; const { clientHost } = this.settingsService.getSettings(); const url = `${clientHost}/set-new-password/${recoveryToken.token}`; @@ -148,11 +148,11 @@ class UserService { }; validateRecovery = async (recoveryToken) => { - await this.db.validateRecoveryToken(recoveryToken); + await this.db.recoveryModule.validateRecoveryToken(recoveryToken); }; resetPassword = async (password, recoveryToken) => { - const user = await this.db.resetPassword(password, recoveryToken); + const user = await this.db.recoveryModule.resetPassword(password, recoveryToken); const appSettings = await this.settingsService.getSettings(); const token = this.issueToken(user._doc, appSettings); return { user, token };