Merge pull request #2517 from bluewave-labs/feat/team-access-middleware

feat: add middleware for verifying team access
This commit is contained in:
Alexander Holliday
2025-06-24 10:03:00 +08:00
committed by GitHub
5 changed files with 70 additions and 8 deletions

View File

@@ -8,6 +8,7 @@ const verifyOwnership = (Model, paramName) => {
return async (req, res, next) => {
const userId = req.user._id;
const documentId = req.params[paramName];
try {
const doc = await Model.findById(documentId);
//If the document is not found, return a 404 error
@@ -35,7 +36,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(stringService.verifyOwnerUnauthorized);
const error = new Error("Unauthorized");
error.status = 403;
throw error;
}

View File

@@ -0,0 +1,38 @@
const SERVICE_NAME = "verifyTeamAccess";
const verifyTeamAccess = (Model, paramName) => {
return async (req, res, next) => {
try {
const documentId = req.params[paramName];
const doc = await Model.findById(documentId);
if (!doc) {
const error = new Error("Document not found");
error.status = 404;
throw error;
}
if (!req?.user?.teamId || !doc.teamId) {
const error = new Error("Missing team information");
error.status = 400;
throw error;
}
if (req.user.teamId.toString() === doc.teamId.toString()) {
next();
return;
}
const error = new Error("Unauthorized");
error.status = 403;
throw error;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "verifyTeamAccess";
next(error);
return;
}
};
};
export { verifyTeamAccess };

View File

@@ -1,7 +1,8 @@
import { Router } from "express";
import { verifyOwnership } from "../middleware/verifyOwnership.js";
import { verifyTeamAccess } from "../middleware/verifyTeamAccess.js";
import Monitor from "../db/models/Monitor.js";
import MaintenanceWindow from "../db/models/MaintenanceWindow.js";
class MaintenanceWindowRoutes {
constructor(maintenanceWindowController) {
this.router = Router();
@@ -24,9 +25,17 @@ class MaintenanceWindowRoutes {
this.router.get("/:id", this.maintenanceWindowController.getMaintenanceWindowById);
this.router.put("/:id", this.maintenanceWindowController.editMaintenanceWindow);
this.router.put(
"/:id",
verifyTeamAccess(MaintenanceWindow, "id"),
this.maintenanceWindowController.editMaintenanceWindow
);
this.router.delete("/:id", this.maintenanceWindowController.deleteMaintenanceWindow);
this.router.delete(
"/:id",
verifyTeamAccess(MaintenanceWindow, "id"),
this.maintenanceWindowController.deleteMaintenanceWindow
);
}
getRouter() {

View File

@@ -2,7 +2,9 @@ import { Router } from "express";
import { isAllowed } from "../middleware/isAllowed.js";
import multer from "multer";
import { fetchMonitorCertificate } from "../controllers/controllerUtils.js";
import Monitor from "../db/models/Monitor.js";
import { verifyOwnership } from "../middleware/verifyOwnership.js";
import { verifyTeamAccess } from "../middleware/verifyTeamAccess.js";
const upload = multer({
storage: multer.memoryStorage(), // Store file in memory as Buffer
});
@@ -62,6 +64,7 @@ class MonitorRoutes {
this.router.delete(
"/:monitorId",
verifyOwnership(Monitor, "monitorId"),
isAllowed(["admin", "superadmin"]),
this.monitorController.deleteMonitor
);
@@ -74,6 +77,7 @@ class MonitorRoutes {
this.router.put(
"/:monitorId",
verifyTeamAccess(Monitor, "monitorId"),
isAllowed(["admin", "superadmin"]),
this.monitorController.editMonitor
);

View File

@@ -1,6 +1,8 @@
import { Router } from "express";
import { verifyJWT } from "../middleware/verifyJWT.js";
import { verifyOwnership } from "../middleware/verifyOwnership.js";
import { verifyTeamAccess } from "../middleware/verifyTeamAccess.js";
import Notification from "../db/models/Notification.js";
class NotificationRoutes {
constructor(notificationController) {
this.router = Router();
@@ -18,10 +20,18 @@ class NotificationRoutes {
this.router.get("/team", this.notificationController.getNotificationsByTeamId);
this.router.delete("/:id", this.notificationController.deleteNotification);
this.router.delete(
"/:id",
verifyOwnership(Notification, "id"),
this.notificationController.deleteNotification
);
this.router.get("/:id", this.notificationController.getNotificationById);
this.router.put("/:id", this.notificationController.editNotification);
this.router.put(
"/:id",
verifyTeamAccess(Notification, "id"),
this.notificationController.editNotification
);
}
getRouter() {