fix issues from test deploy

This commit is contained in:
Milo Schwartz
2024-12-21 21:01:12 -05:00
parent 3fb3be1f1e
commit ce5df3b0b9
92 changed files with 1410 additions and 1019 deletions

View File

@@ -17,13 +17,21 @@ import logger from "@server/logger";
import { verify } from "@node-rs/argon2";
import { isWithinExpirationDate } from "oslo";
const authWithAccessTokenBodySchema = z.object({
accessToken: z.string()
});
const authWithAccessTokenBodySchema = z
.object({
accessToken: z.string(),
accessTokenId: z.string()
})
.strict();
const authWithAccessTokenParamsSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive())
});
const authWithAccessTokenParamsSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
export type AuthWithAccessTokenResponse = {
session?: string;
@@ -57,9 +65,7 @@ export async function authWithAccessToken(
}
const { resourceId } = parsedParams.data;
const { accessToken: at } = parsedBody.data;
const [accessTokenId, accessToken] = at.split(".");
const { accessToken, accessTokenId } = parsedBody.data;
try {
const [result] = await db
@@ -86,7 +92,7 @@ export async function authWithAccessToken(
HttpCode.UNAUTHORIZED,
createHttpError(
HttpCode.BAD_REQUEST,
"Email is not whitelisted"
"Access token does not exist for resource"
)
)
);
@@ -98,15 +104,12 @@ export async function authWithAccessToken(
);
}
// const validCode = await verify(tokenItem.tokenHash, accessToken, {
// memoryCost: 19456,
// timeCost: 2,
// outputLen: 32,
// parallelism: 1
// });
logger.debug(`${accessToken} ${tokenItem.tokenHash}`)
const validCode = accessToken === tokenItem.tokenHash;
const validCode = await verify(tokenItem.tokenHash, accessToken, {
memoryCost: 19456,
timeCost: 2,
outputLen: 32,
parallelism: 1
});
if (!validCode) {
return next(
createHttpError(HttpCode.UNAUTHORIZED, "Invalid access token")

View File

@@ -14,14 +14,22 @@ import {
serializeResourceSessionCookie
} from "@server/auth/resource";
import config from "@server/config";
import logger from "@server/logger";
export const authWithPasswordBodySchema = z.object({
password: z.string()
});
export const authWithPasswordBodySchema = z
.object({
password: z.string()
})
.strict();
export const authWithPasswordParamsSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive())
});
export const authWithPasswordParamsSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
export type AuthWithPasswordResponse = {
session?: string;
@@ -120,10 +128,7 @@ export async function authWithPassword(
passwordId: definedPassword.passwordId
});
const cookieName = `${config.server.resource_session_cookie_name}_${resource.resourceId}`;
const cookie = serializeResourceSessionCookie(
cookieName,
token,
);
const cookie = serializeResourceSessionCookie(cookieName, token);
res.appendHeader("Set-Cookie", cookie);
return response<AuthWithPasswordResponse>(res, {
@@ -136,6 +141,7 @@ export async function authWithPassword(
status: HttpCode.OK
});
} catch (e) {
logger.error(e);
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,

View File

@@ -24,13 +24,20 @@ import config from "@server/config";
import { AuthWithPasswordResponse } from "./authWithPassword";
import { isValidOtp, sendResourceOtpEmail } from "@server/auth/resourceOtp";
export const authWithPincodeBodySchema = z.object({
pincode: z.string()
});
export const authWithPincodeBodySchema = z
.object({
pincode: z.string()
})
.strict();
export const authWithPincodeParamsSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive())
});
export const authWithPincodeParamsSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
export type AuthWithPincodeResponse = {
session?: string;
@@ -128,10 +135,7 @@ export async function authWithPincode(
pincodeId: definedPincode.pincodeId
});
const cookieName = `${config.server.resource_session_cookie_name}_${resource.resourceId}`;
const cookie = serializeResourceSessionCookie(
cookieName,
token,
);
const cookie = serializeResourceSessionCookie(cookieName, token);
res.appendHeader("Set-Cookie", cookie);
return response<AuthWithPincodeResponse>(res, {

View File

@@ -22,14 +22,21 @@ import config from "@server/config";
import { isValidOtp, sendResourceOtpEmail } from "@server/auth/resourceOtp";
import logger from "@server/logger";
const authWithWhitelistBodySchema = z.object({
email: z.string().email(),
otp: z.string().optional()
});
const authWithWhitelistBodySchema = z
.object({
email: z.string().email(),
otp: z.string().optional()
})
.strict();
const authWithWhitelistParamsSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive())
});
const authWithWhitelistParamsSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
export type AuthWithWhitelistResponse = {
otpSent?: boolean;
@@ -171,10 +178,7 @@ export async function authWithWhitelist(
whitelistId: whitelistedEmail.whitelistId
});
const cookieName = `${config.server.resource_session_cookie_name}_${resource.resourceId}`;
const cookie = serializeResourceSessionCookie(
cookieName,
token,
);
const cookie = serializeResourceSessionCookie(cookieName, token);
res.appendHeader("Set-Cookie", cookie);
return response<AuthWithWhitelistResponse>(res, {

View File

@@ -1,3 +1,4 @@
import { SqliteError } from "better-sqlite3";
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { db } from "@server/db";
@@ -7,7 +8,7 @@ import {
resources,
roleResources,
roles,
userResources,
userResources
} from "@server/db/schema";
import response from "@server/utils/response";
import HttpCode from "@server/types/HttpCode";
@@ -16,16 +17,19 @@ import { eq, and } from "drizzle-orm";
import stoi from "@server/utils/stoi";
import { fromError } from "zod-validation-error";
import { subdomainSchema } from "@server/schemas/subdomainSchema";
import logger from "@server/logger";
const createResourceParamsSchema = z.object({
siteId: z.string().transform(stoi).pipe(z.number().int().positive()),
orgId: z.string(),
});
const createResourceParamsSchema = z
.object({
siteId: z.string().transform(stoi).pipe(z.number().int().positive()),
orgId: z.string()
})
.strict();
const createResourceSchema = z
.object({
name: z.string().min(1).max(255),
subdomain: subdomainSchema,
subdomain: subdomainSchema
})
.strict();
@@ -94,7 +98,7 @@ export async function createResource(
orgId,
name,
subdomain,
ssl: true,
ssl: true
})
.returning();
@@ -112,14 +116,14 @@ export async function createResource(
await db.insert(roleResources).values({
roleId: adminRole[0].roleId,
resourceId: newResource[0].resourceId,
resourceId: newResource[0].resourceId
});
if (req.userOrgRoleId != adminRole[0].roleId) {
// make sure the user can access the resource
await db.insert(userResources).values({
userId: req.user?.userId!,
resourceId: newResource[0].resourceId,
resourceId: newResource[0].resourceId
});
}
@@ -128,9 +132,22 @@ export async function createResource(
success: true,
error: false,
message: "Resource created successfully",
status: HttpCode.CREATED,
status: HttpCode.CREATED
});
} catch (error) {
if (
error instanceof SqliteError &&
error.code === "SQLITE_CONSTRAINT_UNIQUE"
) {
return next(
createHttpError(
HttpCode.CONFLICT,
"Resource with that subdomain already exists"
)
);
}
logger.error(error);
return next(
createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred")
);

View File

@@ -12,9 +12,14 @@ import { addPeer } from "../gerbil/peers";
import { removeTargets } from "../newt/targets";
// Define Zod schema for request parameters validation
const deleteResourceSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
});
const deleteResourceSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
export async function deleteResource(
req: Request,
@@ -67,20 +72,20 @@ export async function deleteResource(
)
);
}
if (site.pubKey) {
if (site.type == "wireguard") {
// TODO: is this all inefficient?
// Fetch resources for this site
const resourcesRes = await db.query.resources.findMany({
where: eq(resources.siteId, site.siteId),
where: eq(resources.siteId, site.siteId)
});
// 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),
where: eq(targets.resourceId, resource.resourceId)
});
return targetsRes.map((target) => `${target.ip}/32`);
})
@@ -88,7 +93,7 @@ export async function deleteResource(
await addPeer(site.exitNodeId!, {
publicKey: site.pubKey,
allowedIps: targetIps.flat(),
allowedIps: targetIps.flat()
});
} else if (site.type == "newt") {
// get the newt on the site by querying the newt table for siteId
@@ -107,7 +112,7 @@ export async function deleteResource(
success: true,
error: false,
message: "Resource deleted successfully",
status: HttpCode.OK,
status: HttpCode.OK
});
} catch (error) {
logger.error(error);

View File

@@ -7,10 +7,16 @@ import response from "@server/utils/response";
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import { fromError } from "zod-validation-error";
import logger from "@server/logger";
const getResourceSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
});
const getResourceSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
export type GetResourceResponse = Resource;
@@ -52,9 +58,10 @@ export async function getResource(
success: true,
error: false,
message: "Resource retrieved successfully",
status: HttpCode.OK,
status: HttpCode.OK
});
} catch (error) {
logger.error(error);
return next(
createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred")
);

View File

@@ -4,17 +4,23 @@ import { db } from "@server/db";
import {
resourcePassword,
resourcePincode,
resources,
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 { fromError } from "zod-validation-error";
import logger from "@server/logger";
const getResourceAuthInfoSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
});
const getResourceAuthInfoSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
export type GetResourceAuthInfoResponse = {
resourceId: number;
@@ -30,7 +36,7 @@ export type GetResourceAuthInfoResponse = {
export async function getResourceAuthInfo(
req: Request,
res: Response,
next: NextFunction,
next: NextFunction
): Promise<any> {
try {
const parsedParams = getResourceAuthInfoSchema.safeParse(req.params);
@@ -38,8 +44,8 @@ export async function getResourceAuthInfo(
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedParams.error).toString(),
),
fromError(parsedParams.error).toString()
)
);
}
@@ -50,11 +56,11 @@ export async function getResourceAuthInfo(
.from(resources)
.leftJoin(
resourcePincode,
eq(resourcePincode.resourceId, resources.resourceId),
eq(resourcePincode.resourceId, resources.resourceId)
)
.leftJoin(
resourcePassword,
eq(resourcePassword.resourceId, resources.resourceId),
eq(resourcePassword.resourceId, resources.resourceId)
)
.where(eq(resources.resourceId, resourceId))
.limit(1);
@@ -67,7 +73,7 @@ export async function getResourceAuthInfo(
if (!resource) {
return next(
createHttpError(HttpCode.NOT_FOUND, "Resource not found"),
createHttpError(HttpCode.NOT_FOUND, "Resource not found")
);
}
@@ -85,14 +91,12 @@ export async function getResourceAuthInfo(
success: true,
error: false,
message: "Resource auth info retrieved successfully",
status: HttpCode.OK,
status: HttpCode.OK
});
} catch (error) {
logger.error(error);
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"An error occurred",
),
createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred")
);
}
}

