From 490ddfcd88d214a55746ed9fa7f23fb5520c63ee Mon Sep 17 00:00:00 2001 From: miloschwartz Date: Sun, 20 Apr 2025 17:00:45 -0400 Subject: [PATCH] add clients openapi registries --- server/openApi.ts | 3 ++- server/routers/client/createClient.ts | 24 +++++++++++++++---- server/routers/client/deleteClient.ts | 14 +++++++++++- server/routers/client/getClient.ts | 33 ++++++++++++++++++--------- server/routers/client/listClients.ts | 13 +++++++++++ server/routers/client/updateClient.ts | 21 ++++++++++++++++- 6 files changed, 90 insertions(+), 18 deletions(-) diff --git a/server/openApi.ts b/server/openApi.ts index 43e84e56..d5df61dc 100644 --- a/server/openApi.ts +++ b/server/openApi.ts @@ -12,5 +12,6 @@ export enum OpenAPITags { Target = "Target", Rule = "Rule", AccessToken = "Access Token", - Idp = "Identity Provider" + Idp = "Identity Provider", + Client = "Client" } diff --git a/server/routers/client/createClient.ts b/server/routers/client/createClient.ts index 75d0bdc5..1dffcd8f 100644 --- a/server/routers/client/createClient.ts +++ b/server/routers/client/createClient.ts @@ -23,6 +23,7 @@ import moment from "moment"; import { hashPassword } from "@server/auth/password"; import { isValidCIDR, isValidIP } from "@server/lib/validators"; import { isIpInCidr } from "@server/lib/ip"; +import { OpenAPITags, registry } from "@server/openApi"; const createClientParamsSchema = z .object({ @@ -45,6 +46,24 @@ export type CreateClientBody = z.infer; export type CreateClientResponse = Client; +registry.registerPath({ + method: "put", + path: "/org/{orgId}/client", + description: "Create a new client.", + tags: [OpenAPITags.Client, OpenAPITags.Org], + request: { + params: createClientParamsSchema, + body: { + content: { + "application/json": { + schema: createClientSchema + } + } + } + }, + responses: {} +}); + export async function createClient( req: Request, res: Response, @@ -90,10 +109,7 @@ export async function createClient( ); } - const [org] = await db - .select() - .from(orgs) - .where(eq(orgs.orgId, orgId)); + const [org] = await db.select().from(orgs).where(eq(orgs.orgId, orgId)); if (!org) { return next( diff --git a/server/routers/client/deleteClient.ts b/server/routers/client/deleteClient.ts index a46d4f46..21185d26 100644 --- a/server/routers/client/deleteClient.ts +++ b/server/routers/client/deleteClient.ts @@ -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 deleteClientSchema = z .object({ @@ -15,6 +16,17 @@ const deleteClientSchema = z }) .strict(); +registry.registerPath({ + method: "delete", + path: "/client/{clientId}", + description: "Delete a client by its client ID.", + tags: [OpenAPITags.Client], + request: { + params: deleteClientSchema + }, + responses: {} +}); + export async function deleteClient( req: Request, res: Response, @@ -73,4 +85,4 @@ export async function deleteClient( createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred") ); } -} \ No newline at end of file +} diff --git a/server/routers/client/getClient.ts b/server/routers/client/getClient.ts index ae1178ff..b3608719 100644 --- a/server/routers/client/getClient.ts +++ b/server/routers/client/getClient.ts @@ -9,28 +9,37 @@ import createHttpError from "http-errors"; import logger from "@server/logger"; import stoi from "@server/lib/stoi"; import { fromError } from "zod-validation-error"; +import { OpenAPITags, registry } from "@server/openApi"; const getClientSchema = z .object({ - clientId: z - .string() - .transform(stoi) - .pipe(z.number().int().positive()), + clientId: z.string().transform(stoi).pipe(z.number().int().positive()), orgId: z.string().optional() }) .strict(); async function query(clientId: number) { - const [res] = await db - .select() - .from(clients) - .where(eq(clients.clientId, clientId)) - .limit(1); - return res; + const [res] = await db + .select() + .from(clients) + .where(eq(clients.clientId, clientId)) + .limit(1); + return res; } export type GetClientResponse = NonNullable>>; +registry.registerPath({ + method: "get", + path: "/org/{orgId}/client/{clientId}", + description: "Get a client by its client ID.", + tags: [OpenAPITags.Client, OpenAPITags.Org], + request: { + params: getClientSchema + }, + responses: {} +}); + export async function getClient( req: Request, res: Response, @@ -55,7 +64,9 @@ export async function getClient( const client = await query(clientId); if (!client) { - return next(createHttpError(HttpCode.NOT_FOUND, "Client not found")); + return next( + createHttpError(HttpCode.NOT_FOUND, "Client not found") + ); } return response(res, { diff --git a/server/routers/client/listClients.ts b/server/routers/client/listClients.ts index 9a0ae23c..d76c8b9e 100644 --- a/server/routers/client/listClients.ts +++ b/server/routers/client/listClients.ts @@ -15,6 +15,7 @@ import { NextFunction, Request, Response } from "express"; import createHttpError from "http-errors"; import { z } from "zod"; import { fromError } from "zod-validation-error"; +import { OpenAPITags, registry } from "@server/openApi"; const listClientsParamsSchema = z .object({ @@ -86,6 +87,18 @@ export type ListClientsResponse = { pagination: { total: number; limit: number; offset: number }; }; +registry.registerPath({ + method: "get", + path: "/org/{orgId}/clients", + description: "List all clients for an organization.", + tags: [OpenAPITags.Client, OpenAPITags.Org], + request: { + query: listClientsSchema, + params: listClientsParamsSchema + }, + responses: {} +}); + export async function listClients( req: Request, res: Response, diff --git a/server/routers/client/updateClient.ts b/server/routers/client/updateClient.ts index 097b4a4d..f3f00c47 100644 --- a/server/routers/client/updateClient.ts +++ b/server/routers/client/updateClient.ts @@ -11,6 +11,7 @@ import createHttpError from "http-errors"; import logger from "@server/logger"; import { eq, and } from "drizzle-orm"; import { fromError } from "zod-validation-error"; +import { OpenAPITags, registry } from "@server/openApi"; const updateClientParamsSchema = z .object({ @@ -27,6 +28,24 @@ const updateClientSchema = z export type UpdateClientBody = z.infer; +registry.registerPath({ + method: "post", + path: "/client/{clientId}", + description: "Update a client by its client ID.", + tags: [OpenAPITags.Client], + request: { + params: updateClientParamsSchema, + body: { + content: { + "application/json": { + schema: updateClientSchema + } + } + } + }, + responses: {} +}); + export async function updateClient( req: Request, res: Response, @@ -121,4 +140,4 @@ export async function updateClient( createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred") ); } -} \ No newline at end of file +}