refactor contexts, format zod errors, and more refactoring

This commit is contained in:
Milo Schwartz
2024-11-03 13:57:51 -05:00
parent 2635443105
commit 2852d62258
83 changed files with 2150 additions and 1264 deletions

View File

@@ -1,13 +1,14 @@
import { Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import { db } from '@server/db';
import { userActions, users } from '@server/db/schema';
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { db } from "@server/db";
import { userActions, users } from "@server/db/schema";
import response from "@server/utils/response";
import HttpCode from '@server/types/HttpCode';
import createHttpError from 'http-errors';
import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
import logger from '@server/logger';
import { eq } from 'drizzle-orm';
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
import logger from "@server/logger";
import { eq } from "drizzle-orm";
import { fromError } from "zod-validation-error";
const addUserActionSchema = z.object({
userId: z.string(),
@@ -15,14 +16,18 @@ const addUserActionSchema = z.object({
orgId: z.string(),
});
export async function addUserAction(req: Request, res: Response, next: NextFunction): Promise<any> {
export async function addUserAction(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedBody = addUserActionSchema.safeParse(req.body);
if (!parsedBody.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedBody.error.errors.map(e => e.message).join(', ')
fromError(parsedBody.error).toString()
)
);
}
@@ -30,22 +35,42 @@ export async function addUserAction(req: Request, res: Response, next: NextFunct
const { userId, actionId, orgId } = parsedBody.data;
// Check if the user has permission to add user actions
const hasPermission = await checkUserActionPermission(ActionsEnum.addUserAction, req);
const hasPermission = await checkUserActionPermission(
ActionsEnum.addUserAction,
req
);
if (!hasPermission) {
return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have permission to perform this action'));
return next(
createHttpError(
HttpCode.FORBIDDEN,
"User does not have permission to perform this action"
)
);
}
// Check if the user exists
const user = await db.select().from(users).where(eq(users.userId, userId)).limit(1);
const user = await db
.select()
.from(users)
.where(eq(users.userId, userId))
.limit(1);
if (user.length === 0) {
return next(createHttpError(HttpCode.NOT_FOUND, `User with ID ${userId} not found`));
return next(
createHttpError(
HttpCode.NOT_FOUND,
`User with ID ${userId} not found`
)
);
}
const newUserAction = await db.insert(userActions).values({
userId,
actionId,
orgId,
}).returning();
const newUserAction = await db
.insert(userActions)
.values({
userId,
actionId,
orgId,
})
.returning();
return response(res, {
data: newUserAction[0],
@@ -56,6 +81,11 @@ export async function addUserAction(req: Request, res: Response, next: NextFunct
});
} catch (error) {
logger.error(error);
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred..."));
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"An error occurred..."
)
);
}
}

View File

@@ -1,87 +0,0 @@
import { Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import { db } from '@server/db';
import { userOrgs, users, roles } from '@server/db/schema';
import { and, eq } from 'drizzle-orm';
import response from "@server/utils/response";
import HttpCode from '@server/types/HttpCode';
import createHttpError from 'http-errors';
import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
import logger from '@server/logger';
const addUserParamsSchema = z.object({
userId: z.string().uuid(),
orgId: z.string()
});
const addUserSchema = z.object({
roleId: z.number().int().positive(),
});
export async function addUserOrg(req: Request, res: Response, next: NextFunction): Promise<any> {
try {
const parsedParams = addUserParamsSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedParams.error.errors.map(e => e.message).join(', ')
)
);
}
const { userId, orgId } = parsedParams.data;
const parsedBody = addUserSchema.safeParse(req.body);
if (!parsedBody.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedBody.error.errors.map(e => e.message).join(', ')
)
);
}
const { roleId } = parsedBody.data;
// Check if the user has permission to add users
const hasPermission = await checkUserActionPermission(ActionsEnum.addUser, req);
if (!hasPermission) {
return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have permission to perform this action'));
}
// Check if the user exists
const user = await db.select().from(users).where(eq(users.userId, userId)).limit(1);
if (user.length === 0) {
return next(createHttpError(HttpCode.NOT_FOUND, `User with ID ${userId} not found`));
}
// Check if the user is already in the organization
const existingUserOrg = await db.select()
.from(userOrgs)
.where(and(eq(userOrgs.userId, userId), eq(userOrgs.orgId, orgId)))
.limit(1);
if (existingUserOrg.length > 0) {
return next(createHttpError(HttpCode.CONFLICT, 'User is already a member of this organization'));
}
// Add the user to the userOrgs table
const newUserOrg = await db.insert(userOrgs).values({
userId,
orgId,
roleId
}).returning();
return response(res, {
data: newUserOrg[0],
success: true,
error: false,
message: "User added to organization successfully",
status: HttpCode.CREATED,
});
} catch (error) {
logger.error(error);
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred..."));
}
}

