diff --git a/server/config.ts b/server/config.ts
index 228072fb..665f3882 100644
--- a/server/config.ts
+++ b/server/config.ts
@@ -120,7 +120,8 @@ if (!parsedConfig.success) {
throw new Error(`Invalid configuration file: ${errors}`);
}
-process.env.SERVER_EXTERNAL_PORT = parsedConfig.data.server.external_port.toString();
+process.env.SERVER_EXTERNAL_PORT =
+ parsedConfig.data.server.external_port.toString();
process.env.FLAGS_EMAIL_VERIFICATION_REQUIRED = parsedConfig.data.flags
?.require_email_verification
? "true"
diff --git a/server/routers/external.ts b/server/routers/external.ts
index 1b13f058..d57327f9 100644
--- a/server/routers/external.ts
+++ b/server/routers/external.ts
@@ -47,7 +47,7 @@ authenticated.get("/org/:orgId/sites", verifyOrgAccess, site.listSites);
authenticated.get("/org/:orgId/site/:niceId", verifyOrgAccess, site.getSite);
authenticated.get(
- "/org/:orgId/pickSiteDefaults",
+ "/org/:orgId/pick-site-defaults",
verifyOrgAccess,
site.pickSiteDefaults
);
@@ -118,12 +118,12 @@ authenticated.delete(
target.deleteTarget
);
-authenticated.put(
- "/org/:orgId/role",
- verifyOrgAccess,
- verifySuperuser,
- role.createRole
-);
+// authenticated.put(
+// "/org/:orgId/role",
+// verifyOrgAccess,
+// verifySuperuser,
+// role.createRole
+// );
authenticated.get("/org/:orgId/roles", verifyOrgAccess, role.listRoles);
authenticated.get(
"/role/:roleId",
@@ -131,18 +131,18 @@ authenticated.get(
verifyUserInRole,
role.getRole
);
-authenticated.post(
- "/role/:roleId",
- verifyRoleAccess,
- verifySuperuser,
- role.updateRole
-);
-authenticated.delete(
- "/role/:roleId",
- verifyRoleAccess,
- verifySuperuser,
- role.deleteRole
-);
+// authenticated.post(
+// "/role/:roleId",
+// verifyRoleAccess,
+// verifySuperuser,
+// role.updateRole
+// );
+// authenticated.delete(
+// "/role/:roleId",
+// verifyRoleAccess,
+// verifySuperuser,
+// role.deleteRole
+// );
authenticated.put(
"/role/:roleId/site",
@@ -210,12 +210,6 @@ authenticated.delete(
verifyUserAccess,
user.removeUserOrg
);
-authenticated.put(
- "/org/:orgId/user/:userId",
- verifyOrgAccess,
- verifyUserAccess,
- user.addUserOrg
-);
authenticated.put(
"/user/:userId/site",
diff --git a/server/routers/gerbil/getConfig.ts b/server/routers/gerbil/getConfig.ts
index 1eeb881c..a45806f0 100644
--- a/server/routers/gerbil/getConfig.ts
+++ b/server/routers/gerbil/getConfig.ts
@@ -10,6 +10,7 @@ import logger from '@server/logger';
import config from "@server/config";
import { getUniqueExitNodeEndpointName } from '@server/db/names';
import { findNextAvailableCidr } from "@server/utils/ip";
+import { fromError } from 'zod-validation-error';
// Define Zod schema for request validation
const getConfigSchema = z.object({
publicKey: z.string(),
@@ -33,7 +34,7 @@ export async function getConfig(req: Request, res: Response, next: NextFunction)
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
diff --git a/server/routers/org/checkId.ts b/server/routers/org/checkId.ts
index 741738e8..7ab2fe58 100644
--- a/server/routers/org/checkId.ts
+++ b/server/routers/org/checkId.ts
@@ -1,32 +1,38 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { orgs } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { orgs } from "@server/db/schema";
+import { eq } from "drizzle-orm";
import response from "@server/utils/response";
-import HttpCode from '@server/types/HttpCode';
-import createHttpError from 'http-errors';
-import logger from '@server/logger';
+import HttpCode from "@server/types/HttpCode";
+import createHttpError from "http-errors";
+import logger from "@server/logger";
+import { fromError } from "zod-validation-error";
const getOrgSchema = z.object({
- orgId: z.string()
+ orgId: z.string(),
});
-export async function checkId(req: Request, res: Response, next: NextFunction): Promise {
+export async function checkId(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedQuery = getOrgSchema.safeParse(req.query);
if (!parsedQuery.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedQuery.error.errors.map(e => e.message).join(', ')
+ fromError(parsedQuery.error).toString()
)
);
}
const { orgId } = parsedQuery.data;
- const org = await db.select()
+ const org = await db
+ .select()
.from(orgs)
.where(eq(orgs.orgId, orgId))
.limit(1);
@@ -50,6 +56,11 @@ export async function checkId(req: Request, res: Response, next: NextFunction):
});
} 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..."
+ )
+ );
}
}
diff --git a/server/routers/org/createOrg.ts b/server/routers/org/createOrg.ts
index 2c504660..9f4854dc 100644
--- a/server/routers/org/createOrg.ts
+++ b/server/routers/org/createOrg.ts
@@ -10,6 +10,7 @@ import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
import logger from '@server/logger';
import { createSuperuserRole } from '@server/db/ensureActions';
import config, { APP_PATH } from "@server/config";
+import { fromError } from 'zod-validation-error';
const createOrgSchema = z.object({
orgId: z.string(),
@@ -26,7 +27,7 @@ export async function createOrg(req: Request, res: Response, next: NextFunction)
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
diff --git a/server/routers/org/deleteOrg.ts b/server/routers/org/deleteOrg.ts
index 44a1a6e8..24f306aa 100644
--- a/server/routers/org/deleteOrg.ts
+++ b/server/routers/org/deleteOrg.ts
@@ -8,6 +8,7 @@ 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 deleteOrgSchema = z.object({
orgId: z.string()
@@ -20,7 +21,7 @@ export async function deleteOrg(req: Request, res: Response, next: NextFunction)
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
diff --git a/server/routers/org/updateOrg.ts b/server/routers/org/updateOrg.ts
index 44f757cf..e721f641 100644
--- a/server/routers/org/updateOrg.ts
+++ b/server/routers/org/updateOrg.ts
@@ -8,6 +8,7 @@ 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 updateOrgParamsSchema = z.object({
orgId: z.string()
@@ -27,7 +28,7 @@ export async function updateOrg(req: Request, res: Response, next: NextFunction)
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -37,7 +38,7 @@ export async function updateOrg(req: Request, res: Response, next: NextFunction)
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
diff --git a/server/routers/resource/createResource.ts b/server/routers/resource/createResource.ts
index cb054243..77f28820 100644
--- a/server/routers/resource/createResource.ts
+++ b/server/routers/resource/createResource.ts
@@ -9,6 +9,7 @@ import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
import logger from '@server/logger';
import { eq, and } from 'drizzle-orm';
import stoi from '@server/utils/stoi';
+import { fromError } from 'zod-validation-error';
const createResourceParamsSchema = z.object({
siteId: z.string().optional().transform(stoi).pipe(z.number().int().positive().optional()),
@@ -29,7 +30,7 @@ export async function createResource(req: Request, res: Response, next: NextFunc
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
@@ -42,7 +43,7 @@ export async function createResource(req: Request, res: Response, next: NextFunc
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
diff --git a/server/routers/resource/deleteResource.ts b/server/routers/resource/deleteResource.ts
index ffb15286..5fb70e17 100644
--- a/server/routers/resource/deleteResource.ts
+++ b/server/routers/resource/deleteResource.ts
@@ -1,20 +1,25 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { resources } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { resources } from "@server/db/schema";
+import { 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";
// Define Zod schema for request parameters validation
const deleteResourceSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function deleteResource(req: Request, res: Response, next: NextFunction): Promise {
+export async function deleteResource(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
// Validate request parameters
const parsedParams = deleteResourceSchema.safeParse(req.params);
@@ -22,7 +27,7 @@ export async function deleteResource(req: Request, res: Response, next: NextFunc
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -30,13 +35,22 @@ export async function deleteResource(req: Request, res: Response, next: NextFunc
const { resourceId } = parsedParams.data;
// Check if the user has permission to list sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.deleteResource, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.deleteResource,
+ 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"
+ )
+ );
}
// Delete the resource from the database
- const deletedResource = await db.delete(resources)
+ const deletedResource = await db
+ .delete(resources)
.where(eq(resources.resourceId, resourceId))
.returning();
@@ -58,6 +72,11 @@ export async function deleteResource(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..."
+ )
+ );
}
}
diff --git a/server/routers/resource/getResource.ts b/server/routers/resource/getResource.ts
index 21b361e0..122e9dbb 100644
--- a/server/routers/resource/getResource.ts
+++ b/server/routers/resource/getResource.ts
@@ -1,13 +1,14 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { resources } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { resources } from "@server/db/schema";
+import { 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";
// Define Zod schema for request parameters validation
const getResourceSchema = z.object({
@@ -19,9 +20,13 @@ export type GetResourceResponse = {
siteId: number;
orgId: string;
name: string;
-}
+};
-export async function getResource(req: Request, res: Response, next: NextFunction): Promise {
+export async function getResource(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
// Validate request parameters
const parsedParams = getResourceSchema.safeParse(req.params);
@@ -29,7 +34,7 @@ export async function getResource(req: Request, res: Response, next: NextFunctio
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -37,13 +42,22 @@ export async function getResource(req: Request, res: Response, next: NextFunctio
const { resourceId } = parsedParams.data;
// Check if the user has permission to list sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.getResource, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.getResource,
+ 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"
+ )
+ );
}
// Fetch the resource from the database
- const resource = await db.select()
+ const resource = await db
+ .select()
.from(resources)
.where(eq(resources.resourceId, resourceId))
.limit(1);
@@ -62,7 +76,7 @@ export async function getResource(req: Request, res: Response, next: NextFunctio
resourceId: resource[0].resourceId,
siteId: resource[0].siteId,
orgId: resource[0].orgId,
- name: resource[0].name
+ name: resource[0].name,
},
success: true,
error: false,
@@ -71,6 +85,11 @@ export async function getResource(req: Request, res: Response, next: NextFunctio
});
} catch (error) {
throw error;
- return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred..."));
+ return next(
+ createHttpError(
+ HttpCode.INTERNAL_SERVER_ERROR,
+ "An error occurred..."
+ )
+ );
}
}
diff --git a/server/routers/resource/listResourceRoles.ts b/server/routers/resource/listResourceRoles.ts
index 4883be49..aa624733 100644
--- a/server/routers/resource/listResourceRoles.ts
+++ b/server/routers/resource/listResourceRoles.ts
@@ -1,26 +1,31 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roleResources, roles } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { roleResources, roles } from "@server/db/schema";
+import { 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 listResourceRolesSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function listResourceRoles(req: Request, res: Response, next: NextFunction): Promise {
+export async function listResourceRoles(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = listResourceRolesSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -28,9 +33,17 @@ export async function listResourceRoles(req: Request, res: Response, next: NextF
const { resourceId } = parsedParams.data;
// Check if the user has permission to list resource roles
- const hasPermission = await checkUserActionPermission(ActionsEnum.listResourceRoles, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.listResourceRoles,
+ 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 resourceRolesList = await db
@@ -53,6 +66,11 @@ export async function listResourceRoles(req: Request, res: Response, next: NextF
});
} 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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/resource/updateResource.ts b/server/routers/resource/updateResource.ts
index a03ef573..5b208f9a 100644
--- a/server/routers/resource/updateResource.ts
+++ b/server/routers/resource/updateResource.ts
@@ -1,13 +1,14 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { resources } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { resources } from "@server/db/schema";
+import { 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";
// Define Zod schema for request parameters validation
const updateResourceParamsSchema = z.object({
@@ -15,14 +16,20 @@ const updateResourceParamsSchema = z.object({
});
// Define Zod schema for request body validation
-const updateResourceBodySchema = z.object({
- name: z.string().min(1).max(255).optional(),
- subdomain: z.string().min(1).max(255).optional(),
-}).refine(data => Object.keys(data).length > 0, {
- message: "At least one field must be provided for update"
-});
+const updateResourceBodySchema = z
+ .object({
+ name: z.string().min(1).max(255).optional(),
+ subdomain: z.string().min(1).max(255).optional(),
+ })
+ .refine((data) => Object.keys(data).length > 0, {
+ message: "At least one field must be provided for update",
+ });
-export async function updateResource(req: Request, res: Response, next: NextFunction): Promise {
+export async function updateResource(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
// Validate request parameters
const parsedParams = updateResourceParamsSchema.safeParse(req.params);
@@ -30,7 +37,7 @@ export async function updateResource(req: Request, res: Response, next: NextFunc
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -41,7 +48,7 @@ export async function updateResource(req: Request, res: Response, next: NextFunc
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
@@ -50,13 +57,22 @@ export async function updateResource(req: Request, res: Response, next: NextFunc
const updateData = parsedBody.data;
// Check if the user has permission to list sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.updateResource, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.updateResource,
+ 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"
+ )
+ );
}
// Update the resource in the database
- const updatedResource = await db.update(resources)
+ const updatedResource = await db
+ .update(resources)
.set(updateData)
.where(eq(resources.resourceId, resourceId))
.returning();
@@ -79,6 +95,11 @@ export async function updateResource(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..."
+ )
+ );
}
}
diff --git a/server/routers/role/addRoleAction.ts b/server/routers/role/addRoleAction.ts
index 5e677aa4..99944b89 100644
--- a/server/routers/role/addRoleAction.ts
+++ b/server/routers/role/addRoleAction.ts
@@ -1,13 +1,14 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roleActions, roles } from '@server/db/schema';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { roleActions, roles } 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 addRoleActionParamSchema = z.object({
roleId: z.string().transform(Number).pipe(z.number().int().positive()),
@@ -17,14 +18,18 @@ const addRoleActionSchema = z.object({
actionId: z.string(),
});
-export async function addRoleAction(req: Request, res: Response, next: NextFunction): Promise {
+export async function addRoleAction(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedBody = addRoleActionSchema.safeParse(req.body);
if (!parsedBody.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
@@ -36,7 +41,7 @@ export async function addRoleAction(req: Request, res: Response, next: NextFunct
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -44,22 +49,42 @@ export async function addRoleAction(req: Request, res: Response, next: NextFunct
const { roleId } = parsedParams.data;
// Check if the user has permission to add role actions
- const hasPermission = await checkUserActionPermission(ActionsEnum.addRoleAction, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.addRoleAction,
+ 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"
+ )
+ );
}
// Get the orgId for the role
- const role = await db.select({ orgId: roles.orgId }).from(roles).where(eq(roles.roleId, roleId)).limit(1);
+ const role = await db
+ .select({ orgId: roles.orgId })
+ .from(roles)
+ .where(eq(roles.roleId, roleId))
+ .limit(1);
if (role.length === 0) {
- return next(createHttpError(HttpCode.NOT_FOUND, `Role with ID ${roleId} not found`));
+ return next(
+ createHttpError(
+ HttpCode.NOT_FOUND,
+ `Role with ID ${roleId} not found`
+ )
+ );
}
- const newRoleAction = await db.insert(roleActions).values({
- roleId,
- actionId,
- orgId: role[0].orgId!,
- }).returning();
+ const newRoleAction = await db
+ .insert(roleActions)
+ .values({
+ roleId,
+ actionId,
+ orgId: role[0].orgId!,
+ })
+ .returning();
return response(res, {
data: newRoleAction[0],
@@ -70,6 +95,11 @@ export async function addRoleAction(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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/role/addRoleResource.ts b/server/routers/role/addRoleResource.ts
index 93bd244f..59091050 100644
--- a/server/routers/role/addRoleResource.ts
+++ b/server/routers/role/addRoleResource.ts
@@ -1,12 +1,13 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roleResources } from '@server/db/schema';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { roleResources } 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 addRoleResourceParamsSchema = z.object({
roleId: z.string().transform(Number).pipe(z.number().int().positive()),
@@ -16,14 +17,18 @@ const addRoleResourceSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function addRoleResource(req: Request, res: Response, next: NextFunction): Promise {
+export async function addRoleResource(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedBody = addRoleResourceSchema.safeParse(req.body);
if (!parsedBody.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
@@ -35,7 +40,7 @@ export async function addRoleResource(req: Request, res: Response, next: NextFun
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -43,15 +48,26 @@ export async function addRoleResource(req: Request, res: Response, next: NextFun
const { roleId } = parsedParams.data;
// Check if the user has permission to add role resources
- const hasPermission = await checkUserActionPermission(ActionsEnum.addRoleResource, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.addRoleResource,
+ 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 newRoleResource = await db.insert(roleResources).values({
- roleId,
- resourceId,
- }).returning();
+ const newRoleResource = await db
+ .insert(roleResources)
+ .values({
+ roleId,
+ resourceId,
+ })
+ .returning();
return response(res, {
data: newRoleResource[0],
@@ -62,6 +78,11 @@ export async function addRoleResource(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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/role/addRoleSite.ts b/server/routers/role/addRoleSite.ts
index 7ac55e56..3d21149e 100644
--- a/server/routers/role/addRoleSite.ts
+++ b/server/routers/role/addRoleSite.ts
@@ -1,13 +1,14 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { resources, roleResources, roleSites } from '@server/db/schema';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { resources, roleResources, roleSites } 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 addRoleSiteParamsSchema = z.object({
roleId: z.string().transform(Number).pipe(z.number().int().positive()),
@@ -17,14 +18,18 @@ const addRoleSiteSchema = z.object({
siteId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function addRoleSite(req: Request, res: Response, next: NextFunction): Promise {
+export async function addRoleSite(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedBody = addRoleSiteSchema.safeParse(req.body);
if (!parsedBody.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
@@ -36,7 +41,7 @@ export async function addRoleSite(req: Request, res: Response, next: NextFunctio
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -44,17 +49,29 @@ export async function addRoleSite(req: Request, res: Response, next: NextFunctio
const { roleId } = parsedParams.data;
// Check if the user has permission to add role sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.addRoleSite, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.addRoleSite,
+ 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 newRoleSite = await db.insert(roleSites).values({
- roleId,
- siteId,
- }).returning();
+ const newRoleSite = await db
+ .insert(roleSites)
+ .values({
+ roleId,
+ siteId,
+ })
+ .returning();
- const siteResources = await db.select()
+ const siteResources = await db
+ .select()
.from(resources)
.where(eq(resources.siteId, siteId));
@@ -74,6 +91,11 @@ export async function addRoleSite(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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/role/createRole.ts b/server/routers/role/createRole.ts
index 01d9af2d..f61e8c07 100644
--- a/server/routers/role/createRole.ts
+++ b/server/routers/role/createRole.ts
@@ -1,15 +1,16 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roles } from '@server/db/schema';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { roles } 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 createRoleParamsSchema = z.object({
- orgId: z.string()
+ orgId: z.string(),
});
const createRoleSchema = z.object({
@@ -17,14 +18,18 @@ const createRoleSchema = z.object({
description: z.string().optional(),
});
-export async function createRole(req: Request, res: Response, next: NextFunction): Promise {
+export async function createRole(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedBody = createRoleSchema.safeParse(req.body);
if (!parsedBody.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
@@ -36,7 +41,7 @@ export async function createRole(req: Request, res: Response, next: NextFunction
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -44,15 +49,26 @@ export async function createRole(req: Request, res: Response, next: NextFunction
const { orgId } = parsedParams.data;
// Check if the user has permission to create roles
- const hasPermission = await checkUserActionPermission(ActionsEnum.createRole, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.createRole,
+ 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 newRole = await db.insert(roles).values({
- ...roleData,
- orgId,
- }).returning();
+ const newRole = await db
+ .insert(roles)
+ .values({
+ ...roleData,
+ orgId,
+ })
+ .returning();
return response(res, {
data: newRole[0],
@@ -63,6 +79,11 @@ export async function createRole(req: Request, res: Response, next: NextFunction
});
} 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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/role/deleteRole.ts b/server/routers/role/deleteRole.ts
index f5b1225a..62138e53 100644
--- a/server/routers/role/deleteRole.ts
+++ b/server/routers/role/deleteRole.ts
@@ -1,26 +1,31 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roles } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { roles } from "@server/db/schema";
+import { 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 deleteRoleSchema = z.object({
- roleId: z.string().transform(Number).pipe(z.number().int().positive())
+ roleId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function deleteRole(req: Request, res: Response, next: NextFunction): Promise {
+export async function deleteRole(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = deleteRoleSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -28,15 +33,24 @@ export async function deleteRole(req: Request, res: Response, next: NextFunction
const { roleId } = parsedParams.data;
// Check if the user has permission to delete roles
- const hasPermission = await checkUserActionPermission(ActionsEnum.deleteRole, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.deleteRole,
+ 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 role = await db.select()
- .from(roles)
- .where(eq(roles.roleId, roleId))
- .limit(1);
+ const role = await db
+ .select()
+ .from(roles)
+ .where(eq(roles.roleId, roleId))
+ .limit(1);
if (role.length === 0) {
return next(
@@ -56,7 +70,8 @@ export async function deleteRole(req: Request, res: Response, next: NextFunction
);
}
- const deletedRole = await db.delete(roles)
+ const deletedRole = await db
+ .delete(roles)
.where(eq(roles.roleId, roleId))
.returning();
@@ -78,6 +93,11 @@ export async function deleteRole(req: Request, res: Response, next: NextFunction
});
} 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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/role/getRole.ts b/server/routers/role/getRole.ts
index 6866448b..964661c7 100644
--- a/server/routers/role/getRole.ts
+++ b/server/routers/role/getRole.ts
@@ -1,26 +1,31 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roles } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { roles } from "@server/db/schema";
+import { 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 getRoleSchema = z.object({
- roleId: z.string().transform(Number).pipe(z.number().int().positive())
+ roleId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function getRole(req: Request, res: Response, next: NextFunction): Promise {
+export async function getRole(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = getRoleSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -28,12 +33,21 @@ export async function getRole(req: Request, res: Response, next: NextFunction):
const { roleId } = parsedParams.data;
// Check if the user has permission to get roles
- const hasPermission = await checkUserActionPermission(ActionsEnum.getRole, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.getRole,
+ 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 role = await db.select()
+ const role = await db
+ .select()
.from(roles)
.where(eq(roles.roleId, roleId))
.limit(1);
@@ -56,6 +70,11 @@ export async function getRole(req: Request, res: Response, next: NextFunction):
});
} 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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/role/listRoleActions.ts b/server/routers/role/listRoleActions.ts
index 6f16b956..0a61070f 100644
--- a/server/routers/role/listRoleActions.ts
+++ b/server/routers/role/listRoleActions.ts
@@ -1,26 +1,31 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roleActions, actions } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { roleActions, actions } from "@server/db/schema";
+import { 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 listRoleActionsSchema = z.object({
roleId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function listRoleActions(req: Request, res: Response, next: NextFunction): Promise {
+export async function listRoleActions(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = listRoleActionsSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -28,9 +33,17 @@ export async function listRoleActions(req: Request, res: Response, next: NextFun
const { roleId } = parsedParams.data;
// Check if the user has permission to list role actions
- const hasPermission = await checkUserActionPermission(ActionsEnum.listRoleActions, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.listRoleActions,
+ 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 roleActionsList = await db
@@ -43,7 +56,7 @@ export async function listRoleActions(req: Request, res: Response, next: NextFun
.innerJoin(actions, eq(roleActions.actionId, actions.actionId))
.where(eq(roleActions.roleId, roleId));
- // TODO: Do we need to filter out what the user can see?
+ // TODO: Do we need to filter out what the user can see?
return response(res, {
data: roleActionsList,
@@ -54,6 +67,11 @@ export async function listRoleActions(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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/role/listRoleResources.ts b/server/routers/role/listRoleResources.ts
index 0d4644a4..18075e44 100644
--- a/server/routers/role/listRoleResources.ts
+++ b/server/routers/role/listRoleResources.ts
@@ -1,26 +1,31 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roleResources, resources } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { roleResources, resources } from "@server/db/schema";
+import { 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 listRoleResourcesSchema = z.object({
roleId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function listRoleResources(req: Request, res: Response, next: NextFunction): Promise {
+export async function listRoleResources(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = listRoleResourcesSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -28,9 +33,17 @@ export async function listRoleResources(req: Request, res: Response, next: NextF
const { roleId } = parsedParams.data;
// Check if the user has permission to list role resources
- const hasPermission = await checkUserActionPermission(ActionsEnum.listRoleResources, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.listRoleResources,
+ 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 roleResourcesList = await db
@@ -40,10 +53,13 @@ export async function listRoleResources(req: Request, res: Response, next: NextF
subdomain: resources.subdomain,
})
.from(roleResources)
- .innerJoin(resources, eq(roleResources.resourceId, resources.resourceId))
+ .innerJoin(
+ resources,
+ eq(roleResources.resourceId, resources.resourceId)
+ )
.where(eq(roleResources.roleId, roleId));
- // TODO: Do we need to filter out what the user can see?
+ // TODO: Do we need to filter out what the user can see?
return response(res, {
data: roleResourcesList,
@@ -54,6 +70,11 @@ export async function listRoleResources(req: Request, res: Response, next: NextF
});
} 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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/role/listRoleSites.ts b/server/routers/role/listRoleSites.ts
index 8b11d036..e74a50f9 100644
--- a/server/routers/role/listRoleSites.ts
+++ b/server/routers/role/listRoleSites.ts
@@ -1,26 +1,31 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roleSites, sites } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { roleSites, sites } from "@server/db/schema";
+import { 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 listRoleSitesSchema = z.object({
roleId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function listRoleSites(req: Request, res: Response, next: NextFunction): Promise {
+export async function listRoleSites(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = listRoleSitesSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -28,9 +33,17 @@ export async function listRoleSites(req: Request, res: Response, next: NextFunct
const { roleId } = parsedParams.data;
// Check if the user has permission to list role sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.listRoleSites, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.listRoleSites,
+ 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 roleSitesList = await db
@@ -42,7 +55,7 @@ export async function listRoleSites(req: Request, res: Response, next: NextFunct
.innerJoin(sites, eq(roleSites.siteId, sites.siteId))
.where(eq(roleSites.roleId, roleId));
- // TODO: Do we need to filter out what the user can see?
+ // TODO: Do we need to filter out what the user can see?
return response(res, {
data: roleSitesList,
@@ -53,6 +66,11 @@ export async function listRoleSites(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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/role/listRoles.ts b/server/routers/role/listRoles.ts
index db489a47..1b6f911f 100644
--- a/server/routers/role/listRoles.ts
+++ b/server/routers/role/listRoles.ts
@@ -1,32 +1,49 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roles, orgs } from '@server/db/schema';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { roles, orgs } from "@server/db/schema";
import response from "@server/utils/response";
-import HttpCode from '@server/types/HttpCode';
-import createHttpError from 'http-errors';
-import { sql, eq } from 'drizzle-orm';
-import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
-import logger from '@server/logger';
+import HttpCode from "@server/types/HttpCode";
+import createHttpError from "http-errors";
+import { sql, eq } from "drizzle-orm";
+import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
+import logger from "@server/logger";
+import { fromError } from "zod-validation-error";
const listRolesParamsSchema = z.object({
- orgId: z.string()
+ orgId: z.string(),
});
const listRolesSchema = z.object({
- limit: z.string().optional().transform(Number).pipe(z.number().int().positive().default(10)),
- offset: z.string().optional().transform(Number).pipe(z.number().int().nonnegative().default(0)),
- orgId: z.string().optional().transform(Number).pipe(z.number().int().positive()),
+ limit: z
+ .string()
+ .optional()
+ .transform(Number)
+ .pipe(z.number().int().positive().default(10)),
+ offset: z
+ .string()
+ .optional()
+ .transform(Number)
+ .pipe(z.number().int().nonnegative().default(0)),
+ orgId: z
+ .string()
+ .optional()
+ .transform(Number)
+ .pipe(z.number().int().positive()),
});
-export async function listRoles(req: Request, res: Response, next: NextFunction): Promise {
+export async function listRoles(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedQuery = listRolesSchema.safeParse(req.query);
if (!parsedQuery.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedQuery.error.errors.map(e => e.message).join(', ')
+ fromError(parsedQuery.error).toString()
)
);
}
@@ -38,7 +55,7 @@ export async function listRoles(req: Request, res: Response, next: NextFunction)
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -46,9 +63,17 @@ export async function listRoles(req: Request, res: Response, next: NextFunction)
const { orgId } = parsedParams.data;
// Check if the user has permission to list roles
- const hasPermission = await checkUserActionPermission(ActionsEnum.listRoles, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.listRoles,
+ 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"
+ )
+ );
}
let baseQuery: any = db
@@ -64,8 +89,10 @@ export async function listRoles(req: Request, res: Response, next: NextFunction)
.leftJoin(orgs, eq(roles.orgId, orgs.orgId))
.where(eq(roles.orgId, orgId));
- let countQuery: any = db.select({ count: sql`cast(count(*) as integer)` }).from(roles)
- .where(eq(roles.orgId, orgId));
+ let countQuery: any = db
+ .select({ count: sql`cast(count(*) as integer)` })
+ .from(roles)
+ .where(eq(roles.orgId, orgId));
const rolesList = await baseQuery.limit(limit).offset(offset);
const totalCountResult = await countQuery;
@@ -87,6 +114,11 @@ export async function listRoles(req: Request, res: Response, next: NextFunction)
});
} 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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/role/removeRoleAction.ts b/server/routers/role/removeRoleAction.ts
index 08c1217d..a9f071b5 100644
--- a/server/routers/role/removeRoleAction.ts
+++ b/server/routers/role/removeRoleAction.ts
@@ -1,13 +1,14 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roleActions } 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 { roleActions } 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 removeRoleActionParamsSchema = z.object({
roleId: z.string().transform(Number).pipe(z.number().int().positive()),
@@ -17,14 +18,18 @@ const removeRoleActionSchema = z.object({
actionId: z.string(),
});
-export async function removeRoleAction(req: Request, res: Response, next: NextFunction): Promise {
+export async function removeRoleAction(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = removeRoleActionSchema.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 removeRoleAction(req: Request, res: Response, next: NextFu
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
@@ -44,13 +49,27 @@ export async function removeRoleAction(req: Request, res: Response, next: NextFu
const { roleId } = parsedBody.data;
// Check if the user has permission to remove role actions
- const hasPermission = await checkUserActionPermission(ActionsEnum.removeRoleAction, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.removeRoleAction,
+ 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 deletedRoleAction = await db.delete(roleActions)
- .where(and(eq(roleActions.roleId, roleId), eq(roleActions.actionId, actionId)))
+ const deletedRoleAction = await db
+ .delete(roleActions)
+ .where(
+ and(
+ eq(roleActions.roleId, roleId),
+ eq(roleActions.actionId, actionId)
+ )
+ )
.returning();
if (deletedRoleAction.length === 0) {
@@ -71,6 +90,11 @@ export async function removeRoleAction(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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/role/removeRoleResource.ts b/server/routers/role/removeRoleResource.ts
index 3ec19263..bf2582c3 100644
--- a/server/routers/role/removeRoleResource.ts
+++ b/server/routers/role/removeRoleResource.ts
@@ -1,13 +1,14 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roleResources } 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 { roleResources } 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 removeRoleResourceParamsSchema = z.object({
roleId: z.string().transform(Number).pipe(z.number().int().positive()),
@@ -17,14 +18,18 @@ const removeRoleResourceSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function removeRoleResource(req: Request, res: Response, next: NextFunction): Promise {
+export async function removeRoleResource(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = removeRoleResourceSchema.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 removeRoleResource(req: Request, res: Response, next: Next
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
@@ -44,13 +49,27 @@ export async function removeRoleResource(req: Request, res: Response, next: Next
const { roleId } = parsedBody.data;
// Check if the user has permission to remove role resources
- const hasPermission = await checkUserActionPermission(ActionsEnum.removeRoleResource, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.removeRoleResource,
+ 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 deletedRoleResource = await db.delete(roleResources)
- .where(and(eq(roleResources.roleId, roleId), eq(roleResources.resourceId, resourceId)))
+ const deletedRoleResource = await db
+ .delete(roleResources)
+ .where(
+ and(
+ eq(roleResources.roleId, roleId),
+ eq(roleResources.resourceId, resourceId)
+ )
+ )
.returning();
if (deletedRoleResource.length === 0) {
@@ -71,6 +90,11 @@ export async function removeRoleResource(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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/role/removeRoleSite.ts b/server/routers/role/removeRoleSite.ts
index badaac87..dd1f2d57 100644
--- a/server/routers/role/removeRoleSite.ts
+++ b/server/routers/role/removeRoleSite.ts
@@ -1,13 +1,14 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { resources, roleResources, roleSites } 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, roleResources, roleSites } 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 removeRoleSiteParamsSchema = z.object({
roleId: z.string().transform(Number).pipe(z.number().int().positive()),
@@ -17,14 +18,18 @@ const removeRoleSiteSchema = z.object({
siteId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function removeRoleSite(req: Request, res: Response, next: NextFunction): Promise {
+export async function removeRoleSite(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = removeRoleSiteSchema.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 removeRoleSite(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 removeRoleSite(req: Request, res: Response, next: NextFunc
const { roleId } = parsedBody.data;
// Check if the user has permission to remove role sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.removeRoleSite, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.removeRoleSite,
+ 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 deletedRoleSite = await db.delete(roleSites)
- .where(and(eq(roleSites.roleId, roleId), eq(roleSites.siteId, siteId)))
+ const deletedRoleSite = await db
+ .delete(roleSites)
+ .where(
+ and(eq(roleSites.roleId, roleId), eq(roleSites.siteId, siteId))
+ )
.returning();
if (deletedRoleSite.length === 0) {
@@ -62,13 +78,20 @@ export async function removeRoleSite(req: Request, res: Response, next: NextFunc
);
}
- const siteResources = await db.select()
- .from(resources)
- .where(eq(resources.siteId, siteId));
+ const siteResources = await db
+ .select()
+ .from(resources)
+ .where(eq(resources.siteId, siteId));
for (const resource of siteResources) {
- await db.delete(roleResources)
- .where(and(eq(roleResources.roleId, roleId), eq(roleResources.resourceId, resource.resourceId)))
+ await db
+ .delete(roleResources)
+ .where(
+ and(
+ eq(roleResources.roleId, roleId),
+ eq(roleResources.resourceId, resource.resourceId)
+ )
+ )
.returning();
}
@@ -81,6 +104,11 @@ export async function removeRoleSite(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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/role/updateRole.ts b/server/routers/role/updateRole.ts
index bd8960b5..8d05db76 100644
--- a/server/routers/role/updateRole.ts
+++ b/server/routers/role/updateRole.ts
@@ -1,33 +1,40 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roles } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { roles } from "@server/db/schema";
+import { 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 updateRoleParamsSchema = z.object({
- roleId: z.string().transform(Number).pipe(z.number().int().positive())
+ roleId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-const updateRoleBodySchema = z.object({
- name: z.string().min(1).max(255).optional(),
- description: z.string().optional(),
-}).refine(data => Object.keys(data).length > 0, {
- message: "At least one field must be provided for update"
-});
+const updateRoleBodySchema = z
+ .object({
+ name: z.string().min(1).max(255).optional(),
+ description: z.string().optional(),
+ })
+ .refine((data) => Object.keys(data).length > 0, {
+ message: "At least one field must be provided for update",
+ });
-export async function updateRole(req: Request, res: Response, next: NextFunction): Promise {
+export async function updateRole(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = updateRoleParamsSchema.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 +44,7 @@ export async function updateRole(req: Request, res: Response, next: NextFunction
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
@@ -46,15 +53,24 @@ export async function updateRole(req: Request, res: Response, next: NextFunction
const updateData = parsedBody.data;
// Check if the user has permission to update roles
- const hasPermission = await checkUserActionPermission(ActionsEnum.updateRole, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.updateRole,
+ 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 role = await db.select()
- .from(roles)
- .where(eq(roles.roleId, roleId))
- .limit(1);
+ const role = await db
+ .select()
+ .from(roles)
+ .where(eq(roles.roleId, roleId))
+ .limit(1);
if (role.length === 0) {
return next(
@@ -74,7 +90,8 @@ export async function updateRole(req: Request, res: Response, next: NextFunction
);
}
- const updatedRole = await db.update(roles)
+ const updatedRole = await db
+ .update(roles)
.set(updateData)
.where(eq(roles.roleId, roleId))
.returning();
@@ -97,6 +114,11 @@ export async function updateRole(req: Request, res: Response, next: NextFunction
});
} 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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/site/createSite.ts b/server/routers/site/createSite.ts
index ee8759ea..c50018ec 100644
--- a/server/routers/site/createSite.ts
+++ b/server/routers/site/createSite.ts
@@ -1,20 +1,25 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roles, userSites, sites, roleSites, exitNodes } from '@server/db/schema';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import {
+ roles,
+ userSites,
+ sites,
+ roleSites,
+ exitNodes,
+} 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, and } from 'drizzle-orm';
-import { getUniqueSiteName } from '@server/db/names';
-import { addPeer } from '../gerbil/peers';
-
-const API_BASE_URL = "http://localhost:3000";
+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, and } from "drizzle-orm";
+import { getUniqueSiteName } from "@server/db/names";
+import { addPeer } from "../gerbil/peers";
+import { fromError } from "zod-validation-error";
const createSiteParamsSchema = z.object({
- orgId: z.string()
+ orgId: z.string(),
});
// Define Zod schema for request body validation
@@ -36,7 +41,11 @@ export type CreateSiteResponse = {
// subnet: string;
};
-export async function createSite(req: Request, res: Response, next: NextFunction): Promise {
+export async function createSite(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
// Validate request body
const parsedBody = createSiteSchema.safeParse(req.body);
@@ -44,7 +53,7 @@ export async function createSite(req: Request, res: Response, next: NextFunction
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
@@ -57,7 +66,7 @@ export async function createSite(req: Request, res: Response, next: NextFunction
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -65,38 +74,49 @@ export async function createSite(req: Request, res: Response, next: NextFunction
const { orgId } = parsedParams.data;
// Check if the user has permission to list sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.createSite, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.createSite,
+ req
+ );
if (!hasPermission) {
- return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have permission perform this action'));
+ return next(
+ createHttpError(
+ HttpCode.FORBIDDEN,
+ "User does not have permission perform this action"
+ )
+ );
}
if (!req.userOrgRoleId) {
- return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have a role'));
+ return next(
+ createHttpError(HttpCode.FORBIDDEN, "User does not have a role")
+ );
}
const niceId = await getUniqueSiteName(orgId);
// Create new site in the database
- const [newSite] = await db.insert(sites).values({
- orgId,
- exitNodeId,
- name,
- niceId,
- pubKey,
- subnet,
- }).returning();
+ const [newSite] = await db
+ .insert(sites)
+ .values({
+ orgId,
+ exitNodeId,
+ name,
+ niceId,
+ pubKey,
+ subnet,
+ })
+ .returning();
// find the superuser roleId and also add the resource to the superuser role
- const superuserRole = await db.select()
- .from(roles)
- .where(and(eq(roles.isSuperuserRole, true), eq(roles.orgId, orgId)))
- .limit(1);
+ const superuserRole = await db
+ .select()
+ .from(roles)
+ .where(and(eq(roles.isSuperuserRole, true), eq(roles.orgId, orgId)))
+ .limit(1);
if (superuserRole.length === 0) {
return next(
- createHttpError(
- HttpCode.NOT_FOUND,
- `Superuser role not found`
- )
+ createHttpError(HttpCode.NOT_FOUND, `Superuser role not found`)
);
}
@@ -135,6 +155,11 @@ export async function createSite(req: Request, res: Response, next: NextFunction
});
} 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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/site/deleteSite.ts b/server/routers/site/deleteSite.ts
index 399e7d0d..aa69ef44 100644
--- a/server/routers/site/deleteSite.ts
+++ b/server/routers/site/deleteSite.ts
@@ -1,23 +1,28 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { sites } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { sites } from "@server/db/schema";
+import { 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 { deletePeer } from '../gerbil/peers';
+import HttpCode from "@server/types/HttpCode";
+import createHttpError from "http-errors";
+import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
+import logger from "@server/logger";
+import { deletePeer } from "../gerbil/peers";
+import { fromError } from "zod-validation-error";
const API_BASE_URL = "http://localhost:3000";
// Define Zod schema for request parameters validation
const deleteSiteSchema = z.object({
- siteId: z.string().transform(Number).pipe(z.number().int().positive())
+ siteId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function deleteSite(req: Request, res: Response, next: NextFunction): Promise {
+export async function deleteSite(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
// Validate request parameters
const parsedParams = deleteSiteSchema.safeParse(req.params);
@@ -25,7 +30,7 @@ export async function deleteSite(req: Request, res: Response, next: NextFunction
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -33,13 +38,22 @@ export async function deleteSite(req: Request, res: Response, next: NextFunction
const { siteId } = parsedParams.data;
// Check if the user has permission to list sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.deleteSite, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.deleteSite,
+ 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"
+ )
+ );
}
// Delete the site from the database
- const [deletedSite] = await db.delete(sites)
+ const [deletedSite] = await db
+ .delete(sites)
.where(eq(sites.siteId, siteId))
.returning();
@@ -63,26 +77,33 @@ export async function deleteSite(req: Request, res: Response, next: NextFunction
});
} 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..."
+ )
+ );
}
}
-
async function removePeer(publicKey: string) {
try {
- const response = await fetch(`${API_BASE_URL}/peer?public_key=${encodeURIComponent(publicKey)}`, {
- method: 'DELETE',
- });
+ const response = await fetch(
+ `${API_BASE_URL}/peer?public_key=${encodeURIComponent(publicKey)}`,
+ {
+ method: "DELETE",
+ }
+ );
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
- console.log('Peer removed successfully:', data.status);
+ console.log("Peer removed successfully:", data.status);
return data;
} catch (error: any) {
- console.error('Error removing peer:', error.message);
+ console.error("Error removing peer:", error.message);
throw error;
}
}
diff --git a/server/routers/site/getSite.ts b/server/routers/site/getSite.ts
index 927a3628..4791970b 100644
--- a/server/routers/site/getSite.ts
+++ b/server/routers/site/getSite.ts
@@ -1,18 +1,24 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { sites } 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 { sites } 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 stoi from '@server/utils/stoi';
+import HttpCode from "@server/types/HttpCode";
+import createHttpError from "http-errors";
+import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
+import logger from "@server/logger";
+import stoi from "@server/utils/stoi";
+import { fromError } from "zod-validation-error";
// Define Zod schema for request parameters validation
const getSiteSchema = z.object({
- siteId: z.string().optional().transform(stoi).pipe(z.number().int().positive().optional()).optional(),
+ siteId: z
+ .string()
+ .optional()
+ .transform(stoi)
+ .pipe(z.number().int().positive().optional())
+ .optional(),
niceId: z.string().optional(),
orgId: z.string().optional(),
});
@@ -22,9 +28,13 @@ export type GetSiteResponse = {
name: string;
subdomain: string;
subnet: string;
-}
+};
-export async function getSite(req: Request, res: Response, next: NextFunction): Promise {
+export async function getSite(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
// Validate request parameters
const parsedParams = getSiteSchema.safeParse(req.params);
@@ -32,7 +42,7 @@ export async function getSite(req: Request, res: Response, next: NextFunction):
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -40,27 +50,37 @@ export async function getSite(req: Request, res: Response, next: NextFunction):
const { siteId, niceId, orgId } = parsedParams.data;
// Check if the user has permission to list sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.updateSite, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.updateSite,
+ 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"
+ )
+ );
}
let site;
// Fetch the site from the database
if (siteId) {
- site = await db.select()
+ site = await db
+ .select()
.from(sites)
.where(eq(sites.siteId, siteId))
.limit(1);
} else if (niceId && orgId) {
- site = await db.select()
+ site = await db
+ .select()
.from(sites)
.where(and(eq(sites.niceId, niceId), eq(sites.orgId, orgId)))
.limit(1);
}
if (!site) {
- return next(createHttpError(HttpCode.NOT_FOUND, 'Site not found'));
+ return next(createHttpError(HttpCode.NOT_FOUND, "Site not found"));
}
if (site.length === 0) {
@@ -86,6 +106,11 @@ export async function getSite(req: Request, res: Response, next: NextFunction):
});
} catch (error) {
logger.error("Error from getSite: ", error);
- return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred..."));
+ return next(
+ createHttpError(
+ HttpCode.INTERNAL_SERVER_ERROR,
+ "An error occurred..."
+ )
+ );
}
}
diff --git a/server/routers/site/listSiteRoles.ts b/server/routers/site/listSiteRoles.ts
index 4acf52c0..8c725908 100644
--- a/server/routers/site/listSiteRoles.ts
+++ b/server/routers/site/listSiteRoles.ts
@@ -1,26 +1,31 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { roleSites, roles } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { roleSites, roles } from "@server/db/schema";
+import { 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 listSiteRolesSchema = z.object({
siteId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function listSiteRoles(req: Request, res: Response, next: NextFunction): Promise {
+export async function listSiteRoles(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = listSiteRolesSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -28,9 +33,17 @@ export async function listSiteRoles(req: Request, res: Response, next: NextFunct
const { siteId } = parsedParams.data;
// Check if the user has permission to list site roles
- const hasPermission = await checkUserActionPermission(ActionsEnum.listSiteRoles, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.listSiteRoles,
+ 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 siteRolesList = await db
@@ -53,6 +66,11 @@ export async function listSiteRoles(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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/site/pickSiteDefaults.ts b/server/routers/site/pickSiteDefaults.ts
index 5901de8c..ad369536 100644
--- a/server/routers/site/pickSiteDefaults.ts
+++ b/server/routers/site/pickSiteDefaults.ts
@@ -18,26 +18,25 @@ export type PickSiteDefaultsResponse = {
listenPort: number;
endpoint: string;
subnet: string;
-}
+};
export async function pickSiteDefaults(
req: Request,
res: Response,
- next: NextFunction,
+ next: NextFunction
): Promise {
try {
-
// Check if the user has permission to list sites
const hasPermission = await checkUserActionPermission(
ActionsEnum.createSite,
- req,
+ req
);
if (!hasPermission) {
return next(
createHttpError(
HttpCode.FORBIDDEN,
- "User does not have permission to perform this action",
- ),
+ "User does not have permission to perform this action"
+ )
);
}
@@ -47,10 +46,7 @@ export async function pickSiteDefaults(
const nodes = await db.select().from(exitNodes);
if (nodes.length === 0) {
return next(
- createHttpError(
- HttpCode.NOT_FOUND,
- "No exit nodes available",
- ),
+ createHttpError(HttpCode.NOT_FOUND, "No exit nodes available")
);
}
@@ -59,9 +55,10 @@ export async function pickSiteDefaults(
// TODO: this probably can be optimized...
// list all of the sites on that exit node
- const sitesQuery = await db.select({
- subnet: sites.subnet
- })
+ const sitesQuery = await db
+ .select({
+ subnet: sites.subnet,
+ })
.from(sites)
.where(eq(sites.exitNodeId, exitNode.exitNodeId));
@@ -74,8 +71,8 @@ export async function pickSiteDefaults(
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
- "No available subnets",
- ),
+ "No available subnets"
+ )
);
}
@@ -97,11 +94,7 @@ export async function pickSiteDefaults(
} catch (error) {
logger.error(error);
return next(
- createHttpError(
- HttpCode.INTERNAL_SERVER_ERROR,
- "An error occurred...",
- ),
+ createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred")
);
}
}
-
diff --git a/server/routers/site/updateSite.ts b/server/routers/site/updateSite.ts
index e5ecc409..52a39911 100644
--- a/server/routers/site/updateSite.ts
+++ b/server/routers/site/updateSite.ts
@@ -1,33 +1,40 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { sites } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { sites } from "@server/db/schema";
+import { 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";
// Define Zod schema for request parameters validation
const updateSiteParamsSchema = z.object({
- siteId: z.string().transform(Number).pipe(z.number().int().positive())
+ siteId: z.string().transform(Number).pipe(z.number().int().positive()),
});
// Define Zod schema for request body validation
-const updateSiteBodySchema = z.object({
- name: z.string().min(1).max(255).optional(),
- subdomain: z.string().min(1).max(255).optional(),
- pubKey: z.string().optional(),
- subnet: z.string().optional(),
- exitNode: z.number().int().positive().optional(),
- megabytesIn: z.number().int().nonnegative().optional(),
- megabytesOut: z.number().int().nonnegative().optional(),
-}).refine(data => Object.keys(data).length > 0, {
- message: "At least one field must be provided for update"
-});
+const updateSiteBodySchema = z
+ .object({
+ name: z.string().min(1).max(255).optional(),
+ subdomain: z.string().min(1).max(255).optional(),
+ pubKey: z.string().optional(),
+ subnet: z.string().optional(),
+ exitNode: z.number().int().positive().optional(),
+ megabytesIn: z.number().int().nonnegative().optional(),
+ megabytesOut: z.number().int().nonnegative().optional(),
+ })
+ .refine((data) => Object.keys(data).length > 0, {
+ message: "At least one field must be provided for update",
+ });
-export async function updateSite(req: Request, res: Response, next: NextFunction): Promise {
+export async function updateSite(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
// Validate request parameters
const parsedParams = updateSiteParamsSchema.safeParse(req.params);
@@ -35,7 +42,7 @@ export async function updateSite(req: Request, res: Response, next: NextFunction
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -46,7 +53,7 @@ export async function updateSite(req: Request, res: Response, next: NextFunction
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
@@ -55,13 +62,22 @@ export async function updateSite(req: Request, res: Response, next: NextFunction
const updateData = parsedBody.data;
// Check if the user has permission to list sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.updateSite, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.updateSite,
+ 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"
+ )
+ );
}
// Update the site in the database
- const updatedSite = await db.update(sites)
+ const updatedSite = await db
+ .update(sites)
.set(updateData)
.where(eq(sites.siteId, siteId))
.returning();
@@ -84,6 +100,11 @@ export async function updateSite(req: Request, res: Response, next: NextFunction
});
} 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..."
+ )
+ );
}
}
diff --git a/server/routers/target/createTarget.ts b/server/routers/target/createTarget.ts
index 58344219..84f45f0e 100644
--- a/server/routers/target/createTarget.ts
+++ b/server/routers/target/createTarget.ts
@@ -1,15 +1,16 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { resources, sites, targets } from '@server/db/schema';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { resources, sites, targets } 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 { addPeer } from '../gerbil/peers';
-import { eq, and } from 'drizzle-orm';
-import { isIpInCidr } from '@server/utils/ip';
+import HttpCode from "@server/types/HttpCode";
+import createHttpError from "http-errors";
+import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
+import logger from "@server/logger";
+import { addPeer } from "../gerbil/peers";
+import { eq, and } from "drizzle-orm";
+import { isIpInCidr } from "@server/utils/ip";
+import { fromError } from "zod-validation-error";
const createTargetParamsSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
@@ -23,14 +24,18 @@ const createTargetSchema = z.object({
enabled: z.boolean().default(true),
});
-export async function createTarget(req: Request, res: Response, next: NextFunction): Promise {
+export async function createTarget(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedBody = createTargetSchema.safeParse(req.body);
if (!parsedBody.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
@@ -42,7 +47,7 @@ export async function createTarget(req: Request, res: Response, next: NextFuncti
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -50,15 +55,24 @@ export async function createTarget(req: Request, res: Response, next: NextFuncti
const { resourceId } = parsedParams.data;
// Check if the user has permission to list sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.createTarget, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.createTarget,
+ 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"
+ )
+ );
}
// get the resource
- const [resource] = await db.select({
- siteId: resources.siteId,
- })
+ const [resource] = await db
+ .select({
+ siteId: resources.siteId,
+ })
.from(resources)
.where(eq(resources.resourceId, resourceId));
@@ -72,9 +86,10 @@ export async function createTarget(req: Request, res: Response, next: NextFuncti
}
// TODO: is this all inefficient?
-
+
// get the site
- const [site] = await db.select()
+ const [site] = await db
+ .select()
.from(sites)
.where(eq(sites.siteId, resource.siteId!))
.limit(1);
@@ -98,10 +113,13 @@ export async function createTarget(req: Request, res: Response, next: NextFuncti
);
}
- const newTarget = await db.insert(targets).values({
- resourceId,
- ...targetData
- }).returning();
+ const newTarget = await db
+ .insert(targets)
+ .values({
+ resourceId,
+ ...targetData,
+ })
+ .returning();
// Fetch resources for this site
const resourcesRes = await db.query.resources.findMany({
@@ -109,16 +127,18 @@ export async function createTarget(req: Request, res: Response, next: NextFuncti
});
// Fetch targets for all resources of this site
- const targetIps = await Promise.all(resourcesRes.map(async (resource) => {
- const targetsRes = await db.query.targets.findMany({
- where: eq(targets.resourceId, resource.resourceId),
- });
- return targetsRes.map(target => `${target.ip}/32`);
- }));
+ const targetIps = await Promise.all(
+ resourcesRes.map(async (resource) => {
+ const targetsRes = await db.query.targets.findMany({
+ where: eq(targets.resourceId, resource.resourceId),
+ });
+ return targetsRes.map((target) => `${target.ip}/32`);
+ })
+ );
await addPeer(site.exitNodeId!, {
publicKey: site.pubKey,
- allowedIps: targetIps.flat()
+ allowedIps: targetIps.flat(),
});
return response(res, {
@@ -130,6 +150,11 @@ export async function createTarget(req: Request, res: Response, next: NextFuncti
});
} 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..."
+ )
+ );
}
}
diff --git a/server/routers/target/deleteTarget.ts b/server/routers/target/deleteTarget.ts
index f74b7bbe..e5e50ffd 100644
--- a/server/routers/target/deleteTarget.ts
+++ b/server/routers/target/deleteTarget.ts
@@ -1,27 +1,32 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { resources, sites, targets } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { resources, sites, targets } from "@server/db/schema";
+import { 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 { addPeer } from '../gerbil/peers';
+import HttpCode from "@server/types/HttpCode";
+import createHttpError from "http-errors";
+import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
+import logger from "@server/logger";
+import { addPeer } from "../gerbil/peers";
+import { fromError } from "zod-validation-error";
const deleteTargetSchema = z.object({
- targetId: z.string().transform(Number).pipe(z.number().int().positive())
+ targetId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function deleteTarget(req: Request, res: Response, next: NextFunction): Promise {
+export async function deleteTarget(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = deleteTargetSchema.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,21 @@ export async function deleteTarget(req: Request, res: Response, next: NextFuncti
const { targetId } = parsedParams.data;
// Check if the user has permission to list sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.deleteTarget, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.deleteTarget,
+ 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 [deletedTarget] = await db.delete(targets)
+ const [deletedTarget] = await db
+ .delete(targets)
.where(eq(targets.targetId, targetId))
.returning();
@@ -48,9 +61,10 @@ export async function deleteTarget(req: Request, res: Response, next: NextFuncti
);
}
// get the resource
- const [resource] = await db.select({
- siteId: resources.siteId,
- })
+ const [resource] = await db
+ .select({
+ siteId: resources.siteId,
+ })
.from(resources)
.where(eq(resources.resourceId, deletedTarget.resourceId!));
@@ -66,7 +80,8 @@ export async function deleteTarget(req: Request, res: Response, next: NextFuncti
// TODO: is this all inefficient?
// get the site
- const [site] = await db.select()
+ const [site] = await db
+ .select()
.from(sites)
.where(eq(sites.siteId, resource.siteId!))
.limit(1);
@@ -86,16 +101,18 @@ export async function deleteTarget(req: Request, res: Response, next: NextFuncti
});
// Fetch targets for all resources of this site
- const targetIps = await Promise.all(resourcesRes.map(async (resource) => {
- const targetsRes = await db.query.targets.findMany({
- where: eq(targets.resourceId, resource.resourceId),
- });
- return targetsRes.map(target => `${target.ip}/32`);
- }));
+ const targetIps = await Promise.all(
+ resourcesRes.map(async (resource) => {
+ const targetsRes = await db.query.targets.findMany({
+ where: eq(targets.resourceId, resource.resourceId),
+ });
+ return targetsRes.map((target) => `${target.ip}/32`);
+ })
+ );
await addPeer(site.exitNodeId!, {
publicKey: site.pubKey,
- allowedIps: targetIps.flat()
+ allowedIps: targetIps.flat(),
});
return response(res, {
@@ -107,6 +124,11 @@ export async function deleteTarget(req: Request, res: Response, next: NextFuncti
});
} 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..."
+ )
+ );
}
}
diff --git a/server/routers/target/getTarget.ts b/server/routers/target/getTarget.ts
index a0a1c321..665c534b 100644
--- a/server/routers/target/getTarget.ts
+++ b/server/routers/target/getTarget.ts
@@ -1,26 +1,31 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { targets } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { targets } from "@server/db/schema";
+import { 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 getTargetSchema = z.object({
- targetId: z.string().transform(Number).pipe(z.number().int().positive())
+ targetId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-export async function getTarget(req: Request, res: Response, next: NextFunction): Promise {
+export async function getTarget(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = getTargetSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -28,12 +33,21 @@ export async function getTarget(req: Request, res: Response, next: NextFunction)
const { targetId } = parsedParams.data;
// Check if the user has permission to list sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.getTarget, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.getTarget,
+ 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 target = await db.select()
+ const target = await db
+ .select()
.from(targets)
.where(eq(targets.targetId, targetId))
.limit(1);
@@ -56,6 +70,11 @@ export async function getTarget(req: Request, res: Response, next: NextFunction)
});
} 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..."
+ )
+ );
}
}
diff --git a/server/routers/target/updateTarget.ts b/server/routers/target/updateTarget.ts
index a02e11e3..8adcd9ff 100644
--- a/server/routers/target/updateTarget.ts
+++ b/server/routers/target/updateTarget.ts
@@ -1,36 +1,43 @@
-import { Request, Response, NextFunction } from 'express';
-import { z } from 'zod';
-import { db } from '@server/db';
-import { targets } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db } from "@server/db";
+import { targets } from "@server/db/schema";
+import { 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 updateTargetParamsSchema = z.object({
- targetId: z.string().transform(Number).pipe(z.number().int().positive())
+ targetId: z.string().transform(Number).pipe(z.number().int().positive()),
});
-const updateTargetBodySchema = z.object({
- // ip: z.string().ip().optional(), // for now we cant update the ip; you will have to delete
- method: z.string().min(1).max(10).optional(),
- port: z.number().int().min(1).max(65535).optional(),
- protocol: z.string().optional(),
- enabled: z.boolean().optional(),
-}).refine(data => Object.keys(data).length > 0, {
- message: "At least one field must be provided for update"
-});
+const updateTargetBodySchema = z
+ .object({
+ // ip: z.string().ip().optional(), // for now we cant update the ip; you will have to delete
+ method: z.string().min(1).max(10).optional(),
+ port: z.number().int().min(1).max(65535).optional(),
+ protocol: z.string().optional(),
+ enabled: z.boolean().optional(),
+ })
+ .refine((data) => Object.keys(data).length > 0, {
+ message: "At least one field must be provided for update",
+ });
-export async function updateTarget(req: Request, res: Response, next: NextFunction): Promise {
+export async function updateTarget(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
try {
const parsedParams = updateTargetParamsSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedParams.error.errors.map(e => e.message).join(', ')
+ fromError(parsedParams.error).toString()
)
);
}
@@ -40,7 +47,7 @@ export async function updateTarget(req: Request, res: Response, next: NextFuncti
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- parsedBody.error.errors.map(e => e.message).join(', ')
+ fromError(parsedBody.error).toString()
)
);
}
@@ -49,12 +56,21 @@ export async function updateTarget(req: Request, res: Response, next: NextFuncti
const updateData = parsedBody.data;
// Check if the user has permission to list sites
- const hasPermission = await checkUserActionPermission(ActionsEnum.updateTarget, req);
+ const hasPermission = await checkUserActionPermission(
+ ActionsEnum.updateTarget,
+ 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 updatedTarget = await db.update(targets)
+ const updatedTarget = await db
+ .update(targets)
.set(updateData)
.where(eq(targets.targetId, targetId))
.returning();
@@ -77,6 +93,11 @@ export async function updateTarget(req: Request, res: Response, next: NextFuncti
});
} 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..."
+ )
+ );
}
}
diff --git a/server/routers/user/addUserAction.ts b/server/routers/user/addUserAction.ts
index 981d651e..764f52fe 100644
--- a/server/routers/user/addUserAction.ts
+++ b/server/routers/user/addUserAction.ts
@@ -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 {
+export async function addUserAction(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
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..."
+ )
+ );
}
}
diff --git a/server/routers/user/addUserOrg.ts b/server/routers/user/addUserOrg.ts
deleted file mode 100644
index 139fd0c4..00000000
--- a/server/routers/user/addUserOrg.ts
+++ /dev/null
@@ -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 {
- 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..."));
- }
-}
diff --git a/server/routers/user/addUserResource.ts b/server/routers/user/addUserResource.ts
index 65c13000..aaa6e097 100644
--- a/server/routers/user/addUserResource.ts
+++ b/server/routers/user/addUserResource.ts
@@ -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 {
+export async function addUserResource(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/user/addUserSite.ts b/server/routers/user/addUserSite.ts
index 8be945a0..4691b571 100644
--- a/server/routers/user/addUserSite.ts
+++ b/server/routers/user/addUserSite.ts
@@ -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 {
+export async function addUserSite(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/user/index.ts b/server/routers/user/index.ts
index 421c288a..68541b7f 100644
--- a/server/routers/user/index.ts
+++ b/server/routers/user/index.ts
@@ -1,6 +1,5 @@
export * from "./getUser";
export * from "./removeUserOrg";
-export * from "./addUserOrg";
export * from "./listUsers";
export * from "./setUserRole";
export * from "./inviteUser";
diff --git a/server/routers/user/removeUserAction.ts b/server/routers/user/removeUserAction.ts
index 0896dd62..3a36ddec 100644
--- a/server/routers/user/removeUserAction.ts
+++ b/server/routers/user/removeUserAction.ts
@@ -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 {
+export async function removeUserAction(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/user/removeUserOrg.ts b/server/routers/user/removeUserOrg.ts
index 4a655961..f1f297f9 100644
--- a/server/routers/user/removeUserOrg.ts
+++ b/server/routers/user/removeUserOrg.ts
@@ -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 {
+export async function removeUserOrg(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
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..."
+ )
+ );
}
}
diff --git a/server/routers/user/removeUserResource.ts b/server/routers/user/removeUserResource.ts
index 3599b37b..3eecdf3f 100644
--- a/server/routers/user/removeUserResource.ts
+++ b/server/routers/user/removeUserResource.ts
@@ -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 {
+export async function removeUserResource(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/user/removeUserSite.ts b/server/routers/user/removeUserSite.ts
index 362c02a8..bdd29134 100644
--- a/server/routers/user/removeUserSite.ts
+++ b/server/routers/user/removeUserSite.ts
@@ -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 {
+export async function removeUserSite(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/server/routers/user/setUserRole.ts b/server/routers/user/setUserRole.ts
index 7bd5d34c..a95f7dc0 100644
--- a/server/routers/user/setUserRole.ts
+++ b/server/routers/user/setUserRole.ts
@@ -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 {
+export async function addUserRole(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
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..."
+ )
+ );
}
-}
\ No newline at end of file
+}
diff --git a/src/app/[orgId]/settings/components/Header.tsx b/src/app/[orgId]/settings/components/Header.tsx
index 5900a4a0..70d22c44 100644
--- a/src/app/[orgId]/settings/components/Header.tsx
+++ b/src/app/[orgId]/settings/components/Header.tsx
@@ -20,7 +20,7 @@ import {
SelectTrigger,
SelectValue,
} from "@app/components/ui/select";
-import { useToast } from "@app/hooks/use-toast";
+import { useToast } from "@app/hooks/useToast";
import { ListOrgsResponse } from "@server/routers/org";
import Link from "next/link";
import { useRouter } from "next/navigation";
diff --git a/src/app/[orgId]/settings/layout.tsx b/src/app/[orgId]/settings/layout.tsx
index 399c0fc2..20a084a6 100644
--- a/src/app/[orgId]/settings/layout.tsx
+++ b/src/app/[orgId]/settings/layout.tsx
@@ -8,6 +8,9 @@ import { internal } from "@app/api";
import { AxiosResponse } from "axios";
import { GetOrgResponse, ListOrgsResponse } from "@server/routers/org";
import { authCookieHeader } from "@app/api/cookies";
+import { cache } from "react";
+
+export const dynamic = "force-dynamic";
export const metadata: Metadata = {
title: `Settings - Pangolin`,
@@ -47,7 +50,8 @@ export default async function SettingsLayout(props: SettingsLayoutProps) {
const { children } = props;
- const user = await verifySession();
+ const getUser = cache(verifySession);
+ const user = await getUser();
if (!user) {
redirect("/auth/login");
@@ -56,20 +60,23 @@ export default async function SettingsLayout(props: SettingsLayoutProps) {
const cookie = await authCookieHeader();
try {
- await internal.get>(
- `/org/${params.orgId}`,
- cookie
+ const getOrg = cache(() =>
+ internal.get>(
+ `/org/${params.orgId}`,
+ cookie
+ )
);
+ const org = await getOrg();
} catch {
redirect(`/`);
}
let orgs: ListOrgsResponse["orgs"] = [];
try {
- const res = await internal.get>(
- `/orgs`,
- cookie
+ const getOrgs = cache(() =>
+ internal.get>(`/orgs`, cookie)
);
+ const res = await getOrgs();
if (res && res.data.data.orgs) {
orgs = res.data.data.orgs;
}
diff --git a/src/app/[orgId]/settings/resources/[resourceId]/components/CreateResource.tsx b/src/app/[orgId]/settings/resources/[resourceId]/components/CreateResource.tsx
index 49ba2ab8..75b6080e 100644
--- a/src/app/[orgId]/settings/resources/[resourceId]/components/CreateResource.tsx
+++ b/src/app/[orgId]/settings/resources/[resourceId]/components/CreateResource.tsx
@@ -8,7 +8,7 @@ import {
import { useForm } from "react-hook-form";
import { z } from "zod";
import { cn } from "@/lib/utils";
-import { toast } from "@/hooks/use-toast";
+import { toast } from "@/hooks/useToast";
import { Button} from "@/components/ui/button";
import {
Form,
diff --git a/src/app/[orgId]/settings/resources/[resourceId]/components/GeneralForm.tsx b/src/app/[orgId]/settings/resources/[resourceId]/components/GeneralForm.tsx
index 777ed323..046d2cf1 100644
--- a/src/app/[orgId]/settings/resources/[resourceId]/components/GeneralForm.tsx
+++ b/src/app/[orgId]/settings/resources/[resourceId]/components/GeneralForm.tsx
@@ -36,6 +36,8 @@ import { AxiosResponse } from "axios";
import api from "@app/api";
import { useParams } from "next/navigation";
import { useForm } from "react-hook-form";
+import { GetResourceResponse } from "@server/routers/resource";
+import { useToast } from "@app/hooks/useToast";
const GeneralFormSchema = z.object({
name: z.string(),
@@ -49,6 +51,7 @@ export function GeneralForm() {
const orgId = params.orgId;
const { resource, updateResource } = useResourceContext();
const [sites, setSites] = useState([]);
+ const { toast } = useToast();
const form = useForm({
resolver: zodResolver(GeneralFormSchema),
@@ -72,7 +75,24 @@ export function GeneralForm() {
}, []);
async function onSubmit(data: GeneralFormValues) {
- await updateResource({ name: data.name, siteId: data.siteId });
+ updateResource({ name: data.name, siteId: data.siteId });
+ await api
+ .post>(
+ `resource/${resource?.resourceId}`,
+ {
+ name: data.name,
+ siteId: data.siteId,
+ }
+ )
+ .catch((e) => {
+ toast({
+ variant: "destructive",
+ title: "Failed to update resource",
+ description:
+ e.response?.data?.message ||
+ "An error occurred while updating the resource",
+ });
+ });
}
return (
diff --git a/src/app/[orgId]/settings/sites/[niceId]/components/CreateSite.tsx b/src/app/[orgId]/settings/sites/[niceId]/components/CreateSite.tsx
index efe4497e..e88117e4 100644
--- a/src/app/[orgId]/settings/sites/[niceId]/components/CreateSite.tsx
+++ b/src/app/[orgId]/settings/sites/[niceId]/components/CreateSite.tsx
@@ -5,7 +5,7 @@ import { ChevronDownIcon } from "@radix-ui/react-icons";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { cn } from "@/lib/utils";
-import { toast } from "@/hooks/use-toast";
+import { toast } from "@/hooks/useToast";
import { Button, buttonVariants } from "@/components/ui/button";
import {
Form,
@@ -78,7 +78,7 @@ export function CreateSiteForm() {
setKeypair(generatedKeypair);
setIsLoading(false);
- api.get(`/org/${orgId}/pickSiteDefaults`)
+ api.get(`/org/${orgId}/pick-site-defaults`)
.catch((e) => {
toast({
title: "Error creating site...",
diff --git a/src/app/[orgId]/settings/sites/[niceId]/components/GeneralForm.tsx b/src/app/[orgId]/settings/sites/[niceId]/components/GeneralForm.tsx
index e380ffdd..1af7c03b 100644
--- a/src/app/[orgId]/settings/sites/[niceId]/components/GeneralForm.tsx
+++ b/src/app/[orgId]/settings/sites/[niceId]/components/GeneralForm.tsx
@@ -15,6 +15,8 @@ import {
import { Input } from "@/components/ui/input";
import { useSiteContext } from "@app/hooks/useSiteContext";
import { useForm } from "react-hook-form";
+import api from "@app/api";
+import { useToast } from "@app/hooks/useToast";
const GeneralFormSchema = z.object({
name: z.string(),
@@ -24,6 +26,7 @@ type GeneralFormValues = z.infer;
export function GeneralForm() {
const { site, updateSite } = useSiteContext();
+ const { toast } = useToast();
const form = useForm({
resolver: zodResolver(GeneralFormSchema),
@@ -34,7 +37,21 @@ export function GeneralForm() {
});
async function onSubmit(data: GeneralFormValues) {
- await updateSite({ name: data.name });
+ updateSite({ name: data.name });
+
+ await api
+ .post(`/site/${site?.siteId}`, {
+ name: data.name,
+ })
+ .catch((e) => {
+ toast({
+ variant: "destructive",
+ title: "Failed to update site",
+ description:
+ e.message ||
+ "An error occurred while updating the site.",
+ });
+ });
}
return (
diff --git a/src/app/[orgId]/settings/sites/components/SitesTable.tsx b/src/app/[orgId]/settings/sites/components/SitesTable.tsx
index b8da14d9..93466e3d 100644
--- a/src/app/[orgId]/settings/sites/components/SitesTable.tsx
+++ b/src/app/[orgId]/settings/sites/components/SitesTable.tsx
@@ -92,7 +92,7 @@ export const columns: ColumnDef[] = [
View settings
diff --git a/src/app/[orgId]/settings/users/components/InviteUserForm.tsx b/src/app/[orgId]/settings/users/components/InviteUserForm.tsx
index c693eb7f..2364233d 100644
--- a/src/app/[orgId]/settings/users/components/InviteUserForm.tsx
+++ b/src/app/[orgId]/settings/users/components/InviteUserForm.tsx
@@ -18,15 +18,30 @@ import {
SelectTrigger,
SelectValue,
} from "@app/components/ui/select";
-import { useToast } from "@app/hooks/use-toast";
+import { useToast } from "@app/hooks/useToast";
import { zodResolver } from "@hookform/resolvers/zod";
import { InviteUserBody, InviteUserResponse } from "@server/routers/user";
import { AxiosResponse } from "axios";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
-import { useParams } from "next/navigation";
import CopyTextBox from "@app/components/CopyTextBox";
+import {
+ Credenza,
+ CredenzaBody,
+ CredenzaClose,
+ CredenzaContent,
+ CredenzaDescription,
+ CredenzaFooter,
+ CredenzaHeader,
+ CredenzaTitle,
+} from "@app/components/Credenza";
+import { useOrgContext } from "@app/hooks/useOrgContext";
+
+type InviteUserFormProps = {
+ open: boolean;
+ setOpen: (open: boolean) => void;
+};
const formSchema = z.object({
email: z.string().email({ message: "Invalid email address" }),
@@ -34,9 +49,9 @@ const formSchema = z.object({
roleId: z.string(),
});
-export default function InviteUserForm() {
+export default function InviteUserForm({ open, setOpen }: InviteUserFormProps) {
const { toast } = useToast();
- const { orgId } = useParams();
+ const { org } = useOrgContext();
const [inviteLink, setInviteLink] = useState(null);
const [loading, setLoading] = useState(false);
@@ -74,7 +89,7 @@ export default function InviteUserForm() {
const res = await api
.post>(
- `/org/${orgId}/create-invite`,
+ `/org/${org?.org.orgId}/create-invite`,
{
email: values.email,
roleId: parseInt(values.roleId),
@@ -107,117 +122,151 @@ export default function InviteUserForm() {
return (
<>
- {!inviteLink && (
-
+
+ )}
+
+ {inviteLink && (
+
+
+ The user has been successfully invited. They
+ must access the link below to accept the
+ invitation.
+
+
+ The invite will expire in{" "}
+
+ {expiresInDays}{" "}
+ {expiresInDays === 1 ? "day" : "days"}
+
+ .
+
+
+
+ )}
+
+
-
-
- )}
-
- {inviteLink && (
-
-
- The user has been successfully invited. They must access
- the link below to accept the invitation.
-
-
- The invite will expire in{" "}
-
- {expiresInDays}{" "}
- {expiresInDays === 1 ? "day" : "days"}
-
- .
-
-
-
- )}
+
+
+
+
+
+
>
);
}
diff --git a/src/app/[orgId]/settings/users/components/UsersTable.tsx b/src/app/[orgId]/settings/users/components/UsersTable.tsx
index d8f730d7..54560985 100644
--- a/src/app/[orgId]/settings/users/components/UsersTable.tsx
+++ b/src/app/[orgId]/settings/users/components/UsersTable.tsx
@@ -10,16 +10,8 @@ import {
import { Button } from "@app/components/ui/button";
import { ArrowUpDown, MoreHorizontal } from "lucide-react";
import { UsersDataTable } from "./UsersDataTable";
-import {
- Dialog,
- DialogContent,
- DialogDescription,
- DialogHeader,
- DialogTitle,
-} from "@app/components/ui/dialog";
import { useState } from "react";
import InviteUserForm from "./InviteUserForm";
-import { Credenza, CredenzaTitle, CredenzaDescription, CredenzaHeader, CredenzaClose, CredenzaFooter, CredenzaContent, CredenzaBody } from "@app/components/Credenza";
export type UserRow = {
id: string;
@@ -74,19 +66,10 @@ export default function UsersTable({ users }: UsersTableProps) {
return (
<>
-
-
-
- Invite User
-
- Give new users access to your organization
-
-
-
-
-
-
-
+
;
@@ -10,15 +13,36 @@ type UsersPageProps = {
export default async function UsersPage(props: UsersPageProps) {
const params = await props.params;
+
let users: ListUsersResponse["users"] = [];
- try {
- const res = await internal.get>(
+ const res = await internal
+ .get>(
`/org/${params.orgId}/users`,
await authCookieHeader()
- );
+ )
+ .catch((e) => {
+ console.error(e);
+ });
+
+ if (res && res.status === 200) {
users = res.data.data.users;
- } catch (e) {
- console.error("Error fetching users", e);
+ }
+
+ let org: GetOrgResponse | null = null;
+ const getOrg = cache(async () =>
+ internal
+ .get>(
+ `/org/${params.orgId}`,
+ await authCookieHeader()
+ )
+ .catch((e) => {
+ console.error(e);
+ })
+ );
+ const orgRes = await getOrg();
+
+ if (orgRes && orgRes.status === 200) {
+ org = orgRes.data.data;
}
const userRows: UserRow[] = users.map((user) => {
@@ -40,7 +64,9 @@ export default async function UsersPage(props: UsersPageProps) {
-
+
+
+
>
);
}
diff --git a/src/app/auth/login/page.tsx b/src/app/auth/login/page.tsx
index 88d9fcad..e14fff25 100644
--- a/src/app/auth/login/page.tsx
+++ b/src/app/auth/login/page.tsx
@@ -2,12 +2,16 @@ import LoginForm from "@app/app/auth/login/LoginForm";
import { verifySession } from "@app/lib/auth/verifySession";
import Link from "next/link";
import { redirect } from "next/navigation";
+import { cache } from "react";
+
+export const dynamic = 'force-dynamic';
export default async function Page(props: {
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
}) {
const searchParams = await props.searchParams;
- const user = await verifySession();
+ const getUser = cache(verifySession);
+ const user = await getUser();
if (user) {
redirect("/");
diff --git a/src/app/auth/signup/page.tsx b/src/app/auth/signup/page.tsx
index c5088423..785a168c 100644
--- a/src/app/auth/signup/page.tsx
+++ b/src/app/auth/signup/page.tsx
@@ -2,12 +2,16 @@ import SignupForm from "@app/app/auth/signup/SignupForm";
import { verifySession } from "@app/lib/auth/verifySession";
import Link from "next/link";
import { redirect } from "next/navigation";
+import { cache } from "react";
+
+export const dynamic = 'force-dynamic';
export default async function Page(props: {
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
}) {
const searchParams = await props.searchParams;
- const user = await verifySession();
+ const getUser = cache(verifySession);
+ const user = await getUser();
if (user) {
redirect("/");
diff --git a/src/app/auth/verify-email/VerifyEmailForm.tsx b/src/app/auth/verify-email/VerifyEmailForm.tsx
index becf4dc9..b1071462 100644
--- a/src/app/auth/verify-email/VerifyEmailForm.tsx
+++ b/src/app/auth/verify-email/VerifyEmailForm.tsx
@@ -32,7 +32,7 @@ import { AxiosResponse } from "axios";
import { VerifyEmailResponse } from "@server/routers/auth";
import { Loader2 } from "lucide-react";
import { Alert, AlertDescription } from "../../../components/ui/alert";
-import { useToast } from "@app/hooks/use-toast";
+import { useToast } from "@app/hooks/useToast";
import { useRouter } from "next/navigation";
const FormSchema = z.object({
diff --git a/src/app/auth/verify-email/page.tsx b/src/app/auth/verify-email/page.tsx
index 2444ea13..4a9560aa 100644
--- a/src/app/auth/verify-email/page.tsx
+++ b/src/app/auth/verify-email/page.tsx
@@ -1,6 +1,9 @@
import VerifyEmailForm from "@app/app/auth/verify-email/VerifyEmailForm";
import { verifySession } from "@app/lib/auth/verifySession";
import { redirect } from "next/navigation";
+import { cache } from "react";
+
+export const dynamic = "force-dynamic";
export default async function Page(props: {
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
@@ -10,7 +13,8 @@ export default async function Page(props: {
}
const searchParams = await props.searchParams;
- const user = await verifySession();
+ const getUser = cache(verifySession);
+ const user = await getUser();
if (!user) {
redirect("/");
diff --git a/src/app/page.tsx b/src/app/page.tsx
index b1197cce..3ace08a6 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -7,12 +7,16 @@ import { AxiosResponse } from "axios";
import { ArrowUpRight } from "lucide-react";
import Link from "next/link";
import { redirect } from "next/navigation";
+import { cache } from "react";
+
+export const dynamic = "force-dynamic";
export default async function Page(props: {
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
}) {
const params = await props.searchParams; // this is needed to prevent static optimization
- const user = await verifySession();
+ const getUser = cache(verifySession);
+ const user = await getUser();
if (!user) {
redirect("/auth/login");
diff --git a/src/app/profile/account/account-form.tsx b/src/app/profile/account/account-form.tsx
index 2cb9bf1e..a3f48044 100644
--- a/src/app/profile/account/account-form.tsx
+++ b/src/app/profile/account/account-form.tsx
@@ -6,7 +6,7 @@ import { useForm } from "react-hook-form"
import { z } from "zod"
import { cn } from "@/lib/utils"
-import { toast } from "@/hooks/use-toast"
+import { toast } from "@/hooks/useToast"
import { Button } from "@/components/ui/button"
import {
Command,
diff --git a/src/app/profile/appearance/appearance-form.tsx b/src/app/profile/appearance/appearance-form.tsx
index 9a81f37a..3d085541 100644
--- a/src/app/profile/appearance/appearance-form.tsx
+++ b/src/app/profile/appearance/appearance-form.tsx
@@ -6,7 +6,7 @@ import { useForm } from "react-hook-form"
import { z } from "zod"
import { cn } from "@/lib/utils"
-import { toast } from "@/hooks/use-toast"
+import { toast } from "@/hooks/useToast"
import { Button, buttonVariants } from "@/components/ui/button"
import {
Form,
diff --git a/src/app/profile/display/display-form.tsx b/src/app/profile/display/display-form.tsx
index cf1c6c0d..950ecd5d 100644
--- a/src/app/profile/display/display-form.tsx
+++ b/src/app/profile/display/display-form.tsx
@@ -4,7 +4,7 @@ import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
-import { toast } from "@/hooks/use-toast"
+import { toast } from "@/hooks/useToast"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import {
diff --git a/src/app/profile/notifications/notifications-form.tsx b/src/app/profile/notifications/notifications-form.tsx
index cc191252..0eb215b5 100644
--- a/src/app/profile/notifications/notifications-form.tsx
+++ b/src/app/profile/notifications/notifications-form.tsx
@@ -5,7 +5,7 @@ import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
-import { toast } from "@/hooks/use-toast"
+import { toast } from "@/hooks/useToast"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import {
diff --git a/src/app/profile/profile-form.tsx b/src/app/profile/profile-form.tsx
index 0911ac0f..70ec6d6f 100644
--- a/src/app/profile/profile-form.tsx
+++ b/src/app/profile/profile-form.tsx
@@ -6,7 +6,7 @@ import { useFieldArray, useForm } from "react-hook-form"
import { z } from "zod"
import { cn } from "@/lib/utils"
-import { toast } from "@/hooks/use-toast"
+import { toast } from "@/hooks/useToast"
import { Button } from "@/components/ui/button"
import {
diff --git a/src/app/setup/page.tsx b/src/app/setup/page.tsx
index 62093157..483303e4 100644
--- a/src/app/setup/page.tsx
+++ b/src/app/setup/page.tsx
@@ -5,7 +5,7 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import Link from "next/link";
import api from "@app/api";
-import { toast } from "@app/hooks/use-toast";
+import { toast } from "@app/hooks/useToast";
import { useCallback, useEffect, useState } from "react";
import {
Card,
diff --git a/src/components/account-form.tsx b/src/components/account-form.tsx
index 2cb9bf1e..a3f48044 100644
--- a/src/components/account-form.tsx
+++ b/src/components/account-form.tsx
@@ -6,7 +6,7 @@ import { useForm } from "react-hook-form"
import { z } from "zod"
import { cn } from "@/lib/utils"
-import { toast } from "@/hooks/use-toast"
+import { toast } from "@/hooks/useToast"
import { Button } from "@/components/ui/button"
import {
Command,
diff --git a/src/components/appearance-form.tsx b/src/components/appearance-form.tsx
index 95ac2d2d..2d97cf21 100644
--- a/src/components/appearance-form.tsx
+++ b/src/components/appearance-form.tsx
@@ -1,169 +1,179 @@
-"use client"
+"use client";
-import { zodResolver } from "@hookform/resolvers/zod"
-import { ChevronDownIcon } from "@radix-ui/react-icons"
-import { useForm } from "react-hook-form"
-import { z } from "zod"
+import { zodResolver } from "@hookform/resolvers/zod";
+import { ChevronDownIcon } from "@radix-ui/react-icons";
+import { useForm } from "react-hook-form";
+import { z } from "zod";
-import { cn } from "@/lib/utils"
-import { toast } from "@/hooks/use-toast"
-import { Button, buttonVariants } from "@/components/ui/button"
+import { cn } from "@/lib/utils";
+import { toast } from "@/hooks/useToast";
+import { Button, buttonVariants } from "@/components/ui/button";
import {
- Form,
- FormControl,
- FormDescription,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
-} from "@/components/ui/form"
-import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
-import { useSiteContext } from "@app/hooks/useSiteContext"
+ Form,
+ FormControl,
+ FormDescription,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from "@/components/ui/form";
+import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
+import { useSiteContext } from "@app/hooks/useSiteContext";
const appearanceFormSchema = z.object({
- theme: z.enum(["light", "dark"], {
- required_error: "Please select a theme.",
- }),
- font: z.enum(["inter", "manrope", "system"], {
- invalid_type_error: "Select a font",
- required_error: "Please select a font.",
- }),
-})
+ theme: z.enum(["light", "dark"], {
+ required_error: "Please select a theme.",
+ }),
+ font: z.enum(["inter", "manrope", "system"], {
+ invalid_type_error: "Select a font",
+ required_error: "Please select a font.",
+ }),
+});
-type AppearanceFormValues = z.infer
+type AppearanceFormValues = z.infer;
// This can come from your database or API.
const defaultValues: Partial = {
- theme: "light",
-}
+ theme: "light",
+};
export function AppearanceForm() {
const site = useSiteContext();
console.log(site);
-
- const form = useForm({
- resolver: zodResolver(appearanceFormSchema),
- defaultValues,
- })
- function onSubmit(data: AppearanceFormValues) {
- toast({
- title: "You submitted the following values:",
- description: (
-
- {JSON.stringify(data, null, 2)}
-
- ),
- })
- }
+ const form = useForm({
+ resolver: zodResolver(appearanceFormSchema),
+ defaultValues,
+ });
- return (
-
-
- )
+
+
+
+ );
}
diff --git a/src/components/display-form.tsx b/src/components/display-form.tsx
index cf1c6c0d..950ecd5d 100644
--- a/src/components/display-form.tsx
+++ b/src/components/display-form.tsx
@@ -4,7 +4,7 @@ import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
-import { toast } from "@/hooks/use-toast"
+import { toast } from "@/hooks/useToast"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import {
diff --git a/src/components/notifications-form.tsx b/src/components/notifications-form.tsx
index cc191252..0eb215b5 100644
--- a/src/components/notifications-form.tsx
+++ b/src/components/notifications-form.tsx
@@ -5,7 +5,7 @@ import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
-import { toast } from "@/hooks/use-toast"
+import { toast } from "@/hooks/useToast"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import {
diff --git a/src/components/profile-form.tsx b/src/components/profile-form.tsx
index 0911ac0f..70ec6d6f 100644
--- a/src/components/profile-form.tsx
+++ b/src/components/profile-form.tsx
@@ -6,7 +6,7 @@ import { useFieldArray, useForm } from "react-hook-form"
import { z } from "zod"
import { cn } from "@/lib/utils"
-import { toast } from "@/hooks/use-toast"
+import { toast } from "@/hooks/useToast"
import { Button } from "@/components/ui/button"
import {
diff --git a/src/components/ui/toaster.tsx b/src/components/ui/toaster.tsx
index 171beb46..d1bd3c3d 100644
--- a/src/components/ui/toaster.tsx
+++ b/src/components/ui/toaster.tsx
@@ -1,6 +1,6 @@
"use client"
-import { useToast } from "@/hooks/use-toast"
+import { useToast } from "@/hooks/useToast"
import {
Toast,
ToastClose,
diff --git a/src/contexts/orgContext.ts b/src/contexts/orgContext.ts
new file mode 100644
index 00000000..d0ce10f5
--- /dev/null
+++ b/src/contexts/orgContext.ts
@@ -0,0 +1,11 @@
+import { GetOrgResponse } from "@server/routers/org";
+import { createContext } from "react";
+
+interface OrgContextType {
+ org: GetOrgResponse | null;
+ updateOrg: (updateOrg: Partial) => void;
+}
+
+const OrgContext = createContext(undefined);
+
+export default OrgContext;
diff --git a/src/contexts/resourceContext.ts b/src/contexts/resourceContext.ts
index 70b87b9b..e3090b3d 100644
--- a/src/contexts/resourceContext.ts
+++ b/src/contexts/resourceContext.ts
@@ -3,9 +3,11 @@ import { createContext } from "react";
interface ResourceContextType {
resource: GetResourceResponse | null;
- updateResource: (updatedResource: Partial) => Promise;
+ updateResource: (updatedResource: Partial) => void;
}
-const ResourceContext = createContext(undefined);
+const ResourceContext = createContext(
+ undefined
+);
-export default ResourceContext;
\ No newline at end of file
+export default ResourceContext;
diff --git a/src/contexts/siteContext.ts b/src/contexts/siteContext.ts
index 0e35b8bf..cb42cbd2 100644
--- a/src/contexts/siteContext.ts
+++ b/src/contexts/siteContext.ts
@@ -3,9 +3,9 @@ import { createContext } from "react";
interface SiteContextType {
site: GetSiteResponse | null;
- updateSite: (updatedSite: Partial) => Promise;
+ updateSite: (updatedSite: Partial) => void;
}
const SiteContext = createContext(undefined);
-export default SiteContext;
\ No newline at end of file
+export default SiteContext;
diff --git a/src/hooks/useOrgContext.ts b/src/hooks/useOrgContext.ts
new file mode 100644
index 00000000..ced28a6e
--- /dev/null
+++ b/src/hooks/useOrgContext.ts
@@ -0,0 +1,10 @@
+import OrgContext from "@app/contexts/orgContext";
+import { useContext } from "react";
+
+export function useOrgContext() {
+ const context = useContext(OrgContext);
+ if (context === undefined) {
+ throw new Error("useOrgContext must be used within a OrgProvider");
+ }
+ return context;
+}
diff --git a/src/hooks/useResourceContext.ts b/src/hooks/useResourceContext.ts
index 81abeae3..eb5b1f34 100644
--- a/src/hooks/useResourceContext.ts
+++ b/src/hooks/useResourceContext.ts
@@ -4,7 +4,9 @@ import { useContext } from "react";
export function useResourceContext() {
const context = useContext(ResourceContext);
if (context === undefined) {
- throw new Error('useResourceContext must be used within a ResourceProvider');
+ throw new Error(
+ "useResourceContext must be used within a ResourceProvider"
+ );
}
return context;
-}
\ No newline at end of file
+}
diff --git a/src/hooks/use-toast.ts b/src/hooks/useToast.ts
similarity index 100%
rename from src/hooks/use-toast.ts
rename to src/hooks/useToast.ts
diff --git a/src/lib/auth/verifySession.ts b/src/lib/auth/verifySession.ts
index 5b488fa3..59f9386c 100644
--- a/src/lib/auth/verifySession.ts
+++ b/src/lib/auth/verifySession.ts
@@ -14,4 +14,4 @@ export async function verifySession(): Promise {
} catch {
return null;
}
-}
+}
\ No newline at end of file
diff --git a/src/providers/OrgProvider.tsx b/src/providers/OrgProvider.tsx
new file mode 100644
index 00000000..29008bf8
--- /dev/null
+++ b/src/providers/OrgProvider.tsx
@@ -0,0 +1,39 @@
+"use client";
+
+import OrgContext from "@app/contexts/orgContext";
+import { GetOrgResponse } from "@server/routers/org";
+import { useState } from "react";
+
+interface OrgProviderProps {
+ children: React.ReactNode;
+ org: GetOrgResponse | null;
+}
+
+export function OrgProvider({ children, org: serverOrg }: OrgProviderProps) {
+ const [org, setOrg] = useState(serverOrg);
+
+ const updateOrg = (updatedOrg: Partial) => {
+ if (!org) {
+ throw new Error("No org to update");
+ }
+
+ setOrg((prev) => {
+ if (!prev) {
+ return prev;
+ }
+
+ return {
+ ...prev,
+ ...updatedOrg,
+ };
+ });
+ };
+
+ return (
+
+ {children}
+
+ );
+}
+
+export default OrgProvider;
diff --git a/src/providers/ResourceProvider.tsx b/src/providers/ResourceProvider.tsx
index 015a0f6f..28748697 100644
--- a/src/providers/ResourceProvider.tsx
+++ b/src/providers/ResourceProvider.tsx
@@ -1,10 +1,7 @@
"use client";
-import api from "@app/api";
import ResourceContext from "@app/contexts/resourceContext";
-import { toast } from "@app/hooks/use-toast";
import { GetResourceResponse } from "@server/routers/resource/getResource";
-import { AxiosResponse } from "axios";
import { useState } from "react";
interface ResourceProviderProps {
@@ -12,34 +9,36 @@ interface ResourceProviderProps {
resource: GetResourceResponse | null;
}
-export function ResourceProvider({ children, resource: serverResource }: ResourceProviderProps) {
- const [resource, setResource] = useState(serverResource);
+export function ResourceProvider({
+ children,
+ resource: serverResource,
+}: ResourceProviderProps) {
+ const [resource, setResource] = useState(
+ serverResource
+ );
- const updateResource = async (updatedResource: Partial) => {
- try {
- if (!resource) {
- throw new Error("No resource to update");
+ const updateResource = (updatedResource: Partial) => {
+ if (!resource) {
+ throw new Error("No resource to update");
+ }
+
+ setResource((prev) => {
+ if (!prev) {
+ return prev;
}
- const res = await api.post>(
- `resource/${resource.resourceId}`,
- updatedResource,
- );
- setResource(res.data.data);
- toast({
- title: "Resource updated!",
- });
- } catch (error) {
- console.error(error);
- toast({
- variant: "destructive",
- title: "Error updating resource...",
- })
- }
+ return {
+ ...prev,
+ ...updatedResource,
+ };
+ });
};
-
- return {children};
+ return (
+
+ {children}
+
+ );
}
-export default ResourceProvider;
\ No newline at end of file
+export default ResourceProvider;
diff --git a/src/providers/SiteProvider.tsx b/src/providers/SiteProvider.tsx
index fbc4f2e5..6129e092 100644
--- a/src/providers/SiteProvider.tsx
+++ b/src/providers/SiteProvider.tsx
@@ -1,10 +1,7 @@
"use client";
-import api from "@app/api";
import SiteContext from "@app/contexts/siteContext";
-import { toast } from "@app/hooks/use-toast";
import { GetSiteResponse } from "@server/routers/site/getSite";
-import { AxiosResponse } from "axios";
import { useState } from "react";
interface SiteProviderProps {
@@ -12,34 +9,32 @@ interface SiteProviderProps {
site: GetSiteResponse | null;
}
-export function SiteProvider({ children, site: serverSite }: SiteProviderProps) {
+export function SiteProvider({
+ children,
+ site: serverSite,
+}: SiteProviderProps) {
const [site, setSite] = useState(serverSite);
- const updateSite = async (updatedSite: Partial) => {
- try {
- if (!site) {
- throw new Error("No site to update");
- }
-
- const res = await api.post>(
- `site/${site.siteId}`,
- updatedSite,
- );
- setSite(res.data.data);
- toast({
- title: "Site updated!",
- });
- } catch (error) {
- console.error(error);
- toast({
- variant: "destructive",
- title: "Error updating site...",
- })
+ const updateSite = (updatedSite: Partial) => {
+ if (!site) {
+ throw new Error("No site to update");
}
+ setSite((prev) => {
+ if (!prev) {
+ return prev;
+ }
+ return {
+ ...prev,
+ ...updatedSite,
+ };
+ });
};
-
- return {children};
+ return (
+
+ {children}
+
+ );
}
-export default SiteProvider;
\ No newline at end of file
+export default SiteProvider;