add openapi registers

This commit is contained in:
miloschwartz
2025-04-06 22:44:14 -04:00
parent a76e3e00f7
commit d260450a84
50 changed files with 852 additions and 60 deletions

View File

@@ -20,6 +20,7 @@ import { fromError } from "zod-validation-error";
import logger from "@server/logger";
import { subdomainSchema } from "@server/lib/schemas";
import config from "@server/lib/config";
import { OpenAPITags, registry } from "@server/openApi";
const createResourceParamsSchema = z
.object({
@@ -90,6 +91,26 @@ const createRawResourceSchema = z
export type CreateResourceResponse = Resource;
registry.registerPath({
method: "put",
path: "/org/{orgId}/site/{siteId}/resource",
description: "Create a resource.",
tags: [OpenAPITags.Org, OpenAPITags.Resource],
request: {
params: createResourceParamsSchema,
body: {
content: {
"application/json": {
schema: createHttpResourceSchema.or(
createRawResourceSchema
)
}
}
}
},
responses: {}
});
export async function createResource(
req: Request,
res: Response,

View File

@@ -13,6 +13,7 @@ import {
isValidIP,
isValidUrlGlobPattern
} from "@server/lib/validators";
import { OpenAPITags, registry } from "@server/openApi";
const createResourceRuleSchema = z
.object({
@@ -33,6 +34,24 @@ const createResourceRuleParamsSchema = z
})
.strict();
registry.registerPath({
method: "put",
path: "/resource/{resourceId}/rule",
description: "Create a resource rule.",
tags: [OpenAPITags.Resource, OpenAPITags.Rule],
request: {
params: createResourceRuleParamsSchema,
body: {
content: {
"application/json": {
schema: createResourceRuleSchema
}
}
}
},
responses: {}
});
export async function createResourceRule(
req: Request,
res: Response,

View File

@@ -11,6 +11,7 @@ import { fromError } from "zod-validation-error";
import { addPeer } from "../gerbil/peers";
import { removeTargets } from "../newt/targets";
import { getAllowedIps } from "../target/helpers";
import { OpenAPITags, registry } from "@server/openApi";
// Define Zod schema for request parameters validation
const deleteResourceSchema = z
@@ -22,6 +23,17 @@ const deleteResourceSchema = z
})
.strict();
registry.registerPath({
method: "delete",
path: "/resource/{resourceId}",
description: "Delete a resource.",
tags: [OpenAPITags.Resource],
request: {
params: deleteResourceSchema
},
responses: {}
});
export async function deleteResource(
req: Request,
res: Response,
@@ -88,7 +100,11 @@ export async function deleteResource(
.where(eq(newts.siteId, site.siteId))
.limit(1);
removeTargets(newt.newtId, targetsToBeRemoved, deletedResource.protocol);
removeTargets(
newt.newtId,
targetsToBeRemoved,
deletedResource.protocol
);
}
}

View File

@@ -8,13 +8,11 @@ import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi";
const deleteResourceRuleSchema = z
.object({
ruleId: z
.string()
.transform(Number)
.pipe(z.number().int().positive()),
ruleId: z.string().transform(Number).pipe(z.number().int().positive()),
resourceId: z
.string()
.transform(Number)
@@ -22,6 +20,17 @@ const deleteResourceRuleSchema = z
})
.strict();
registry.registerPath({
method: "delete",
path: "/resource/{resourceId}/rule/{ruleId}",
description: "Delete a resource rule.",
tags: [OpenAPITags.Resource, OpenAPITags.Rule],
request: {
params: deleteResourceRuleSchema
},
responses: {}
});
export async function deleteResourceRule(
req: Request,
res: Response,

View File

@@ -8,6 +8,7 @@ import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import { fromError } from "zod-validation-error";
import logger from "@server/logger";
import { OpenAPITags, registry } from "@server/openApi";
const getResourceSchema = z
.object({
@@ -22,6 +23,17 @@ export type GetResourceResponse = Resource & {
siteName: string;
};
registry.registerPath({
method: "get",
path: "/resource/{resourceId}",
description: "Get a resource.",
tags: [OpenAPITags.Resource],
request: {
params: getResourceSchema
},
responses: {}
});
export async function getResource(
req: Request,
res: Response,

View File

@@ -8,6 +8,7 @@ import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi";
const getResourceWhitelistSchema = z
.object({
@@ -31,6 +32,17 @@ export type GetResourceWhitelistResponse = {
whitelist: NonNullable<Awaited<ReturnType<typeof queryWhitelist>>>;
};
registry.registerPath({
method: "get",
path: "/resource/{resourceId}/whitelist",
description: "Get the whitelist of emails for a specific resource.",
tags: [OpenAPITags.Resource],
request: {
params: getResourceWhitelistSchema
},
responses: {}
});
export async function getResourceWhitelist(
req: Request,
res: Response,

View File

@@ -8,6 +8,7 @@ import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi";
const listResourceRolesSchema = z
.object({
@@ -35,6 +36,17 @@ export type ListResourceRolesResponse = {
roles: NonNullable<Awaited<ReturnType<typeof query>>>;
};
registry.registerPath({
method: "get",
path: "/resource/{resourceId}/roles",
description: "List all roles for a resource.",
tags: [OpenAPITags.Resource, OpenAPITags.Role],
request: {
params: listResourceRolesSchema
},
responses: {}
});
export async function listResourceRoles(
req: Request,
res: Response,

View File

@@ -8,6 +8,7 @@ import createHttpError from "http-errors";
import { z } from "zod";
import { fromError } from "zod-validation-error";
import logger from "@server/logger";
import { OpenAPITags, registry } from "@server/openApi";
const listResourceRulesParamsSchema = z
.object({
@@ -56,6 +57,18 @@ export type ListResourceRulesResponse = {
pagination: { total: number; limit: number; offset: number };
};
registry.registerPath({
method: "get",
path: "/resource/{resourceId}/rules",
description: "List rules for a resource.",
tags: [OpenAPITags.Resource, OpenAPITags.Rule],
request: {
params: listResourceRulesParamsSchema,
query: listResourceRulesSchema
},
responses: {}
});
export async function listResourceRules(
req: Request,
res: Response,

View File

@@ -8,6 +8,7 @@ import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi";
const listResourceUsersSchema = z
.object({
@@ -33,6 +34,17 @@ export type ListResourceUsersResponse = {
users: NonNullable<Awaited<ReturnType<typeof queryUsers>>>;
};
registry.registerPath({
method: "get",
path: "/resource/{resourceId}/users",
description: "List all users for a resource.",
tags: [OpenAPITags.Resource, OpenAPITags.User],
request: {
params: listResourceUsersSchema
},
responses: {}
});
export async function listResourceUsers(
req: Request,
res: Response,

View File

@@ -16,6 +16,7 @@ import { sql, eq, or, inArray, and, count } from "drizzle-orm";
import logger from "@server/logger";
import stoi from "@server/lib/stoi";
import { fromZodError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi";
const listResourcesParamsSchema = z
.object({
@@ -128,6 +129,34 @@ export type ListResourcesResponse = {
pagination: { total: number; limit: number; offset: number };
};
registry.registerPath({
method: "get",
path: "/site/{siteId}/resources",
description: "List resources for a site.",
tags: [OpenAPITags.Site, OpenAPITags.Resource],
request: {
params: z.object({
siteId: z.number()
}),
query: listResourcesSchema
},
responses: {}
});
registry.registerPath({
method: "get",
path: "/org/{orgId}/resources",
description: "List resources for an organization.",
tags: [OpenAPITags.Org, OpenAPITags.Resource],
request: {
params: z.object({
orgId: z.string()
}),
query: listResourcesSchema
},
responses: {}
});
export async function listResources(
req: Request,
res: Response,

View File

@@ -10,6 +10,7 @@ import { hash } from "@node-rs/argon2";
import { response } from "@server/lib";
import logger from "@server/logger";
import { hashPassword } from "@server/auth/password";
import { OpenAPITags, registry } from "@server/openApi";
const setResourceAuthMethodsParamsSchema = z.object({
resourceId: z.string().transform(Number).pipe(z.number().int().positive())
@@ -21,6 +22,25 @@ const setResourceAuthMethodsBodySchema = z
})
.strict();
registry.registerPath({
method: "post",
path: "/resource/{resourceId}/password",
description:
"Set the password for a resource. Setting the password to null will remove it.",
tags: [OpenAPITags.Resource],
request: {
params: setResourceAuthMethodsParamsSchema,
body: {
content: {
"application/json": {
schema: setResourceAuthMethodsBodySchema
}
}
}
},
responses: {}
});
export async function setResourcePassword(
req: Request,
res: Response,

View File

@@ -11,9 +11,10 @@ import { response } from "@server/lib";
import stoi from "@server/lib/stoi";
import logger from "@server/logger";
import { hashPassword } from "@server/auth/password";
import { OpenAPITags, registry } from "@server/openApi";
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
@@ -21,25 +22,44 @@ const setResourceAuthMethodsBodySchema = z
pincode: z
.string()
.regex(/^\d{6}$/)
.or(z.null()),
.or(z.null())
})
.strict();
registry.registerPath({
method: "post",
path: "/resource/{resourceId}/pincode",
description:
"Set the PIN code for a resource. Setting the PIN code to null will remove it.",
tags: [OpenAPITags.Resource],
request: {
params: setResourceAuthMethodsParamsSchema,
body: {
content: {
"application/json": {
schema: setResourceAuthMethodsBodySchema
}
}
}
},
responses: {}
});
export async function setResourcePincode(
req: Request,
res: Response,
next: NextFunction,
next: NextFunction
): Promise<any> {
try {
const parsedParams = setResourceAuthMethodsParamsSchema.safeParse(
req.params,
req.params
);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedParams.error).toString(),
),
fromError(parsedParams.error).toString()
)
);
}
@@ -48,8 +68,8 @@ export async function setResourcePincode(
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedBody.error).toString(),
),
fromError(parsedBody.error).toString()
)
);
}
@@ -75,15 +95,12 @@ export async function setResourcePincode(
success: true,
error: false,
message: "Resource PIN code set successfully",
status: HttpCode.CREATED,
status: HttpCode.CREATED
});
} 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,6 +8,7 @@ import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { eq, and, ne } from "drizzle-orm";
import { OpenAPITags, registry } from "@server/openApi";
const setResourceRolesBodySchema = z
.object({
@@ -24,6 +25,25 @@ const setResourceRolesParamsSchema = z
})
.strict();
registry.registerPath({
method: "post",
path: "/resource/{resourceId}/roles",
description:
"Set roles for a resource. This will replace all existing roles.",
tags: [OpenAPITags.Resource, OpenAPITags.Role],
request: {
params: setResourceRolesParamsSchema,
body: {
content: {
"application/json": {
schema: setResourceRolesBodySchema
}
}
}
},
responses: {}
});
export async function setResourceRoles(
req: Request,
res: Response,

View File

@@ -8,6 +8,7 @@ import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { eq } from "drizzle-orm";
import { OpenAPITags, registry } from "@server/openApi";
const setUserResourcesBodySchema = z
.object({
@@ -24,6 +25,25 @@ const setUserResourcesParamsSchema = z
})
.strict();
registry.registerPath({
method: "post",
path: "/resource/{resourceId}/users",
description:
"Set users for a resource. This will replace all existing users.",
tags: [OpenAPITags.Resource, OpenAPITags.User],
request: {
params: setUserResourcesParamsSchema,
body: {
content: {
"application/json": {
schema: setUserResourcesBodySchema
}
}
}
},
responses: {}
});
export async function setResourceUsers(
req: Request,
res: Response,

View File

@@ -8,6 +8,7 @@ import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { and, eq } from "drizzle-orm";
import { OpenAPITags, registry } from "@server/openApi";
const setResourceWhitelistBodySchema = z
.object({
@@ -37,6 +38,25 @@ const setResourceWhitelistParamsSchema = z
})
.strict();
registry.registerPath({
method: "post",
path: "/resource/{resourceId}/whitelist",
description:
"Set email whitelist for a resource. This will replace all existing emails.",
tags: [OpenAPITags.Resource],
request: {
params: setResourceWhitelistParamsSchema,
body: {
content: {
"application/json": {
schema: setResourceWhitelistBodySchema
}
}
}
},
responses: {}
});
export async function setResourceWhitelist(
req: Request,
res: Response,

View File

@@ -11,6 +11,7 @@ import { fromError } from "zod-validation-error";
import { addPeer } from "../gerbil/peers";
import { addTargets, removeTargets } from "../newt/targets";
import { getAllowedIps } from "../target/helpers";
import { OpenAPITags, registry } from "@server/openApi";
const transferResourceParamsSchema = z
.object({
@@ -27,6 +28,25 @@ const transferResourceBodySchema = z
})
.strict();
registry.registerPath({
method: "post",
path: "/resource/{resourceId}/transfer",
description:
"Transfer a resource to a different site. This will also transfer the targets associated with the resource.",
tags: [OpenAPITags.Resource],
request: {
params: transferResourceParamsSchema,
body: {
content: {
"application/json": {
schema: transferResourceBodySchema
}
}
}
},
responses: {}
});
export async function transferResource(
req: Request,
res: Response,

View File

@@ -17,6 +17,8 @@ import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import config from "@server/lib/config";
import { subdomainSchema } from "@server/lib/schemas";
import { registry } from "@server/openApi";
import { OpenAPITags } from "@server/openApi";
const updateResourceParamsSchema = z
.object({
@@ -93,6 +95,26 @@ const updateRawResourceBodySchema = z
{ message: "Cannot update proxyPort" }
);
registry.registerPath({
method: "post",
path: "/resource/{resourceId}",
description: "Update a resource.",
tags: [OpenAPITags.Resource],
request: {
params: updateResourceParamsSchema,
body: {
content: {
"application/json": {
schema: updateHttpResourceBodySchema.and(
updateRawResourceBodySchema
)
}
}
}
},
responses: {}
});
export async function updateResource(
req: Request,
res: Response,

View File

@@ -13,6 +13,7 @@ import {
isValidIP,
isValidUrlGlobPattern
} from "@server/lib/validators";
import { OpenAPITags, registry } from "@server/openApi";
// Define Zod schema for request parameters validation
const updateResourceRuleParamsSchema = z
@@ -39,6 +40,24 @@ const updateResourceRuleSchema = z
message: "At least one field must be provided for update"
});
registry.registerPath({
method: "post",
path: "/resource/{resourceId}/rule/{ruleId}",
description: "Update a resource rule.",
tags: [OpenAPITags.Resource, OpenAPITags.Rule],
request: {
params: updateResourceRuleParamsSchema,
body: {
content: {
"application/json": {
schema: updateResourceRuleSchema
}
}
}
},
responses: {}
});
export async function updateResourceRule(
req: Request,
res: Response,