View File

@@ -1,26 +1,31 @@
import { Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import { db } from '@server/db';
import { userResources } from '@server/db/schema';
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { db } from "@server/db";
import { userResources } from "@server/db/schema";
import response from "@server/utils/response";
import HttpCode from '@server/types/HttpCode';
import createHttpError from 'http-errors';
import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
import logger from '@server/logger';
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
const addUserResourceSchema = z.object({
userId: z.string(),
resourceId: z.string().transform(Number).pipe(z.number().int().positive())
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
});
export async function addUserResource(req: Request, res: Response, next: NextFunction): Promise<any> {
export async function addUserResource(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedBody = addUserResourceSchema.safeParse(req.body);
if (!parsedBody.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedBody.error.errors.map(e => e.message).join(', ')
fromError(parsedBody.error).toString()
)
);
}
@@ -28,15 +33,26 @@ export async function addUserResource(req: Request, res: Response, next: NextFun
const { userId, resourceId } = parsedBody.data;
// Check if the user has permission to add user resources
const hasPermission = await checkUserActionPermission(ActionsEnum.addUserResource, req);
const hasPermission = await checkUserActionPermission(
ActionsEnum.addUserResource,
req
);
if (!hasPermission) {
return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have permission to perform this action'));
return next(
createHttpError(
HttpCode.FORBIDDEN,
"User does not have permission to perform this action"
)
);
}
const newUserResource = await db.insert(userResources).values({
userId,
resourceId,
}).returning();
const newUserResource = await db
.insert(userResources)
.values({
userId,
resourceId,
})
.returning();
return response(res, {
data: newUserResource[0],
@@ -47,6 +63,11 @@ export async function addUserResource(req: Request, res: Response, next: NextFun
});
} catch (error) {
logger.error(error);
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred..."));
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"An error occurred..."
)
);
}
}
}

View File

@@ -1,27 +1,32 @@
import { Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import { db } from '@server/db';
import { resources, userResources, userSites } from '@server/db/schema';
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { db } from "@server/db";
import { resources, userResources, userSites } from "@server/db/schema";
import response from "@server/utils/response";
import HttpCode from '@server/types/HttpCode';
import createHttpError from 'http-errors';
import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
import logger from '@server/logger';
import { eq } from 'drizzle-orm';
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
import logger from "@server/logger";
import { eq } from "drizzle-orm";
import { fromError } from "zod-validation-error";
const addUserSiteSchema = z.object({
userId: z.string(),
siteId: z.string().transform(Number).pipe(z.number().int().positive()),
});
export async function addUserSite(req: Request, res: Response, next: NextFunction): Promise<any> {
export async function addUserSite(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedBody = addUserSiteSchema.safeParse(req.body);
if (!parsedBody.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedBody.error.errors.map(e => e.message).join(', ')
fromError(parsedBody.error).toString()
)
);
}
@@ -29,18 +34,30 @@ export async function addUserSite(req: Request, res: Response, next: NextFunctio
const { userId, siteId } = parsedBody.data;
// Check if the user has permission to add user sites
const hasPermission = await checkUserActionPermission(ActionsEnum.addUserSite, req);
const hasPermission = await checkUserActionPermission(
ActionsEnum.addUserSite,
req
);
if (!hasPermission) {
return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have permission to perform this action'));
return next(
createHttpError(
HttpCode.FORBIDDEN,
"User does not have permission to perform this action"
)
);
}
const newUserSite = await db.insert(userSites).values({
userId,
siteId,
}).returning();
const newUserSite = await db
.insert(userSites)
.values({
userId,
siteId,
})
.returning();
// Add all resources associated with the site to the user
const siteResources = await db.select()
const siteResources = await db
.select()
.from(resources)
.where(eq(resources.siteId, siteId));
@@ -60,6 +77,11 @@ export async function addUserSite(req: Request, res: Response, next: NextFunctio
});
} catch (error) {
logger.error(error);
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred..."));
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"An error occurred..."
)
);
}
}
}

