Add concrete OpenAPI data schemas for selected routes

Agent-Logs-Url: https://github.com/fosrl/pangolin/sessions/7b395a8e-7fae-4f4d-952e-4030fea08262

Co-authored-by: oschwartz10612 <4999704+oschwartz10612@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-05-17 21:25:53 +00:00
committed by GitHub
parent a0a093ed0b
commit 15a9eb28d9
37 changed files with 403 additions and 342 deletions

View File

@@ -0,0 +1,11 @@
import { z } from "zod";
export function createApiResponseSchema<T extends z.ZodTypeAny>(dataSchema: T) {
return z.object({
data: dataSchema.nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
});
}

View File

@@ -13,6 +13,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db } from "@server/db"; import { db } from "@server/db";
import { import {
alertRules, alertRules,
@@ -148,6 +149,8 @@ const bodySchema = z
export type UpdateAlertRuleResponse = { export type UpdateAlertRuleResponse = {
alertRuleId: number; alertRuleId: number;
}; };
const UpdateAlertRuleResponseDataSchema = z.object({alertRuleId: z.number()});
registry.registerPath({ registry.registerPath({
method: "post", method: "post",
@@ -169,13 +172,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(UpdateAlertRuleResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -39,22 +39,22 @@ const getOrgSchema = z.strictObject({
// request: { // request: {
// params: getOrgSchema // params: getOrgSchema
// }, // },
// responses: { // responses: {
200: { // 200: {
description: "Successful response", // description: "Successful response",
content: { // content: {
"application/json": { // "application/json": {
schema: z.object({ // schema: z.object({
data: z.unknown().nullable(), // data: z.unknown().nullable(),
success: z.boolean(), // success: z.boolean(),
error: z.boolean(), // error: z.boolean(),
message: z.string(), // message: z.string(),
status: z.number() // status: z.number()
}) // })
} // }
} // }
} // }
} // }
// }); // });
export async function getOrgUsage( export async function getOrgUsage(

View File

@@ -25,6 +25,7 @@ import { OpenAPITags, registry } from "@server/openApi";
import { isSubscribed } from "#private/lib/isSubscribed"; import { isSubscribed } from "#private/lib/isSubscribed";
import { build } from "@server/build"; import { build } from "@server/build";
import { tierMatrix } from "@server/lib/billing/tierMatrix"; import { tierMatrix } from "@server/lib/billing/tierMatrix";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
const paramsSchema = z.strictObject({}); const paramsSchema = z.strictObject({});
@@ -65,6 +66,20 @@ export type ListDomainNamespacesResponse = {
pagination: { total: number; limit: number; offset: number }; pagination: { total: number; limit: number; offset: number };
}; };
const ListDomainNamespacesResponseDataSchema = z.object({
domainNamespaces: z.array(
z.object({
domainNamespaceId: z.string(),
domainId: z.string()
})
),
pagination: z.object({
total: z.number(),
limit: z.number(),
offset: z.number()
})
});
registry.registerPath({ registry.registerPath({
method: "get", method: "get",
path: "/domains/namepaces", path: "/domains/namepaces",
@@ -78,13 +93,9 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(
data: z.unknown().nullable(), ListDomainNamespacesResponseDataSchema
success: z.boolean(), )
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -13,6 +13,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db } from "@server/db"; import { db } from "@server/db";
import { eventStreamingDestinations } from "@server/db"; import { eventStreamingDestinations } from "@server/db";
import { logStreamingManager } from "#private/lib/logStreaming"; import { logStreamingManager } from "#private/lib/logStreaming";
@@ -42,6 +43,8 @@ const bodySchema = z.strictObject({
export type CreateEventStreamingDestinationResponse = { export type CreateEventStreamingDestinationResponse = {
destinationId: number; destinationId: number;
}; };
const CreateEventStreamingDestinationResponseDataSchema = z.object({destinationId: z.number()});
registry.registerPath({ registry.registerPath({
method: "put", method: "put",
@@ -63,13 +66,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(CreateEventStreamingDestinationResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -24,6 +24,7 @@ import { OpenAPITags, registry } from "@server/openApi";
import { eq, sql } from "drizzle-orm"; import { eq, sql } from "drizzle-orm";
import { decrypt } from "@server/lib/crypto"; import { decrypt } from "@server/lib/crypto";
import config from "@server/lib/config"; import config from "@server/lib/config";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
const paramsSchema = z.strictObject({ const paramsSchema = z.strictObject({
orgId: z.string().nonempty() orgId: z.string().nonempty()
@@ -67,6 +68,31 @@ export type ListEventStreamingDestinationsResponse = {
}; };
}; };
const ListEventStreamingDestinationsResponseDataSchema = z.object({
destinations: z.array(
z.object({
destinationId: z.number(),
orgId: z.string(),
type: z.string(),
config: z.string(),
enabled: z.boolean(),
lastError: z.string().nullable(),
lastErrorAt: z.number().nullable(),
createdAt: z.number(),
updatedAt: z.number(),
sendConnectionLogs: z.boolean(),
sendRequestLogs: z.boolean(),
sendActionLogs: z.boolean(),
sendAccessLogs: z.boolean()
})
),
pagination: z.object({
total: z.number(),
limit: z.number(),
offset: z.number()
})
});
async function query(orgId: string, limit: number, offset: number) { async function query(orgId: string, limit: number, offset: number) {
const res = await db const res = await db
.select() .select()
@@ -93,13 +119,9 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(
data: z.unknown().nullable(), ListEventStreamingDestinationsResponseDataSchema
success: z.boolean(), )
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -13,6 +13,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db } from "@server/db"; import { db } from "@server/db";
import { eventStreamingDestinations } from "@server/db"; import { eventStreamingDestinations } from "@server/db";
import response from "@server/lib/response"; import response from "@server/lib/response";
@@ -45,6 +46,8 @@ const bodySchema = z.strictObject({
export type UpdateEventStreamingDestinationResponse = { export type UpdateEventStreamingDestinationResponse = {
destinationId: number; destinationId: number;
}; };
const UpdateEventStreamingDestinationResponseDataSchema = z.object({destinationId: z.number()});
registry.registerPath({ registry.registerPath({
method: "post", method: "post",
@@ -66,13 +69,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(UpdateEventStreamingDestinationResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -13,6 +13,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db, targetHealthCheck, newts, sites } from "@server/db"; import { db, targetHealthCheck, newts, sites } from "@server/db";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
@@ -52,6 +53,8 @@ const bodySchema = z.strictObject({
export type CreateHealthCheckResponse = { export type CreateHealthCheckResponse = {
targetHealthCheckId: number; targetHealthCheckId: number;
}; };
const CreateHealthCheckResponseDataSchema = z.object({targetHealthCheckId: z.number()});
registry.registerPath({ registry.registerPath({
method: "put", method: "put",
@@ -73,13 +76,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(CreateHealthCheckResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -13,6 +13,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db, targetHealthCheck, newts, sites } from "@server/db"; import { db, targetHealthCheck, newts, sites } from "@server/db";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
@@ -81,6 +82,8 @@ export type UpdateHealthCheckResponse = {
hcHealthyThreshold: number | null; hcHealthyThreshold: number | null;
hcUnhealthyThreshold: number | null; hcUnhealthyThreshold: number | null;
}; };
const UpdateHealthCheckResponseDataSchema = z.object({targetHealthCheckId: z.number(), name: z.string().nullable(), siteId: z.number().nullable(), hcEnabled: z.boolean(), hcHealth: z.string().nullable(), hcMode: z.string().nullable(), hcHostname: z.string().nullable(), hcPort: z.number().nullable(), hcPath: z.string().nullable(), hcScheme: z.string().nullable(), hcMethod: z.string().nullable(), hcInterval: z.number().nullable(), hcUnhealthyInterval: z.number().nullable(), hcTimeout: z.number().nullable(), hcHeaders: z.string().nullable(), hcFollowRedirects: z.boolean().nullable(), hcStatus: z.number().nullable(), hcTlsServerName: z.string().nullable(), hcHealthyThreshold: z.number().nullable(), hcUnhealthyThreshold: z.number().nullable()});
registry.registerPath({ registry.registerPath({
method: "post", method: "post",
@@ -102,13 +105,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(UpdateHealthCheckResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -13,6 +13,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db, idpOrg } from "@server/db"; import { db, idpOrg } from "@server/db";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
@@ -54,6 +55,8 @@ const bodySchema = z.strictObject({
export type UpdateOrgIdpResponse = { export type UpdateOrgIdpResponse = {
idpId: number; idpId: number;
}; };
const UpdateOrgIdpResponseDataSchema = z.object({idpId: z.number()});
registry.registerPath({ registry.registerPath({
method: "post", method: "post",
@@ -75,13 +78,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(UpdateOrgIdpResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -92,22 +92,22 @@ export type SignSshKeyResponse = {
// } // }
// } // }
// }, // },
// responses: { // responses: {
200: { // 200: {
description: "Successful response", // description: "Successful response",
content: { // content: {
"application/json": { // "application/json": {
schema: z.object({ // schema: z.object({
data: z.unknown().nullable(), // data: z.unknown().nullable(),
success: z.boolean(), // success: z.boolean(),
error: z.boolean(), // error: z.boolean(),
message: z.string(), // message: z.string(),
status: z.number() // status: z.number()
}) // })
} // }
} // }
} // }
} // }
// }); // });
export async function signSshKey( export async function signSshKey(

View File

@@ -2,6 +2,7 @@ import { NextFunction, Request, Response } from "express";
import { db } from "@server/db"; import { db } from "@server/db";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { apiKeyOrg, apiKeys } from "@server/db"; import { apiKeyOrg, apiKeys } from "@server/db";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
@@ -32,6 +33,8 @@ export type CreateOrgApiKeyResponse = {
lastChars: string; lastChars: string;
createdAt: string; createdAt: string;
}; };
const CreateOrgApiKeyResponseDataSchema = z.object({apiKeyId: z.string(), name: z.string(), apiKey: z.string(), lastChars: z.string(), createdAt: z.string()});
registry.registerPath({ registry.registerPath({
method: "put", method: "put",
@@ -53,13 +56,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(CreateOrgApiKeyResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -9,6 +9,7 @@ import { z } from "zod";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
const paramsSchema = z.object({ const paramsSchema = z.object({
apiKeyId: z.string().nonempty() apiKeyId: z.string().nonempty()
@@ -44,6 +45,19 @@ export type ListApiKeyActionsResponse = {
pagination: { total: number; limit: number; offset: number }; pagination: { total: number; limit: number; offset: number };
}; };
const ListApiKeyActionsResponseDataSchema = z.object({
actions: z.array(
z.object({
actionId: z.string()
})
),
pagination: z.object({
total: z.number(),
limit: z.number(),
offset: z.number()
})
});
registry.registerPath({ registry.registerPath({
method: "get", method: "get",
path: "/org/{orgId}/api-key/{apiKeyId}/actions", path: "/org/{orgId}/api-key/{apiKeyId}/actions",
@@ -58,13 +72,9 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(
data: z.unknown().nullable(), ListApiKeyActionsResponseDataSchema
success: z.boolean(), )
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -9,6 +9,7 @@ import { z } from "zod";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { eq, and } from "drizzle-orm"; import { eq, and } from "drizzle-orm";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
const querySchema = z.object({ const querySchema = z.object({
limit: z limit: z
@@ -48,6 +49,23 @@ export type ListOrgApiKeysResponse = {
pagination: { total: number; limit: number; offset: number }; pagination: { total: number; limit: number; offset: number };
}; };
const ListOrgApiKeysResponseDataSchema = z.object({
apiKeys: z.array(
z.object({
apiKeyId: z.string(),
orgId: z.string(),
lastChars: z.string(),
createdAt: z.string(),
name: z.string()
})
),
pagination: z.object({
total: z.number(),
limit: z.number(),
offset: z.number()
})
});
registry.registerPath({ registry.registerPath({
method: "get", method: "get",
path: "/org/{orgId}/api-keys", path: "/org/{orgId}/api-keys",
@@ -62,13 +80,9 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(
data: z.unknown().nullable(), ListOrgApiKeysResponseDataSchema
success: z.boolean(), )
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -51,22 +51,22 @@ export type LookupUserResponse = {
// request: { // request: {
// body: lookupBodySchema // body: lookupBodySchema
// }, // },
// responses: { // responses: {
200: { // 200: {
description: "Successful response", // description: "Successful response",
content: { // content: {
"application/json": { // "application/json": {
schema: z.object({ // schema: z.object({
data: z.unknown().nullable(), // data: z.unknown().nullable(),
success: z.boolean(), // success: z.boolean(),
error: z.boolean(), // error: z.boolean(),
message: z.string(), // message: z.string(),
status: z.number() // status: z.number()
}) // })
} // }
} // }
} // }
} // }
// }); // });
export async function lookupUser( export async function lookupUser(

View File

@@ -6,6 +6,7 @@ import logger from "@server/logger";
import { generateId } from "@server/auth/sessions/app"; import { generateId } from "@server/auth/sessions/app";
import { getNextAvailableClientSubnet } from "@server/lib/ip"; import { getNextAvailableClientSubnet } from "@server/lib/ip";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
@@ -14,6 +15,8 @@ export type PickClientDefaultsResponse = {
olmSecret: string; olmSecret: string;
subnet: string; subnet: string;
}; };
const PickClientDefaultsResponseDataSchema = z.object({olmId: z.string(), olmSecret: z.string(), subnet: z.string()});
const pickClientDefaultsSchema = z.strictObject({ const pickClientDefaultsSchema = z.strictObject({
orgId: z.string() orgId: z.string()
@@ -32,13 +35,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(PickClientDefaultsResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -9,6 +9,7 @@ import { eq, sql } from "drizzle-orm";
import logger from "@server/logger"; import logger from "@server/logger";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
const listDomainsParamsSchema = z.strictObject({ const listDomainsParamsSchema = z.strictObject({
orgId: z.string() orgId: z.string()
@@ -56,6 +57,28 @@ export type ListDomainsResponse = {
pagination: { total: number; limit: number; offset: number }; pagination: { total: number; limit: number; offset: number };
}; };
const ListDomainsResponseDataSchema = z.object({
domains: z.array(
z.object({
domainId: z.string(),
baseDomain: z.string(),
verified: z.boolean(),
type: z.string().nullable(),
failed: z.boolean(),
tries: z.number(),
configManaged: z.boolean(),
certResolver: z.string().nullable(),
preferWildcardCert: z.boolean().nullable(),
errorMessage: z.string().nullable()
})
),
pagination: z.object({
total: z.number(),
limit: z.number(),
offset: z.number()
})
});
registry.registerPath({ registry.registerPath({
method: "get", method: "get",
path: "/org/{orgId}/domains", path: "/org/{orgId}/domains",
@@ -72,13 +95,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(ListDomainsResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -1,5 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db, domains, orgDomains } from "@server/db"; import { db, domains, orgDomains } from "@server/db";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
@@ -24,6 +25,8 @@ export type UpdateDomainResponse = {
certResolver: string | null; certResolver: string | null;
preferWildcardCert: boolean | null; preferWildcardCert: boolean | null;
}; };
const UpdateDomainResponseDataSchema = z.object({domainId: z.string(), certResolver: z.string().nullable(), preferWildcardCert: z.boolean().nullable()});
registry.registerPath({ registry.registerPath({
method: "patch", method: "patch",
@@ -41,13 +44,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(UpdateDomainResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -1,5 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db } from "@server/db"; import { db } from "@server/db";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
@@ -22,6 +23,8 @@ const bodySchema = z.strictObject({
}); });
export type CreateIdpOrgPolicyResponse = {}; export type CreateIdpOrgPolicyResponse = {};
const CreateIdpOrgPolicyResponseDataSchema = z.object({});
registry.registerPath({ registry.registerPath({
method: "put", method: "put",
@@ -43,13 +46,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(CreateIdpOrgPolicyResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -1,5 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db } from "@server/db"; import { db } from "@server/db";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
@@ -33,6 +34,8 @@ export type CreateIdpResponse = {
idpId: number; idpId: number;
redirectUrl: string; redirectUrl: string;
}; };
const CreateIdpResponseDataSchema = z.object({idpId: z.number(), redirectUrl: z.string()});
registry.registerPath({ registry.registerPath({
method: "put", method: "put",
@@ -53,13 +56,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(CreateIdpResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -9,6 +9,7 @@ import { eq, sql } from "drizzle-orm";
import logger from "@server/logger"; import logger from "@server/logger";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
const paramsSchema = z.object({ const paramsSchema = z.object({
idpId: z.coerce.number<number>() idpId: z.coerce.number<number>()
@@ -44,6 +45,21 @@ export type ListIdpOrgPoliciesResponse = {
pagination: { total: number; limit: number; offset: number }; pagination: { total: number; limit: number; offset: number };
}; };
const ListIdpOrgPoliciesResponseDataSchema = z.object({
policies: z.array(
z.object({
idpId: z.number(),
orgId: z.string(),
assignDefaultOrgRoleId: z.number().nullable()
})
),
pagination: z.object({
total: z.number(),
limit: z.number(),
offset: z.number()
})
});
registry.registerPath({ registry.registerPath({
method: "get", method: "get",
path: "/idp/{idpId}/org", path: "/idp/{idpId}/org",
@@ -58,13 +74,9 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(
data: z.unknown().nullable(), ListIdpOrgPoliciesResponseDataSchema
success: z.boolean(), )
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -9,6 +9,7 @@ import { eq, sql } from "drizzle-orm";
import logger from "@server/logger"; import logger from "@server/logger";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
const querySchema = z.strictObject({ const querySchema = z.strictObject({
limit: z limit: z
@@ -54,6 +55,25 @@ export type ListIdpsResponse = {
}; };
}; };
const ListIdpsResponseDataSchema = z.object({
idps: z.array(
z.object({
idpId: z.number(),
name: z.string(),
type: z.string(),
variant: z.string().nullable(),
orgCount: z.number(),
autoProvision: z.boolean().nullable(),
tags: z.string().nullable()
})
),
pagination: z.object({
total: z.number(),
limit: z.number(),
offset: z.number()
})
});
registry.registerPath({ registry.registerPath({
method: "get", method: "get",
path: "/idp", path: "/idp",
@@ -67,13 +87,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(ListIdpsResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -1,5 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db } from "@server/db"; import { db } from "@server/db";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
@@ -21,6 +22,8 @@ const bodySchema = z.strictObject({
}); });
export type UpdateIdpOrgPolicyResponse = {}; export type UpdateIdpOrgPolicyResponse = {};
const UpdateIdpOrgPolicyResponseDataSchema = z.object({});
registry.registerPath({ registry.registerPath({
method: "post", method: "post",
@@ -42,13 +45,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(UpdateIdpOrgPolicyResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -1,5 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db } from "@server/db"; import { db } from "@server/db";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
@@ -38,6 +39,8 @@ const bodySchema = z.strictObject({
export type UpdateIdpResponse = { export type UpdateIdpResponse = {
idpId: number; idpId: number;
}; };
const UpdateIdpResponseDataSchema = z.object({idpId: z.number()});
registry.registerPath({ registry.registerPath({
method: "post", method: "post",
@@ -59,13 +62,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(UpdateIdpResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -43,22 +43,22 @@ export type CreateOlmResponse = {
// }, // },
// params: paramsSchema // params: paramsSchema
// }, // },
// responses: { // responses: {
200: { // 200: {
description: "Successful response", // description: "Successful response",
content: { // content: {
"application/json": { // "application/json": {
schema: z.object({ // schema: z.object({
data: z.unknown().nullable(), // data: z.unknown().nullable(),
success: z.boolean(), // success: z.boolean(),
error: z.boolean(), // error: z.boolean(),
message: z.string(), // message: z.string(),
status: z.number() // status: z.number()
}) // })
} // }
} // }
} // }
} // }
// }); // });
export async function createUserOlm( export async function createUserOlm(

View File

@@ -28,22 +28,22 @@ const paramsSchema = z
// request: { // request: {
// params: paramsSchema // params: paramsSchema
// }, // },
// responses: { // responses: {
200: { // 200: {
description: "Successful response", // description: "Successful response",
content: { // content: {
"application/json": { // "application/json": {
schema: z.object({ // schema: z.object({
data: z.unknown().nullable(), // data: z.unknown().nullable(),
success: z.boolean(), // success: z.boolean(),
error: z.boolean(), // error: z.boolean(),
message: z.string(), // message: z.string(),
status: z.number() // status: z.number()
}) // })
} // }
} // }
} // }
} // }
// }); // });
export async function deleteUserOlm( export async function deleteUserOlm(

View File

@@ -30,22 +30,22 @@ const querySchema = z.object({
// request: { // request: {
// params: paramsSchema // params: paramsSchema
// }, // },
// responses: { // responses: {
200: { // 200: {
description: "Successful response", // description: "Successful response",
content: { // content: {
"application/json": { // "application/json": {
schema: z.object({ // schema: z.object({
data: z.unknown().nullable(), // data: z.unknown().nullable(),
success: z.boolean(), // success: z.boolean(),
error: z.boolean(), // error: z.boolean(),
message: z.string(), // message: z.string(),
status: z.number() // status: z.number()
}) // })
} // }
} // }
} // }
} // }
// }); // });
export async function getUserOlm( export async function getUserOlm(

View File

@@ -41,22 +41,22 @@ const paramsSchema = z
// query: querySchema, // query: querySchema,
// params: paramsSchema // params: paramsSchema
// }, // },
// responses: { // responses: {
200: { // 200: {
description: "Successful response", // description: "Successful response",
content: { // content: {
"application/json": { // "application/json": {
schema: z.object({ // schema: z.object({
data: z.unknown().nullable(), // data: z.unknown().nullable(),
success: z.boolean(), // success: z.boolean(),
error: z.boolean(), // error: z.boolean(),
message: z.string(), // message: z.string(),
status: z.number() // status: z.number()
}) // })
} // }
} // }
} // }
} // }
// }); // });
export type ListUserOlmsResponse = { export type ListUserOlmsResponse = {

View File

@@ -1,5 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db } from "@server/db"; import { db } from "@server/db";
import { Org, orgs } from "@server/db"; import { Org, orgs } from "@server/db";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
@@ -17,6 +18,8 @@ const getOrgSchema = z.strictObject({
export type GetOrgResponse = { export type GetOrgResponse = {
org: Org; org: Org;
}; };
const GetOrgResponseDataSchema = z.object({org: z.object({}).passthrough()});
registry.registerPath({ registry.registerPath({
method: "get", method: "get",
@@ -31,13 +34,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(GetOrgResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -9,6 +9,7 @@ import { sql, inArray, eq } from "drizzle-orm";
import logger from "@server/logger"; import logger from "@server/logger";
import { fromZodError } from "zod-validation-error"; import { fromZodError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
const listOrgsSchema = z.object({ const listOrgsSchema = z.object({
limit: z limit: z
@@ -38,13 +39,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(ListOrgsResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }
@@ -56,6 +51,15 @@ export type ListOrgsResponse = {
pagination: { total: number; limit: number; offset: number }; pagination: { total: number; limit: number; offset: number };
}; };
const ListOrgsResponseDataSchema = z.object({
orgs: z.array(z.object({}).passthrough()),
pagination: z.object({
total: z.number(),
limit: z.number(),
offset: z.number()
})
});
export async function listOrgs( export async function listOrgs(
req: Request, req: Request,
res: Response, res: Response,

View File

@@ -37,22 +37,22 @@ const listOrgsSchema = z.object({
// request: { // request: {
// query: listOrgsSchema // query: listOrgsSchema
// }, // },
// responses: { // responses: {
200: { // 200: {
description: "Successful response", // description: "Successful response",
content: { // content: {
"application/json": { // "application/json": {
schema: z.object({ // schema: z.object({
data: z.unknown().nullable(), // data: z.unknown().nullable(),
success: z.boolean(), // success: z.boolean(),
error: z.boolean(), // error: z.boolean(),
message: z.string(), // message: z.string(),
status: z.number() // status: z.number()
}) // })
} // }
} // }
} // }
} // }
// }); // });
type ResponseOrg = Org & { type ResponseOrg = Org & {

View File

@@ -76,22 +76,22 @@ export type ListUserResourceAliasesResponse = PaginatedResponse<{
// }), // }),
// query: listUserResourceAliasesQuerySchema // query: listUserResourceAliasesQuerySchema
// }, // },
// responses: { // responses: {
200: { // 200: {
description: "Successful response", // description: "Successful response",
content: { // content: {
"application/json": { // "application/json": {
schema: z.object({ // schema: z.object({
data: z.unknown().nullable(), // data: z.unknown().nullable(),
success: z.boolean(), // success: z.boolean(),
error: z.boolean(), // error: z.boolean(),
message: z.string(), // message: z.string(),
status: z.number() // status: z.number()
}) // })
} // }
} // }
} // }
} // }
// }); // });
export async function listUserResourceAliases( export async function listUserResourceAliases(

View File

@@ -15,6 +15,7 @@ import config from "@server/lib/config";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { listExitNodes } from "#dynamic/lib/exitNodes"; import { listExitNodes } from "#dynamic/lib/exitNodes";
export type PickSiteDefaultsResponse = { export type PickSiteDefaultsResponse = {
@@ -29,6 +30,8 @@ export type PickSiteDefaultsResponse = {
newtSecret: string; newtSecret: string;
clientAddress?: string; clientAddress?: string;
}; };
const PickSiteDefaultsResponseDataSchema = z.object({exitNodeId: z.number(), address: z.string(), publicKey: z.string(), name: z.string(), listenPort: z.number(), endpoint: z.string(), subnet: z.string(), newtId: z.string(), newtSecret: z.string(), clientAddress: z.string().optional()});
registry.registerPath({ registry.registerPath({
method: "get", method: "get",
@@ -46,13 +49,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(PickSiteDefaultsResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -1,5 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db } from "@server/db"; import { db } from "@server/db";
import { users, userOrgs } from "@server/db"; import { users, userOrgs } from "@server/db";
import { eq, and } from "drizzle-orm"; import { eq, and } from "drizzle-orm";
@@ -22,6 +23,8 @@ export type UpdateUser2FAResponse = {
userId: string; userId: string;
twoFactorRequested: boolean; twoFactorRequested: boolean;
}; };
const UpdateUser2FAResponseDataSchema = z.object({userId: z.string(), twoFactorRequested: z.boolean()});
registry.registerPath({ registry.registerPath({
method: "post", method: "post",
@@ -43,13 +46,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(UpdateUser2FAResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -1,5 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
@@ -53,6 +54,8 @@ const bodySchema = z
})); }));
export type CreateOrgUserResponse = {}; export type CreateOrgUserResponse = {};
const CreateOrgUserResponseDataSchema = z.object({});
registry.registerPath({ registry.registerPath({
method: "put", method: "put",
@@ -74,13 +77,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(CreateOrgUserResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -1,5 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db } from "@server/db"; import { db } from "@server/db";
import { import {
orgs, orgs,
@@ -67,6 +68,8 @@ export type InviteUserResponse = {
inviteLink: string; inviteLink: string;
expiresAt: number; expiresAt: number;
}; };
const InviteUserResponseDataSchema = z.object({inviteLink: z.string(), expiresAt: z.number()});
registry.registerPath({ registry.registerPath({
method: "post", method: "post",
@@ -88,13 +91,7 @@ registry.registerPath({
description: "Successful response", description: "Successful response",
content: { content: {
"application/json": { "application/json": {
schema: z.object({ schema: createApiResponseSchema(InviteUserResponseDataSchema)
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
} }
} }
} }

View File

@@ -27,22 +27,22 @@ const checkRoundTripMessageParamsSchema = z
// request: { // request: {
// params: checkRoundTripMessageParamsSchema // params: checkRoundTripMessageParamsSchema
// }, // },
// responses: { // responses: {
200: { // 200: {
description: "Successful response", // description: "Successful response",
content: { // content: {
"application/json": { // "application/json": {
schema: z.object({ // schema: z.object({
data: z.unknown().nullable(), // data: z.unknown().nullable(),
success: z.boolean(), // success: z.boolean(),
error: z.boolean(), // error: z.boolean(),
message: z.string(), // message: z.string(),
status: z.number() // status: z.number()
}) // })
} // }
} // }
} // }
} // }
// }); // });
export async function checkRoundTripMessage( export async function checkRoundTripMessage(