View File

@@ -9,9 +9,14 @@ import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
const getResourceWhitelistSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive())
});
const getResourceWhitelistSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
async function queryWhitelist(resourceId: number) {
return await db

View File

@@ -9,9 +9,14 @@ import createHttpError from "http-errors";
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()),
});
const listResourceRolesSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
async function query(resourceId: number) {
return await db
@@ -19,7 +24,7 @@ async function query(resourceId: number) {
roleId: roles.roleId,
name: roles.name,
description: roles.description,
isAdmin: roles.isAdmin,
isAdmin: roles.isAdmin
})
.from(roleResources)
.innerJoin(roles, eq(roleResources.roleId, roles.roleId))
@@ -52,12 +57,12 @@ export async function listResourceRoles(
return response<ListResourceRolesResponse>(res, {
data: {
roles: resourceRolesList,
roles: resourceRolesList
},
success: true,
error: false,
message: "Resource roles retrieved successfully",
status: HttpCode.OK,
status: HttpCode.OK
});
} catch (error) {
logger.error(error);

View File

@@ -9,15 +9,20 @@ import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
const listResourceUsersSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
});
const listResourceUsersSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
async function queryUsers(resourceId: number) {
return await db
.select({
userId: userResources.userId,
email: users.email,
email: users.email
})
.from(userResources)
.innerJoin(users, eq(userResources.userId, users.userId))
@@ -50,12 +55,12 @@ export async function listResourceUsers(
return response<ListResourceUsersResponse>(res, {
data: {
users: resourceUsersList,
users: resourceUsersList
},
success: true,
error: false,
message: "Resource users retrieved successfully",
status: HttpCode.OK,
status: HttpCode.OK
});
} catch (error) {
logger.error(error);

View File

@@ -7,7 +7,7 @@ import {
userResources,
roleResources,
resourcePassword,
resourcePincode,
resourcePincode
} from "@server/db/schema";
import response from "@server/utils/response";
import HttpCode from "@server/types/HttpCode";
@@ -23,10 +23,11 @@ const listResourcesParamsSchema = z
.optional()
.transform(stoi)
.pipe(z.number().int().positive().optional()),
orgId: z.string().optional(),
orgId: z.string().optional()
})
.strict()
.refine((data) => !!data.siteId !== !!data.orgId, {
message: "Either siteId or orgId must be provided, but not both",
message: "Either siteId or orgId must be provided, but not both"
});
const listResourcesSchema = z.object({
@@ -42,13 +43,13 @@ const listResourcesSchema = z.object({
.optional()
.default("0")
.transform(Number)
.pipe(z.number().int().nonnegative()),
.pipe(z.number().int().nonnegative())
});
function queryResources(
accessibleResourceIds: number[],
siteId?: number,
orgId?: string,
orgId?: string
) {
if (siteId) {
return db
@@ -68,17 +69,17 @@ function queryResources(
.leftJoin(sites, eq(resources.siteId, sites.siteId))
.leftJoin(
resourcePassword,
eq(resourcePassword.resourceId, resources.resourceId),
eq(resourcePassword.resourceId, resources.resourceId)
)
.leftJoin(
resourcePincode,
eq(resourcePincode.resourceId, resources.resourceId),
eq(resourcePincode.resourceId, resources.resourceId)
)
.where(
and(
inArray(resources.resourceId, accessibleResourceIds),
eq(resources.siteId, siteId),
),
eq(resources.siteId, siteId)
)
);
} else if (orgId) {
return db
@@ -98,17 +99,17 @@ function queryResources(
.leftJoin(sites, eq(resources.siteId, sites.siteId))
.leftJoin(
resourcePassword,
eq(resourcePassword.resourceId, resources.resourceId),
eq(resourcePassword.resourceId, resources.resourceId)
)
.leftJoin(
resourcePincode,
eq(resourcePincode.resourceId, resources.resourceId),
eq(resourcePincode.resourceId, resources.resourceId)
)
.where(
and(
inArray(resources.resourceId, accessibleResourceIds),
eq(resources.orgId, orgId),
),
eq(resources.orgId, orgId)
)
);
}
}
@@ -121,7 +122,7 @@ export type ListResourcesResponse = {
export async function listResources(
req: Request,
res: Response,
next: NextFunction,
next: NextFunction
): Promise<any> {
try {
const parsedQuery = listResourcesSchema.safeParse(req.query);
@@ -129,8 +130,8 @@ export async function listResources(
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedQuery.error.errors.map((e) => e.message).join(", "),
),
parsedQuery.error.errors.map((e) => e.message).join(", ")
)
);
}
const { limit, offset } = parsedQuery.data;
@@ -140,8 +141,8 @@ export async function listResources(
return next(
createHttpError(
HttpCode.BAD_REQUEST,
parsedParams.error.errors.map((e) => e.message).join(", "),
),
parsedParams.error.errors.map((e) => e.message).join(", ")
)
);
}
const { siteId, orgId } = parsedParams.data;
@@ -150,29 +151,29 @@ export async function listResources(
return next(
createHttpError(
HttpCode.FORBIDDEN,
"User does not have access to this organization",
),
"User does not have access to this organization"
)
);
}
const accessibleResources = await db
.select({
resourceId: sql<number>`COALESCE(${userResources.resourceId}, ${roleResources.resourceId})`,
resourceId: sql<number>`COALESCE(${userResources.resourceId}, ${roleResources.resourceId})`
})
.from(userResources)
.fullJoin(
roleResources,
eq(userResources.resourceId, roleResources.resourceId),
eq(userResources.resourceId, roleResources.resourceId)
)
.where(
or(
eq(userResources.userId, req.user!.userId),
eq(roleResources.roleId, req.userOrgRoleId!),
),
eq(roleResources.roleId, req.userOrgRoleId!)
)
);
const accessibleResourceIds = accessibleResources.map(
(resource) => resource.resourceId,
(resource) => resource.resourceId
);
let countQuery: any = db
@@ -192,21 +193,18 @@ export async function listResources(
pagination: {
total: totalCount,
limit,
offset,
},
offset
}
},
success: true,
error: false,
message: "Resources retrieved successfully",
status: HttpCode.OK,
status: HttpCode.OK
});
} catch (error) {
logger.error(error);
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"An error occurred",
),
createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred")
);
}
}