View File

@@ -1,6 +1,5 @@
export * from "./getUser";
export * from "./removeUserOrg";
export * from "./addUserOrg";
export * from "./listUsers";
export * from "./setUserRole";
export * from "./inviteUser";

View File

@@ -1,13 +1,14 @@
import { Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import { db } from '@server/db';
import { userActions } from '@server/db/schema';
import { and, eq } from 'drizzle-orm';
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { db } from "@server/db";
import { userActions } from "@server/db/schema";
import { and, eq } from "drizzle-orm";
import response from "@server/utils/response";
import HttpCode from '@server/types/HttpCode';
import createHttpError from 'http-errors';
import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
import logger from '@server/logger';
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
const removeUserActionParamsSchema = z.object({
userId: z.string(),
@@ -15,17 +16,21 @@ const removeUserActionParamsSchema = z.object({
const removeUserActionSchema = z.object({
actionId: z.string(),
orgId: z.string()
orgId: z.string(),
});
export async function removeUserAction(req: Request, res: Response, next: NextFunction): Promise<any> {
export async function removeUserAction(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedParams = removeUserActionParamsSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedParams.error.errors.map(e => e.message).join(', ')
fromError(parsedParams.error).toString()
)
);
}
@@ -37,7 +42,7 @@ export async function removeUserAction(req: Request, res: Response, next: NextFu
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedBody.error.errors.map(e => e.message).join(', ')
fromError(parsedBody.error).toString()
)
);
}
@@ -45,17 +50,28 @@ export async function removeUserAction(req: Request, res: Response, next: NextFu
const { actionId, orgId } = parsedBody.data;
// Check if the user has permission to remove user actions
const hasPermission = await checkUserActionPermission(ActionsEnum.removeUserAction, req);
const hasPermission = await checkUserActionPermission(
ActionsEnum.removeUserAction,
req
);
if (!hasPermission) {
return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have permission to perform this action'));
return next(
createHttpError(
HttpCode.FORBIDDEN,
"User does not have permission to perform this action"
)
);
}
const deletedUserAction = await db.delete(userActions)
.where(and(
eq(userActions.userId, userId),
eq(userActions.actionId, actionId),
eq(userActions.orgId, orgId)
))
const deletedUserAction = await db
.delete(userActions)
.where(
and(
eq(userActions.userId, userId),
eq(userActions.actionId, actionId),
eq(userActions.orgId, orgId)
)
)
.returning();
if (deletedUserAction.length === 0) {
@@ -76,6 +92,11 @@ export async function removeUserAction(req: Request, res: Response, next: NextFu
});
} catch (error) {
logger.error(error);
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred..."));
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"An error occurred..."
)
);
}
}
}

View File

@@ -1,27 +1,32 @@
import { Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import { db } from '@server/db';
import { userOrgs, users } from '@server/db/schema';
import { and, eq } from 'drizzle-orm';
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { db } from "@server/db";
import { userOrgs, users } from "@server/db/schema";
import { and, eq } from "drizzle-orm";
import response from "@server/utils/response";
import HttpCode from '@server/types/HttpCode';
import createHttpError from 'http-errors';
import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
import logger from '@server/logger';
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
const removeUserSchema = z.object({
userId: z.string().uuid(),
orgId: z.string()
orgId: z.string(),
});
export async function removeUserOrg(req: Request, res: Response, next: NextFunction): Promise<any> {
export async function removeUserOrg(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedParams = removeUserSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedParams.error.errors.map(e => e.message).join(', ')
fromError(parsedParams.error).toString()
)
);
}
@@ -29,13 +34,22 @@ export async function removeUserOrg(req: Request, res: Response, next: NextFunct
const { userId, orgId } = parsedParams.data;
// Check if the user has permission to list sites
const hasPermission = await checkUserActionPermission(ActionsEnum.removeUser, req);
const hasPermission = await checkUserActionPermission(
ActionsEnum.removeUser,
req
);
if (!hasPermission) {
return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have permission to perform this action'));
return next(
createHttpError(
HttpCode.FORBIDDEN,
"User does not have permission to perform this action"
)
);
}
// remove the user from the userOrgs table
await db.delete(userOrgs)
await db
.delete(userOrgs)
.where(and(eq(userOrgs.userId, userId), eq(userOrgs.orgId, orgId)));
return response(res, {
@@ -47,6 +61,11 @@ export async function removeUserOrg(req: Request, res: Response, next: NextFunct
});
} catch (error) {
logger.error(error);
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred..."));
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"An error occurred..."
)
);
}
}

