mirror of
https://github.com/fosrl/pangolin.git
synced 2026-07-17 11:06:30 +02:00
add site provisioning keys to integration api
This commit is contained in:
@@ -16,6 +16,7 @@ import * as org from "#private/routers/org";
|
||||
import * as logs from "#private/routers/auditLogs";
|
||||
import * as alertEvents from "#private/routers/alertEvents";
|
||||
import * as certificates from "#private/routers/certificates";
|
||||
import * as siteProvisioning from "#private/routers/siteProvisioning";
|
||||
|
||||
import {
|
||||
verifyApiKeyHasAction,
|
||||
@@ -24,6 +25,7 @@ import {
|
||||
verifyApiKeyIdpAccess,
|
||||
verifyApiKeyRoleAccess,
|
||||
verifyApiKeyUserAccess,
|
||||
verifyApiKeySiteProvisioningKeyAccess,
|
||||
verifyLimits
|
||||
} from "@server/middlewares";
|
||||
import * as user from "#private/routers/user";
|
||||
@@ -215,3 +217,45 @@ authenticated.delete(
|
||||
logActionAudit(ActionsEnum.removeUserRole),
|
||||
user.removeUserRole
|
||||
);
|
||||
|
||||
authenticated.put(
|
||||
"/org/:orgId/site-provisioning-key",
|
||||
verifyValidLicense,
|
||||
verifyValidSubscription(tierMatrix.siteProvisioningKeys),
|
||||
verifyApiKeyOrgAccess,
|
||||
verifyLimits,
|
||||
verifyApiKeyHasAction(ActionsEnum.createSiteProvisioningKey),
|
||||
logActionAudit(ActionsEnum.createSiteProvisioningKey),
|
||||
siteProvisioning.createSiteProvisioningKey
|
||||
);
|
||||
|
||||
authenticated.get(
|
||||
"/org/:orgId/site-provisioning-keys",
|
||||
verifyValidLicense,
|
||||
verifyValidSubscription(tierMatrix.siteProvisioningKeys),
|
||||
verifyApiKeyOrgAccess,
|
||||
verifyApiKeyHasAction(ActionsEnum.listSiteProvisioningKeys),
|
||||
siteProvisioning.listSiteProvisioningKeys
|
||||
);
|
||||
|
||||
authenticated.delete(
|
||||
"/org/:orgId/site-provisioning-key/:siteProvisioningKeyId",
|
||||
verifyValidLicense,
|
||||
verifyValidSubscription(tierMatrix.siteProvisioningKeys),
|
||||
verifyApiKeyOrgAccess,
|
||||
verifyApiKeySiteProvisioningKeyAccess,
|
||||
verifyApiKeyHasAction(ActionsEnum.deleteSiteProvisioningKey),
|
||||
logActionAudit(ActionsEnum.deleteSiteProvisioningKey),
|
||||
siteProvisioning.deleteSiteProvisioningKey
|
||||
);
|
||||
|
||||
authenticated.patch(
|
||||
"/org/:orgId/site-provisioning-key/:siteProvisioningKeyId",
|
||||
verifyValidLicense,
|
||||
verifyValidSubscription(tierMatrix.siteProvisioningKeys),
|
||||
verifyApiKeyOrgAccess,
|
||||
verifyApiKeySiteProvisioningKeyAccess,
|
||||
verifyApiKeyHasAction(ActionsEnum.updateSiteProvisioningKey),
|
||||
logActionAudit(ActionsEnum.updateSiteProvisioningKey),
|
||||
siteProvisioning.updateSiteProvisioningKey
|
||||
);
|
||||
|
||||
@@ -26,6 +26,8 @@ import {
|
||||
import logger from "@server/logger";
|
||||
import { hashPassword } from "@server/auth/password";
|
||||
import type { CreateSiteProvisioningKeyResponse } from "@server/routers/siteProvisioning/types";
|
||||
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
|
||||
import { OpenAPITags, registry } from "@server/openApi";
|
||||
|
||||
const paramsSchema = z.object({
|
||||
orgId: z.string().nonempty()
|
||||
@@ -34,10 +36,17 @@ const paramsSchema = z.object({
|
||||
const bodySchema = z
|
||||
.strictObject({
|
||||
name: z.string().min(1).max(255),
|
||||
maxBatchSize: z.union([
|
||||
z.null(),
|
||||
z.coerce.number().int().positive().max(1_000_000)
|
||||
]),
|
||||
maxBatchSize: z
|
||||
.union([
|
||||
z.null(),
|
||||
z.coerce.number().int().positive().max(1_000_000)
|
||||
])
|
||||
.openapi({
|
||||
type: "number",
|
||||
default: null,
|
||||
description:
|
||||
"Maximum number of sites that can be provisioned in a single batch. If null, there is no limit."
|
||||
}),
|
||||
validUntil: z.string().max(255).optional(),
|
||||
approveNewSites: z.boolean().optional().default(true)
|
||||
})
|
||||
@@ -57,6 +66,49 @@ const bodySchema = z
|
||||
|
||||
export type CreateSiteProvisioningKeyBody = z.infer<typeof bodySchema>;
|
||||
|
||||
const CreateSiteProvisioningKeyResponseDataSchema = z.object({
|
||||
siteProvisioningKeyId: z.string(),
|
||||
orgId: z.string(),
|
||||
name: z.string(),
|
||||
siteProvisioningKey: z.string(),
|
||||
lastChars: z.string(),
|
||||
createdAt: z.string(),
|
||||
lastUsed: z.string().nullable(),
|
||||
maxBatchSize: z.number().nullable(),
|
||||
numUsed: z.number(),
|
||||
validUntil: z.string().nullable(),
|
||||
approveNewSites: z.boolean()
|
||||
});
|
||||
|
||||
registry.registerPath({
|
||||
method: "put",
|
||||
path: "/org/{orgId}/site-provisioning-key",
|
||||
description: "Create a new site provisioning key for the organization.",
|
||||
tags: [OpenAPITags.SiteProvisioningKey],
|
||||
request: {
|
||||
params: paramsSchema,
|
||||
body: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: bodySchema
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
responses: {
|
||||
201: {
|
||||
description: "Successful response",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: createApiResponseSchema(
|
||||
CreateSiteProvisioningKeyResponseDataSchema
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export async function createSiteProvisioningKey(
|
||||
req: Request,
|
||||
res: Response,
|
||||
|
||||
@@ -13,23 +13,46 @@
|
||||
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
db,
|
||||
siteProvisioningKeyOrg,
|
||||
siteProvisioningKeys
|
||||
} from "@server/db";
|
||||
import { db, siteProvisioningKeyOrg, siteProvisioningKeys } from "@server/db";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import response from "@server/lib/response";
|
||||
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 paramsSchema = z.object({
|
||||
siteProvisioningKeyId: z.string().nonempty(),
|
||||
orgId: z.string().nonempty()
|
||||
});
|
||||
|
||||
registry.registerPath({
|
||||
method: "delete",
|
||||
path: "/org/{orgId}/site-provisioning-key/{siteProvisioningKeyId}",
|
||||
description: "Delete a site provisioning key.",
|
||||
tags: [OpenAPITags.SiteProvisioningKey],
|
||||
request: {
|
||||
params: paramsSchema
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Successful response",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
data: z.record(z.string(), z.any()).nullable(),
|
||||
success: z.boolean(),
|
||||
error: z.boolean(),
|
||||
message: z.string(),
|
||||
status: z.number()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export async function deleteSiteProvisioningKey(
|
||||
req: Request,
|
||||
res: Response,
|
||||
|
||||
@@ -11,11 +11,7 @@
|
||||
* This file is not licensed under the AGPLv3.
|
||||
*/
|
||||
|
||||
import {
|
||||
db,
|
||||
siteProvisioningKeyOrg,
|
||||
siteProvisioningKeys
|
||||
} from "@server/db";
|
||||
import { db, siteProvisioningKeyOrg, siteProvisioningKeys } from "@server/db";
|
||||
import logger from "@server/logger";
|
||||
import HttpCode from "@server/types/HttpCode";
|
||||
import response from "@server/lib/response";
|
||||
@@ -25,6 +21,8 @@ import { z } from "zod";
|
||||
import { fromError } from "zod-validation-error";
|
||||
import { eq } from "drizzle-orm";
|
||||
import type { ListSiteProvisioningKeysResponse } from "@server/routers/siteProvisioning/types";
|
||||
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
|
||||
import { OpenAPITags, registry } from "@server/openApi";
|
||||
|
||||
const paramsSchema = z.object({
|
||||
orgId: z.string().nonempty()
|
||||
@@ -45,11 +43,55 @@ const querySchema = z.object({
|
||||
.pipe(z.int().nonnegative())
|
||||
});
|
||||
|
||||
const ListSiteProvisioningKeysResponseDataSchema = z.object({
|
||||
siteProvisioningKeys: z.array(
|
||||
z.object({
|
||||
siteProvisioningKeyId: z.string(),
|
||||
orgId: z.string(),
|
||||
lastChars: z.string(),
|
||||
createdAt: z.string(),
|
||||
name: z.string(),
|
||||
lastUsed: z.string().nullable(),
|
||||
maxBatchSize: z.number().nullable(),
|
||||
numUsed: z.number(),
|
||||
validUntil: z.string().nullable(),
|
||||
approveNewSites: z.boolean()
|
||||
})
|
||||
),
|
||||
pagination: z.object({
|
||||
total: z.number(),
|
||||
limit: z.number(),
|
||||
offset: z.number()
|
||||
})
|
||||
});
|
||||
|
||||
registry.registerPath({
|
||||
method: "get",
|
||||
path: "/org/{orgId}/site-provisioning-keys",
|
||||
description: "List all site provisioning keys for an organization.",
|
||||
tags: [OpenAPITags.SiteProvisioningKey],
|
||||
request: {
|
||||
params: paramsSchema,
|
||||
query: querySchema
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Successful response",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: createApiResponseSchema(
|
||||
ListSiteProvisioningKeysResponseDataSchema
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function querySiteProvisioningKeys(orgId: string) {
|
||||
return db
|
||||
.select({
|
||||
siteProvisioningKeyId:
|
||||
siteProvisioningKeys.siteProvisioningKeyId,
|
||||
siteProvisioningKeyId: siteProvisioningKeys.siteProvisioningKeyId,
|
||||
orgId: siteProvisioningKeyOrg.orgId,
|
||||
lastChars: siteProvisioningKeys.lastChars,
|
||||
createdAt: siteProvisioningKeys.createdAt,
|
||||
|
||||
@@ -13,11 +13,7 @@
|
||||
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
db,
|
||||
siteProvisioningKeyOrg,
|
||||
siteProvisioningKeys
|
||||
} from "@server/db";
|
||||
import { db, siteProvisioningKeyOrg, siteProvisioningKeys } from "@server/db";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import response from "@server/lib/response";
|
||||
import HttpCode from "@server/types/HttpCode";
|
||||
@@ -25,6 +21,8 @@ import createHttpError from "http-errors";
|
||||
import logger from "@server/logger";
|
||||
import { fromError } from "zod-validation-error";
|
||||
import type { UpdateSiteProvisioningKeyResponse } from "@server/routers/siteProvisioning/types";
|
||||
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
|
||||
import { OpenAPITags, registry } from "@server/openApi";
|
||||
|
||||
const paramsSchema = z.object({
|
||||
siteProvisioningKeyId: z.string().nonempty(),
|
||||
@@ -38,7 +36,13 @@ const bodySchema = z
|
||||
z.null(),
|
||||
z.coerce.number().int().positive().max(1_000_000)
|
||||
])
|
||||
.optional(),
|
||||
.optional()
|
||||
.openapi({
|
||||
type: "number",
|
||||
default: null,
|
||||
description:
|
||||
"Maximum number of sites that can be provisioned in a single batch. If null, there is no limit."
|
||||
}),
|
||||
validUntil: z.string().max(255).optional(),
|
||||
approveNewSites: z.boolean().optional()
|
||||
})
|
||||
@@ -50,7 +54,8 @@ const bodySchema = z
|
||||
) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: "Provide maxBatchSize and/or validUntil and/or approveNewSites",
|
||||
message:
|
||||
"Provide maxBatchSize and/or validUntil and/or approveNewSites",
|
||||
path: ["maxBatchSize"]
|
||||
});
|
||||
}
|
||||
@@ -69,6 +74,48 @@ const bodySchema = z
|
||||
|
||||
export type UpdateSiteProvisioningKeyBody = z.infer<typeof bodySchema>;
|
||||
|
||||
const UpdateSiteProvisioningKeyResponseDataSchema = z.object({
|
||||
siteProvisioningKeyId: z.string(),
|
||||
orgId: z.string(),
|
||||
name: z.string(),
|
||||
lastChars: z.string(),
|
||||
createdAt: z.string(),
|
||||
lastUsed: z.string().nullable(),
|
||||
maxBatchSize: z.number().nullable(),
|
||||
numUsed: z.number(),
|
||||
validUntil: z.string().nullable(),
|
||||
approveNewSites: z.boolean()
|
||||
});
|
||||
|
||||
registry.registerPath({
|
||||
method: "patch",
|
||||
path: "/org/{orgId}/site-provisioning-key/{siteProvisioningKeyId}",
|
||||
description: "Update a site provisioning key.",
|
||||
tags: [OpenAPITags.SiteProvisioningKey],
|
||||
request: {
|
||||
params: paramsSchema,
|
||||
body: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: bodySchema
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Successful response",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: createApiResponseSchema(
|
||||
UpdateSiteProvisioningKeyResponseDataSchema
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export async function updateSiteProvisioningKey(
|
||||
req: Request,
|
||||
res: Response,
|
||||
|
||||
Reference in New Issue
Block a user