diff --git a/server/routers/auth/verifyUserIsOrgOwner.ts b/server/routers/auth/verifyUserIsOrgOwner.ts new file mode 100644 index 00000000..5314b52a --- /dev/null +++ b/server/routers/auth/verifyUserIsOrgOwner.ts @@ -0,0 +1,68 @@ +import { Request, Response, NextFunction } from "express"; +import { db } from "@server/db"; +import { userOrgs } from "@server/db/schema"; +import { and, eq } from "drizzle-orm"; +import createHttpError from "http-errors"; +import HttpCode from "@server/types/HttpCode"; + +export async function verifyUserIsOrgOwner( + req: Request, + res: Response, + next: NextFunction +) { + const userId = req.user!.userId; + const orgId = req.params.orgId; + let userOrg = req.userOrg; + + if (!userId) { + return next( + createHttpError(HttpCode.UNAUTHORIZED, "User not authenticated") + ); + } + + if (!orgId) { + return next( + createHttpError( + HttpCode.BAD_REQUEST, + "Organization ID not provided" + ) + ); + } + + try { + if (!userOrg) { + const res = await db + .select() + .from(userOrgs) + .where( + and(eq(userOrgs.userId, userId), eq(userOrgs.orgId, orgId)) + ); + userOrg = res[0]; + } + + if (!userOrg) { + return next( + createHttpError( + HttpCode.FORBIDDEN, + "User does not have access to this organization" + ) + ); + } + + if (!userOrg.isOwner) { + return next( + createHttpError( + HttpCode.FORBIDDEN, + "User is not an organization owner" + ) + ); + } + } catch (e) { + return next( + createHttpError( + HttpCode.INTERNAL_SERVER_ERROR, + "Error verifying organization access" + ) + ); + } +} diff --git a/server/routers/external.ts b/server/routers/external.ts index 0d5df100..56524fac 100644 --- a/server/routers/external.ts +++ b/server/routers/external.ts @@ -25,6 +25,7 @@ import { } from "./auth"; import { verifyUserHasAction } from "./auth/verifyUserHasAction"; import { ActionsEnum } from "@server/auth/actions"; +import { verifyUserIsOrgOwner } from "./auth/verifyUserIsOrgOwner"; // Root routes export const unauthenticated = Router(); @@ -52,7 +53,12 @@ authenticated.post( verifyUserHasAction(ActionsEnum.updateOrg), org.updateOrg ); -// authenticated.delete("/org/:orgId", verifyOrgAccess, org.deleteOrg); +// authenticated.delete( +// "/org/:orgId", +// verifyOrgAccess, +// verifyUserIsOrgOwner, +// org.deleteOrg +// ); authenticated.put( "/org/:orgId/site", diff --git a/server/routers/user/removeUserOrg.ts b/server/routers/user/removeUserOrg.ts index 805089c3..3e5182fb 100644 --- a/server/routers/user/removeUserOrg.ts +++ b/server/routers/user/removeUserOrg.ts @@ -32,6 +32,25 @@ export async function removeUserOrg( const { userId, orgId } = parsedParams.data; + // get the user first + const user = await db + .select() + .from(userOrgs) + .where(eq(userOrgs.userId, userId)); + + if (!user || user.length === 0) { + return next(createHttpError(HttpCode.NOT_FOUND, "User not found")); + } + + if (user[0].isOwner) { + return next( + createHttpError( + HttpCode.BAD_REQUEST, + "Cannot remove owner from org" + ) + ); + } + // remove the user from the userOrgs table await db .delete(userOrgs)