View File

@@ -8,14 +8,15 @@ import createHttpError from "http-errors";
import { fromError } from "zod-validation-error";
import { hash } from "@node-rs/argon2";
import { response } from "@server/utils";
import logger from "@server/logger";
const setResourceAuthMethodsParamsSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
resourceId: z.string().transform(Number).pipe(z.number().int().positive())
});
const setResourceAuthMethodsBodySchema = z
.object({
password: z.string().min(4).max(100).nullable(),
password: z.string().min(4).max(100).nullable()
})
.strict();
@@ -60,7 +61,7 @@ export async function setResourcePassword(
memoryCost: 19456,
timeCost: 2,
outputLen: 32,
parallelism: 1,
parallelism: 1
});
await trx
@@ -74,9 +75,10 @@ export async function setResourcePassword(
success: true,
error: false,
message: "Resource password set successfully",
status: HttpCode.CREATED,
status: HttpCode.CREATED
});
} catch (error) {
logger.error(error);
return next(
createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred")
);

View File

@@ -9,6 +9,7 @@ import { fromError } from "zod-validation-error";
import { hash } from "@node-rs/argon2";
import { response } from "@server/utils";
import stoi from "@server/utils/stoi";
import logger from "@server/logger";
const setResourceAuthMethodsParamsSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
@@ -81,6 +82,7 @@ export async function setResourcePincode(
status: HttpCode.CREATED,
});
} catch (error) {
logger.error(error);
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,

View File

@@ -9,13 +9,20 @@ import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { eq, and, ne } from "drizzle-orm";
const setResourceRolesBodySchema = z.object({
roleIds: z.array(z.number().int().positive()),
});
const setResourceRolesBodySchema = z
.object({
roleIds: z.array(z.number().int().positive())
})
.strict();
const setResourceRolesParamsSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
});
const setResourceRolesParamsSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
export async function setResourceRoles(
req: Request,
@@ -99,7 +106,7 @@ export async function setResourceRoles(
success: true,
error: false,
message: "Roles set for resource successfully",
status: HttpCode.CREATED,
status: HttpCode.CREATED
});
});
} catch (error) {

View File

@@ -9,13 +9,20 @@ import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { eq } from "drizzle-orm";
const setUserResourcesBodySchema = z.object({
userIds: z.array(z.string()),
});
const setUserResourcesBodySchema = z
.object({
userIds: z.array(z.string())
})
.strict();
const setUserResourcesParamsSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
});
const setUserResourcesParamsSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
export async function setResourceUsers(
req: Request,
@@ -66,7 +73,7 @@ export async function setResourceUsers(
success: true,
error: false,
message: "Users set for resource successfully",
status: HttpCode.CREATED,
status: HttpCode.CREATED
});
});
} catch (error) {

View File

@@ -9,13 +9,20 @@ import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { and, eq } from "drizzle-orm";
const setResourceWhitelistBodySchema = z.object({
emails: z.array(z.string().email()).max(50)
});
const setResourceWhitelistBodySchema = z
.object({
emails: z.array(z.string().email()).max(50)
})
.strict();
const setResourceWhitelistParamsSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive())
});
const setResourceWhitelistParamsSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
export async function setResourceWhitelist(
req: Request,

View File

@@ -10,9 +10,14 @@ import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { subdomainSchema } from "@server/schemas/subdomainSchema";
const updateResourceParamsSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive()),
});
const updateResourceParamsSchema = z
.object({
resourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
})
.strict();
const updateResourceBodySchema = z
.object({
@@ -21,18 +26,18 @@ const updateResourceBodySchema = z
ssl: z.boolean().optional(),
sso: z.boolean().optional(),
blockAccess: z.boolean().optional(),
emailWhitelistEnabled: z.boolean().optional(),
emailWhitelistEnabled: z.boolean().optional()
// siteId: z.number(),
})
.strict()
.refine((data) => Object.keys(data).length > 0, {
message: "At least one field must be provided for update",
message: "At least one field must be provided for update"
});
export async function updateResource(
req: Request,
res: Response,
next: NextFunction,
next: NextFunction
): Promise<any> {
try {
const parsedParams = updateResourceParamsSchema.safeParse(req.params);
@@ -40,8 +45,8 @@ export async function updateResource(
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedParams.error).toString(),
),
fromError(parsedParams.error).toString()
)
);
}
@@ -50,8 +55,8 @@ export async function updateResource(
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedBody.error).toString(),
),
fromError(parsedBody.error).toString()
)
);
}
@@ -68,8 +73,8 @@ export async function updateResource(
return next(
createHttpError(
HttpCode.NOT_FOUND,
`Resource with ID ${resourceId} not found`,
),
`Resource with ID ${resourceId} not found`
)
);
}
@@ -77,8 +82,8 @@ export async function updateResource(
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Resource does not have a domain",
),
"Resource does not have a domain"
)
);
}
@@ -88,7 +93,7 @@ export async function updateResource(
const updatePayload = {
...updateData,
...(fullDomain && { fullDomain }),
...(fullDomain && { fullDomain })
};
const updatedResource = await db
@@ -101,8 +106,8 @@ export async function updateResource(
return next(
createHttpError(
HttpCode.NOT_FOUND,
`Resource with ID ${resourceId} not found`,
),
`Resource with ID ${resourceId} not found`
)
);
}
@@ -111,15 +116,12 @@ export async function updateResource(
success: true,
error: false,
message: "Resource updated successfully",
status: HttpCode.OK,
status: HttpCode.OK
});
} catch (error) {
logger.error(error);
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"An error occurred",
),
createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred")
);
}
}