View File

@@ -1,27 +1,32 @@
import { Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import { db } from '@server/db';
import { userResources } from '@server/db/schema';
import { and, eq } from 'drizzle-orm';
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { db } from "@server/db";
import { userResources } from "@server/db/schema";
import { and, eq } from "drizzle-orm";
import response from "@server/utils/response";
import HttpCode from '@server/types/HttpCode';
import createHttpError from 'http-errors';
import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
import logger from '@server/logger';
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
const removeUserResourceSchema = z.object({
userId: z.string(),
resourceId: z.string().transform(Number).pipe(z.number().int().positive())
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
});
export async function removeUserResource(req: Request, res: Response, next: NextFunction): Promise<any> {
export async function removeUserResource(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedParams = removeUserResourceSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedParams.error.errors.map(e => e.message).join(', ')
fromError(parsedParams.error).toString()
)
);
}
@@ -29,13 +34,27 @@ export async function removeUserResource(req: Request, res: Response, next: Next
const { userId, resourceId } = parsedParams.data;
// Check if the user has permission to remove user resources
const hasPermission = await checkUserActionPermission(ActionsEnum.removeUserResource, req);
const hasPermission = await checkUserActionPermission(
ActionsEnum.removeUserResource,
req
);
if (!hasPermission) {
return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have permission to perform this action'));
return next(
createHttpError(
HttpCode.FORBIDDEN,
"User does not have permission to perform this action"
)
);
}
const deletedUserResource = await db.delete(userResources)
.where(and(eq(userResources.userId, userId), eq(userResources.resourceId, resourceId)))
const deletedUserResource = await db
.delete(userResources)
.where(
and(
eq(userResources.userId, userId),
eq(userResources.resourceId, resourceId)
)
)
.returning();
if (deletedUserResource.length === 0) {
@@ -56,6 +75,11 @@ export async function removeUserResource(req: Request, res: Response, next: Next
});
} catch (error) {
logger.error(error);
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred..."));
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"An error occurred..."
)
);
}
}
}

View File

