diff --git a/server/routers/client/listClients.ts b/server/routers/client/listClients.ts index c22d31b4..53a66150 100644 --- a/server/routers/client/listClients.ts +++ b/server/routers/client/listClients.ts @@ -99,25 +99,54 @@ const listClientsSchema = z.object({ .positive() .optional() .catch(20) - .default(20), + .default(20) + .openapi({ + type: "integer", + default: 20, + description: "Number of items per page" + }), page: z.coerce .number() // for prettier formatting .int() .min(0) .optional() .catch(1) - .default(1), + .default(1) + .openapi({ + type: "integer", + default: 1, + description: "Page number to retrieve" + }), query: z.string().optional(), sort_by: z .enum(["megabytesIn", "megabytesOut"]) .optional() - .catch(undefined), - order: z.enum(["asc", "desc"]).optional().default("asc").catch("asc"), + .catch(undefined) + .openapi({ + type: "string", + enum: ["megabytesIn", "megabytesOut"], + description: "Field to sort by" + }), + order: z + .enum(["asc", "desc"]) + .optional() + .default("asc") + .catch("asc") + .openapi({ + type: "string", + enum: ["asc", "desc"], + default: "asc", + description: "Sort order" + }), online: z .enum(["true", "false"]) .transform((v) => v === "true") .optional() - .catch(undefined), + .catch(undefined) + .openapi({ + type: "boolean", + description: "Filter by online status" + }), status: z.preprocess( (val: string | undefined) => { if (val) { @@ -130,6 +159,16 @@ const listClientsSchema = z.object({ .optional() .default(["active"]) .catch(["active"]) + .openapi({ + type: "array", + items: { + type: "string", + enum: ["active", "blocked", "archived"] + }, + default: ["active"], + description: + "Filter by client status. Can be a comma-separated list of values. Defaults to 'active'." + }) ) }); diff --git a/server/routers/client/listUserDevices.ts b/server/routers/client/listUserDevices.ts index 9db676d4..54fffe43 100644 --- a/server/routers/client/listUserDevices.ts +++ b/server/routers/client/listUserDevices.ts @@ -100,25 +100,54 @@ const listUserDevicesSchema = z.object({ .positive() .optional() .catch(20) - .default(20), + .default(20) + .openapi({ + type: "integer", + default: 20, + description: "Number of items per page" + }), page: z.coerce .number() // for prettier formatting .int() .min(0) .optional() .catch(1) - .default(1), + .default(1) + .openapi({ + type: "integer", + default: 1, + description: "Page number to retrieve" + }), query: z.string().optional(), sort_by: z .enum(["megabytesIn", "megabytesOut"]) .optional() - .catch(undefined), - order: z.enum(["asc", "desc"]).optional().default("asc").catch("asc"), + .catch(undefined) + .openapi({ + type: "string", + enum: ["megabytesIn", "megabytesOut"], + description: "Field to sort by" + }), + order: z + .enum(["asc", "desc"]) + .optional() + .default("asc") + .catch("asc") + .openapi({ + type: "string", + enum: ["asc", "desc"], + default: "asc", + description: "Sort order" + }), online: z .enum(["true", "false"]) .transform((v) => v === "true") .optional() - .catch(undefined), + .catch(undefined) + .openapi({ + type: "boolean", + description: "Filter by online status" + }), agent: z .enum([ "windows", @@ -131,7 +160,22 @@ const listUserDevicesSchema = z.object({ "unknown" ]) .optional() - .catch(undefined), + .catch(undefined) + .openapi({ + type: "string", + enum: [ + "windows", + "android", + "cli", + "olm", + "macos", + "ios", + "ipados", + "unknown" + ], + description: + "Filter by agent type. Use 'unknown' to filter clients with no agent detected." + }), status: z.preprocess( (val: string | undefined) => { if (val) { @@ -146,6 +190,16 @@ const listUserDevicesSchema = z.object({ .optional() .default(["active", "pending"]) .catch(["active", "pending"]) + .openapi({ + type: "array", + items: { + type: "string", + enum: ["active", "pending", "denied", "blocked", "archived"] + }, + default: ["active", "pending"], + description: + "Filter by device status. Can include multiple values separated by commas. 'active' means not archived, not blocked, and if approval is enabled, approved. 'pending' and 'denied' are only applicable if approval is enabled." + }) ) }); diff --git a/server/routers/resource/listResources.ts b/server/routers/resource/listResources.ts index 1fa8b316..a26a5df5 100644 --- a/server/routers/resource/listResources.ts +++ b/server/routers/resource/listResources.ts @@ -44,28 +44,54 @@ const listResourcesSchema = z.object({ .positive() .optional() .catch(20) - .default(20), + .default(20) + .openapi({ + type: "integer", + default: 20, + description: "Number of items per page" + }), page: z.coerce .number() // for prettier formatting .int() .min(0) .optional() .catch(1) - .default(1), + .default(1) + .openapi({ + type: "integer", + default: 1, + description: "Page number to retrieve" + }), query: z.string().optional(), enabled: z .enum(["true", "false"]) .transform((v) => v === "true") .optional() - .catch(undefined), + .catch(undefined) + .openapi({ + type: "boolean", + description: "Filter resources based on enabled status" + }), authState: z .enum(["protected", "not_protected", "none"]) .optional() - .catch(undefined), + .catch(undefined) + .openapi({ + type: "string", + enum: ["protected", "not_protected", "none"], + description: + "Filter resources based on authentication state. `protected` means the resource has at least one auth mechanism (password, pincode, header auth, SSO, or email whitelist). `not_protected` means the resource has no auth mechanisms. `none` means the resource is not protected by HTTP (i.e. it has no auth mechanisms and http is false)." + }), healthStatus: z .enum(["no_targets", "healthy", "degraded", "offline", "unknown"]) .optional() .catch(undefined) + .openapi({ + type: "string", + enum: ["no_targets", "healthy", "degraded", "offline", "unknown"], + description: + "Filter resources based on health status of their targets. `healthy` means all targets are healthy. `degraded` means at least one target is unhealthy, but not all are unhealthy. `offline` means all targets are unhealthy. `unknown` means all targets have unknown health status. `no_targets` means the resource has no targets." + }) }); // grouped by resource with targets[]) diff --git a/server/routers/site/listSites.ts b/server/routers/site/listSites.ts index 0bd96cac..e4881b1a 100644 --- a/server/routers/site/listSites.ts +++ b/server/routers/site/listSites.ts @@ -88,25 +88,54 @@ const listSitesSchema = z.object({ .positive() .optional() .catch(20) - .default(20), + .default(20) + .openapi({ + type: "integer", + default: 20, + description: "Number of items per page" + }), page: z.coerce .number() // for prettier formatting .int() .min(0) .optional() .catch(1) - .default(1), + .default(1) + .openapi({ + type: "integer", + default: 1, + description: "Page number to retrieve" + }), query: z.string().optional(), sort_by: z .enum(["megabytesIn", "megabytesOut"]) .optional() - .catch(undefined), - order: z.enum(["asc", "desc"]).optional().default("asc").catch("asc"), + .catch(undefined) + .openapi({ + type: "string", + enum: ["megabytesIn", "megabytesOut"], + description: "Field to sort by" + }), + order: z + .enum(["asc", "desc"]) + .optional() + .default("asc") + .catch("asc") + .openapi({ + type: "string", + enum: ["asc", "desc"], + default: "asc", + description: "Sort order" + }), online: z .enum(["true", "false"]) .transform((v) => v === "true") .optional() .catch(undefined) + .openapi({ + type: "boolean", + description: "Filter by online status" + }) }); function querySitesBase() { diff --git a/server/routers/siteResource/listAllSiteResourcesByOrg.ts b/server/routers/siteResource/listAllSiteResourcesByOrg.ts index 944955a5..ead1fc8a 100644 --- a/server/routers/siteResource/listAllSiteResourcesByOrg.ts +++ b/server/routers/siteResource/listAllSiteResourcesByOrg.ts @@ -21,16 +21,34 @@ const listAllSiteResourcesByOrgQuerySchema = z.object({ .positive() .optional() .catch(20) - .default(20), + .default(20) + .openapi({ + type: "integer", + default: 20, + description: "Number of items per page" + }), page: z.coerce .number() // for prettier formatting .int() .min(0) .optional() .catch(1) - .default(1), + .default(1) + .openapi({ + type: "integer", + default: 1, + description: "Page number to retrieve" + }), query: z.string().optional(), - mode: z.enum(["host", "cidr"]).optional().catch(undefined) + mode: z + .enum(["host", "cidr"]) + .optional() + .catch(undefined) + .openapi({ + type: "string", + enum: ["host", "cidr"], + description: "Filter site resources by mode" + }) }); export type ListAllSiteResourcesByOrgResponse = PaginatedResponse<{