Add labels to the integration api

This commit is contained in:
Owen
2026-10-12 16:21:12 -04:00
parent 9afcd68d68
commit e461b231d5
8 changed files with 246 additions and 1 deletions
+51
View File
@@ -16,6 +16,7 @@ import * as siteResource from "./siteResource";
import * as aiProvider from "./aiProvider";
import * as aiBudget from "./aiBudget";
import * as virtualApiKey from "./virtualApiKey";
import * as labels from "./labels";
import {
verifyApiKey,
verifyApiKeyOrgAccess,
@@ -1833,3 +1834,53 @@ authenticated.get(
verifyApiKeyHasAction(ActionsEnum.listAiBudgets),
aiBudget.listAiBudgetsForVirtualApiKey
);
authenticated.get(
"/org/:orgId/labels",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.listOrgLabels),
labels.listOrgLabels
);
authenticated.post(
"/org/:orgId/labels",
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createOrgLabel),
logActionAudit(ActionsEnum.createOrgLabel),
labels.createOrgLabel
);
authenticated.patch(
"/org/:orgId/label/:labelId",
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.updateOrgLabel),
logActionAudit(ActionsEnum.updateOrgLabel),
labels.updateOrgLabel
);
authenticated.delete(
"/org/:orgId/label/:labelId",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.deleteOrgLabel),
logActionAudit(ActionsEnum.deleteOrgLabel),
labels.deleteOrgLabel
);
authenticated.put(
"/org/:orgId/label/:labelId/attach",
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.attachLabelToItem),
logActionAudit(ActionsEnum.attachLabelToItem),
labels.attachLabelToItem
);
authenticated.put(
"/org/:orgId/label/:labelId/detach",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.detachLabelFromItem),
logActionAudit(ActionsEnum.detachLabelFromItem),
labels.detachLabelFromItem
);
@@ -12,6 +12,7 @@ import {
} from "@server/db";
import response from "@server/lib/response";
import logger from "@server/logger";
import { OpenAPITags, registry } from "@server/openApi";
import HttpCode from "@server/types/HttpCode";
import { and, eq, isNull } from "drizzle-orm";
import { NextFunction, Request, Response } from "express";
@@ -31,6 +32,40 @@ const attachLabelBodySchema = z.strictObject({
clientId: z.number().int().optional()
});
registry.registerPath({
method: "put",
path: "/org/{orgId}/label/{labelId}/attach",
description:
"Attach a label to a site, public resource, private resource or client.",
tags: [OpenAPITags.Label],
request: {
params: paramsSchema,
body: {
content: {
"application/json": {
schema: attachLabelBodySchema
}
}
}
},
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 attachLabelToItem(
req: Request,
res: Response,
+34
View File
@@ -9,6 +9,7 @@ import {
import response from "@server/lib/response";
import logger from "@server/logger";
import type { CreateOrEditLabelResponse } from "@server/routers/labels/types";
import { OpenAPITags, registry } from "@server/openApi";
import HttpCode from "@server/types/HttpCode";
import { and, eq, sql } from "drizzle-orm";
import { NextFunction, Request, Response } from "express";
@@ -30,6 +31,39 @@ const bodySchema = z.strictObject({
resourceId: z.number().int().optional()
});
registry.registerPath({
method: "post",
path: "/org/{orgId}/labels",
description: "Create a label in an organization.",
tags: [OpenAPITags.Label],
request: {
params: paramsSchema,
body: {
content: {
"application/json": {
schema: bodySchema
}
}
}
},
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 createOrgLabel(
req: Request,
res: Response,
+27
View File
@@ -1,6 +1,7 @@
import { db, labels } from "@server/db";
import response from "@server/lib/response";
import logger from "@server/logger";
import { OpenAPITags, registry } from "@server/openApi";
import HttpCode from "@server/types/HttpCode";
import { and, eq } from "drizzle-orm";
import { NextFunction, Request, Response } from "express";
@@ -13,6 +14,32 @@ const paramsSchema = z.strictObject({
labelId: z.string().transform(Number).pipe(z.int().positive())
});
registry.registerPath({
method: "delete",
path: "/org/{orgId}/label/{labelId}",
description: "Delete a label.",
tags: [OpenAPITags.Label],
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 deleteOrgLabel(
req: Request,
res: Response,
@@ -12,6 +12,7 @@ import {
} from "@server/db";
import response from "@server/lib/response";
import logger from "@server/logger";
import { OpenAPITags, registry } from "@server/openApi";
import HttpCode from "@server/types/HttpCode";
import { and, eq, isNull } from "drizzle-orm";
import { NextFunction, Request, Response } from "express";
@@ -31,6 +32,40 @@ const detachLabelBodySchema = z.strictObject({
clientId: z.number().int().optional()
});
registry.registerPath({
method: "put",
path: "/org/{orgId}/label/{labelId}/detach",
description:
"Detach a label from a site, public resource, private resource or client.",
tags: [OpenAPITags.Label],
request: {
params: paramsSchema,
body: {
content: {
"application/json": {
schema: detachLabelBodySchema
}
}
}
},
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 detachLabelFromItem(
req: Request,
res: Response,
+28
View File
@@ -2,6 +2,7 @@ import { db, labels } from "@server/db";
import response from "@server/lib/response";
import logger from "@server/logger";
import type { ListOrgLabelsResponse } from "@server/routers/labels/types";
import { OpenAPITags, registry } from "@server/openApi";
import HttpCode from "@server/types/HttpCode";
import { and, asc, eq, like, sql } from "drizzle-orm";
import { NextFunction, Request, Response } from "express";
@@ -51,6 +52,33 @@ function queryLabelsBase() {
.from(labels);
}
registry.registerPath({
method: "get",
path: "/org/{orgId}/labels",
description: "List labels in an organization.",
tags: [OpenAPITags.Label],
request: {
params: paramsSchema,
query: listLabelsSchema
},
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 listOrgLabels(
req: Request,
res: Response,
+34
View File
@@ -2,6 +2,7 @@ import { db, labels } from "@server/db";
import response from "@server/lib/response";
import logger from "@server/logger";
import type { CreateOrEditLabelResponse } from "@server/routers/labels/types";
import { OpenAPITags, registry } from "@server/openApi";
import HttpCode from "@server/types/HttpCode";
import { and, eq, ne, sql } from "drizzle-orm";
import { NextFunction, Request, Response } from "express";
@@ -22,6 +23,39 @@ const updateLabelBodySchema = z.strictObject({
.nonempty()
});
registry.registerPath({
method: "patch",
path: "/org/{orgId}/label/{labelId}",
description: "Update a label.",
tags: [OpenAPITags.Label],
request: {
params: paramsSchema,
body: {
content: {
"application/json": {
schema: updateLabelBodySchema
}
}
}
},
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 updateOrgLabel(
req: Request,
res: Response,