@@ -1,13 +1,14 @@
import { Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import { db } from '@server/db';
import { resources, userResources, userSites } from '@server/db/schema';
import { and, eq } from 'drizzle-orm';
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { db } from "@server/db";
import { resources, userResources, userSites } from "@server/db/schema";
import { and, eq } from "drizzle-orm";
import response from "@server/utils/response";
import HttpCode from '@server/types/HttpCode';
import createHttpError from 'http-errors';
import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
import logger from '@server/logger';
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
const removeUserSiteParamsSchema = z.object({
userId: z.string(),
@@ -17,14 +18,18 @@ const removeUserSiteSchema = z.object({
siteId: z.number().int().positive(),
});
export async function removeUserSite(req: Request, res: Response, next: NextFunction): Promise<any> {
export async function removeUserSite(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedParams = removeUserSiteParamsSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedParams.error.errors.map(e => e.message).join(', ')
fromError(parsedParams.error).toString()
)
);
}
@@ -36,7 +41,7 @@ export async function removeUserSite(req: Request, res: Response, next: NextFunc
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedBody.error.errors.map(e => e.message).join(', ')
fromError(parsedBody.error).toString()
)
);
}
@@ -44,13 +49,24 @@ export async function removeUserSite(req: Request, res: Response, next: NextFunc
const { siteId } = parsedBody.data;
// Check if the user has permission to remove user sites
const hasPermission = await checkUserActionPermission(ActionsEnum.removeUserSite, req);
const hasPermission = await checkUserActionPermission(
ActionsEnum.removeUserSite,
req
);
if (!hasPermission) {
return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have permission to perform this action'));
return next(
createHttpError(
HttpCode.FORBIDDEN,
"User does not have permission to perform this action"
)
);
}
const deletedUserSite = await db.delete(userSites)
.where(and(eq(userSites.userId, userId), eq(userSites.siteId, siteId)))
const deletedUserSite = await db
.delete(userSites)
.where(
and(eq(userSites.userId, userId), eq(userSites.siteId, siteId))
)
.returning();
if (deletedUserSite.length === 0) {
@@ -62,13 +78,20 @@ export async function removeUserSite(req: Request, res: Response, next: NextFunc
);
}
const siteResources = await db.select()
const siteResources = await db
.select()
.from(resources)
.where(eq(resources.siteId, siteId));
for (const resource of siteResources) {
await db.delete(userResources)
.where(and(eq(userResources.userId, userId), eq(userResources.resourceId, resource.resourceId)))
await db
.delete(userResources)
.where(
and(
eq(userResources.userId, userId),
eq(userResources.resourceId, resource.resourceId)
)
)
.returning();
}
@@ -81,6 +104,11 @@ export async function removeUserSite(req: Request, res: Response, next: NextFunc
});
} catch (error) {
logger.error(error);
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred..."));
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"An error occurred..."
)
);
}
}
}

View File

@@ -1,28 +1,33 @@
import { Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import { db } from '@server/db';
import { userOrgs, roles } from '@server/db/schema';
import { eq, and } from 'drizzle-orm';
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { db } from "@server/db";
import { userOrgs, roles } from "@server/db/schema";
import { eq, and } from "drizzle-orm";
import response from "@server/utils/response";
import HttpCode from '@server/types/HttpCode';
import createHttpError from 'http-errors';
import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
import logger from '@server/logger';
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
const addUserRoleSchema = z.object({
userId: z.string(),
roleId: z.number().int().positive(),
orgId: z.string()
orgId: z.string(),
});
export async function addUserRole(req: Request, res: Response, next: NextFunction): Promise<any> {
export async function addUserRole(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedBody = addUserRoleSchema.safeParse(req.body);
if (!parsedBody.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedBody.error.errors.map(e => e.message).join(', ')
fromError(parsedBody.error).toString()
)
);
}
@@ -30,22 +35,37 @@ export async function addUserRole(req: Request, res: Response, next: NextFunctio
const { userId, roleId, orgId } = parsedBody.data;
// Check if the user has permission to add user roles
const hasPermission = await checkUserActionPermission(ActionsEnum.addUserRole, req);
const hasPermission = await checkUserActionPermission(
ActionsEnum.addUserRole,
req
);
if (!hasPermission) {
return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have permission to perform this action'));
return next(
createHttpError(
HttpCode.FORBIDDEN,
"User does not have permission to perform this action"
)
);
}
// Check if the role exists and belongs to the specified org
const roleExists = await db.select()
const roleExists = await db
.select()
.from(roles)
.where(and(eq(roles.roleId, roleId), eq(roles.orgId, orgId)))
.limit(1);
if (roleExists.length === 0) {
return next(createHttpError(HttpCode.NOT_FOUND, 'Role not found or does not belong to the specified organization'));
return next(
createHttpError(
HttpCode.NOT_FOUND,
"Role not found or does not belong to the specified organization"
)
);
}
const newUserRole = await db.update(userOrgs)
const newUserRole = await db
.update(userOrgs)
.set({ roleId })
.where(and(eq(userOrgs.userId, userId), eq(userOrgs.orgId, orgId)))
.returning();
@@ -59,6 +79,11 @@ export async function addUserRole(req: Request, res: Response, next: NextFunctio
});
} catch (error) {
logger.error(error);
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred..."));
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"An error occurred..."
)
);
}
}
}