Add app settings model, routes, db ops, service, use settings for issueToken

This commit is contained in:
Alex Holliday committed 2024-09-26 13:41:50 +08:00
1 parent b2bc441c7f
commit 992bf099fa
12 files changed
+210 -19

No files matched your search

+1 -1
View File
@@ -1,4 +1,4 @@
const PORT = process.env.PORT || 5000;
const PORT = 5000;
const connectDbAndRunServer = async (app, db) => {
try {
+16 -8
View File
@@ -25,10 +25,15 @@ const { getTokenFromHeaders } = require("../utils/utils");
* @param {Object} payload
* @returns {String}
*/
const issueToken = (payload) => {
//TODO Add proper expiration date
const tokenTTL = process.env.TOKEN_TTL ? process.env.TOKEN_TTL : "2h";
return jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: tokenTTL });
const issueToken = async (payload, appSettings) => {
try {
const tokenTTL = appSettings.jwtTTL ? appSettings.jwtTTL : "2h";
return jwt.sign(payload, appSettings.jwtSecret, { expiresIn: tokenTTL });
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "issueToken") : null;
next(error);
}
};
/**
@@ -67,7 +72,8 @@ const registerController = async (req, res, next) => {
delete userForToken.profileImage;
delete userForToken.avatarImage;
const token = issueToken(userForToken);
const appSettings = await req.settingsService.getSettings();
const token = issueToken(userForToken, appSettings);
req.emailService
.buildAndSendEmail(
@@ -130,8 +136,8 @@ const loginController = async (req, res, next) => {
delete userWithoutPassword.avatarImage;
// Happy path, return token
const token = issueToken(userWithoutPassword);
const appSettings = req.settingsService.getSettings();
const token = await issueToken(userWithoutPassword, appSettings);
// reset avatar image
userWithoutPassword.avatarImage = user.avatarImage;
@@ -425,7 +431,9 @@ const resetPasswordController = async (req, res, next) => {
}
try {
const user = await req.db.resetPassword(req, res);
const token = issueToken(user._doc);
const appSettings = await req.settingsService.getSettings();
const token = issueToken(user._doc, appSettings);
res.status(200).json({
success: true,
msg: successMessages.AUTH_RESET_PASSWORD,
+4 -4
View File
@@ -34,7 +34,7 @@ const createCheck = async (req, res, next) => {
.status(200)
.json({ success: true, msg: successMessages.CHECK_CREATE, data: check });
} catch (error) {
error.service === undefined ? (error.serivce = SERVICE_NAME) : null;
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "createCheck") : null;
next(error);
}
@@ -62,7 +62,7 @@ const getChecks = async (req, res, next) => {
data: { checksCount, checks },
});
} catch (error) {
error.service === undefined ? (error.serivce = SERVICE_NAME) : null;
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "getChecks") : null;
next(error);
}
@@ -88,7 +88,7 @@ const getTeamChecks = async (req, res, next) => {
data: checkData,
});
} catch (error) {
error.service === undefined ? (error.serivce = SERVICE_NAME) : null;
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "getTeamChecks") : null;
next(error);
}
@@ -114,7 +114,7 @@ const deleteChecks = async (req, res, next) => {
data: { deletedCount },
});
} catch (error) {
error.service === undefined ? (error.serivce = SERVICE_NAME) : null;
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "deleteChecks") : null;
next(error);
}
+20
View File
@@ -0,0 +1,20 @@
const { successMessages } = require("../utils/messages");
const SERVICE_NAME = "SettingsController";
const getAppSettings = async (req, res, next) => {
try {
const settings = await req.db.getAppSettings();
return res.status(200).json({
success: true,
msg: successMessages.GET_APP_SETTINGS,
data: settings,
});
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "getAppSettings") : null;
}
};
module.exports = {
getAppSettings,
};
+20 -1
View File
@@ -1,5 +1,6 @@
const mongoose = require("mongoose");
const UserModel = require("../../models/User");
const AppSettings = require("../../models/AppSettings");
//****************************************
// DB Connection
@@ -7,7 +8,16 @@ const UserModel = require("../../models/User");
const connect = async () => {
try {
await mongoose.connect(process.env.DB_CONNECTION_STRING);
const connectionString =
process.env.DB_CONNECTION_STRING || "mongodb://localhost:27017/uptime_db";
await mongoose.connect(connectionString);
// If there are no AppSettings, create one
let appSettings = await AppSettings.find();
if (appSettings.length === 0) {
appSettings = new AppSettings({});
await appSettings.save();
}
console.log("Connected to MongoDB");
} catch (error) {
console.error("Failed to connect to MongoDB");
@@ -115,12 +125,20 @@ const {
deleteMaintenanceWindowByUserId,
} = require("./modules/maintenaceWindowModule");
//****************************************
// Notifications
//****************************************
const {
createNotification,
getNotificationsByMonitorId,
deleteNotificationsByMonitorId,
} = require("./modules/notificationModule");
//****************************************
// AppSettings
//****************************************
const { getAppSettings } = require("./modules/settingsModule");
module.exports = {
connect,
insertUser,
@@ -168,4 +186,5 @@ module.exports = {
createNotification,
getNotificationsByMonitorId,
deleteNotificationsByMonitorId,
getAppSettings,
};
+17
View File
@@ -0,0 +1,17 @@
const AppSettings = require("../../../models/AppSettings");
const SERVICE_NAME = "SettingsModule";
const getAppSettings = async () => {
try {
const settings = AppSettings.findOne();
return settings;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "getSettings";
throw error;
}
};
module.exports = {
getAppSettings,
};
+1
View File
@@ -35,6 +35,7 @@ const insertUser = async (userData, imageFile) => {
email: userData.email,
});
userData.teamId = team._id;
userData.checkTTL = 60 * 60 * 24 * 30;
await team.save();
}
+11 -5
View File
@@ -5,7 +5,6 @@ const swaggerUi = require("swagger-ui-express");
const express = require("express");
const helmet = require("helmet");
const cors = require("cors");
require("dotenv").config();
const logger = require("./utils/logger");
const { verifyJWT } = require("./middleware/verifyJWT");
const { handleErrors } = require("./middleware/handleErrors");
@@ -15,6 +14,7 @@ const inviteRouter = require("./routes/inviteRoute");
const monitorRouter = require("./routes/monitorRoute");
const checkRouter = require("./routes/checkRoute");
const maintenanceWindowRouter = require("./routes/maintenanceWindowRoute");
const settingsRouter = require("./routes/settingsRoute");
const { connectDbAndRunServer } = require("./configs/db");
const queueRouter = require("./routes/queueRoute");
@@ -22,6 +22,7 @@ const JobQueue = require("./service/jobQueue");
const NetworkService = require("./service/networkService");
const EmailService = require("./service/emailService");
const PageSpeedService = require("./service/pageSpeedService");
const SettingsService = require("./service/settingsService");
const SERVICE_NAME = "Server";
let cleaningUp = false;
@@ -47,9 +48,11 @@ const startApp = async () => {
FakedDB: () => require("./db/FakeDb"),
};
const db = DB_TYPE[process.env.DB_TYPE]
? DB_TYPE[process.env.DB_TYPE]()
: require("./db/FakeDb");
// const db = DB_TYPE[process.env.DB_TYPE]
// ? DB_TYPE[process.env.DB_TYPE]()
// : require("./db/FakeDb");
const db = DB_TYPE.MongoDB();
const app = express();
@@ -60,7 +63,6 @@ const startApp = async () => {
);
app.use(express.json());
app.use(helmet());
// **************************
// Make DB accessible anywhere we have a Request object
// By adding the DB to the request object, we can access it in any route
@@ -72,6 +74,7 @@ const startApp = async () => {
req.jobQueue = jobQueue;
req.emailService = emailService;
req.pageSpeedService = pageSpeedService;
req.settingsService = settingsService;
next();
});
@@ -80,6 +83,7 @@ const startApp = async () => {
//routes
app.use("/api/v1/auth", authRouter);
app.use("/api/v1/settings", verifyJWT, settingsRouter);
app.use("/api/v1/invite", inviteRouter);
app.use("/api/v1/monitors", verifyJWT, monitorRouter);
app.use("/api/v1/checks", verifyJWT, checkRouter);
@@ -126,6 +130,8 @@ const startApp = async () => {
const networkService = new NetworkService(db, emailService);
const jobQueue = await JobQueue.createJobQueue(db, networkService);
const pageSpeedService = new PageSpeedService();
const settingsService = new SettingsService();
settingsService.loadSettings();
const cleanup = async () => {
if (cleaningUp) {
+76
View File
@@ -0,0 +1,76 @@
const mongoose = require("mongoose");
const AppSettingsSchema = mongoose.Schema(
{
apiBaseUrl: {
type: String,
required: true,
default: "http://localhost:5000/api/v1",
},
logLevel: {
type: String,
default: "debug",
enum: ["debug", "none", "error", "warn"],
},
clientHost: {
type: String,
required: true,
default: "http://localhost:5173",
},
jwtSecret: {
type: String,
required: true,
default: "my_secret",
},
dbType: {
type: String,
required: true,
default: "MongoDB",
},
dbConnectionString: {
type: String,
required: true,
default: "mongodb://localhost:27017/uptime_db",
},
redisHost: {
type: String,
required: true,
default: "127.0.0.1",
},
redisPort: {
type: Number,
default: "6379",
},
jwtTTL: {
type: String,
required: true,
default: "99d",
},
pagespeedApiKey: {
type: String,
},
systemEmailHost: {
type: String,
},
systemEmailPort: {
type: Number,
},
systemEmailAddress: {
type: String,
},
systemEmailAddress: {
type: String,
},
singleton: {
type: Boolean,
required: true,
unique: true,
default: true,
},
},
{
timestamps: true,
}
);
module.exports = mongoose.model("AppSettings", AppSettingsSchema);
+8
View File
@@ -0,0 +1,8 @@
const router = require("express").Router();
const settingsController = require("../controllers/settingsController");
const { isAllowed } = require("../middleware/isAllowed");
const Monitor = require("../models/Monitor");
router.get("/", isAllowed(["superadmin"]), settingsController.getAppSettings);
module.exports = router;
+33
View File
@@ -0,0 +1,33 @@
const AppSettings = require("../models/AppSettings");
const SERVICE_NAME = "SettingsService";
class SettingsService {
constructor() {
this.settings = null;
}
async loadSettings() {
if (!this.settings) {
try {
this.settings = await AppSettings.findOne();
if (!this.settings) {
throw new Error("Settings not found");
}
return this.settings;
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "loadSettings") : null;
throw error;
}
}
}
getSettings() {
if (!this.settings) {
throw new Error("Settings have not been loaded");
}
return this.settings;
}
}
module.exports = SettingsService;
+3
View File
@@ -98,6 +98,9 @@ const successMessages = {
//Ping Operations
PING_SUCCESS: "Success",
// App Settings
GET_APP_SETTINGS: "Got app settings successfully",
};
module.exports = {