Compare commits

..

1 Commits

Author SHA1 Message Date
Owen
a2c96ea2f7 Add aliaes for public/private resources 2026-07-09 20:23:19 -04:00
61 changed files with 1817 additions and 223 deletions

View File

@@ -1,6 +1,6 @@
import { z } from "zod";
import { db, logsDb, statusHistory } from "@server/db";
import { and, eq, gte, lt, asc, desc, inArray } from "drizzle-orm";
import { and, eq, gte, lt, asc, desc } from "drizzle-orm";
import { regionalCache as cache } from "#dynamic/lib/cache";
const STATUS_HISTORY_CACHE_TTL = 60; // seconds
@@ -273,81 +273,3 @@ export function computeBuckets(
return { buckets, totalDowntime };
}
export interface BatchedStatusHistoryResponse {
entityType: string;
entityIds: number[];
days: StatusHistoryDayBucket[];
overallUptimePercent: number;
totalDowntimeSeconds: number;
}
export async function getBatchedStatusHistory(
entityType: string,
entityIds: number[],
days: number
): Promise<BatchedStatusHistoryResponse> {
// const cacheKey = statusHistoryCacheKey(entityType, entityId, days);
// const cached = await cache.get<StatusHistoryResponse>(cacheKey);
// if (cached !== undefined) {
// return cached;
// }
// Anchor to UTC midnight so the query window aligns with stable calendar days
const utcToday = new Date();
utcToday.setUTCHours(0, 0, 0, 0);
const todayMidnightSec = Math.floor(utcToday.getTime() / 1000);
const startSec = todayMidnightSec - days * 86400;
const events = await logsDb
.select()
.from(statusHistory)
.where(
and(
eq(statusHistory.entityType, entityType),
inArray(statusHistory.entityId, entityIds),
gte(statusHistory.timestamp, startSec)
)
)
.orderBy(asc(statusHistory.timestamp));
// Fetch the last known state before the window so that entities that
// haven't changed status recently still show the correct status rather
// than appearing as "no_data".
const [lastKnownEvent] = await logsDb
.select()
.from(statusHistory)
.where(
and(
eq(statusHistory.entityType, entityType),
inArray(statusHistory.entityId, entityIds),
lt(statusHistory.timestamp, startSec)
)
)
.orderBy(desc(statusHistory.timestamp))
.limit(1);
const priorStatus = lastKnownEvent?.status ?? null;
const { buckets, totalDowntime } = computeBuckets(
events,
days,
priorStatus
);
const totalWindow = days * 86400;
const overallUptime =
totalWindow > 0
? Math.max(0, ((totalWindow - totalDowntime) / totalWindow) * 100)
: 100;
const result: BatchedStatusHistoryResponse = {
entityType,
entityIds,
days: buckets,
overallUptimePercent: Math.round(overallUptime * 100) / 100,
totalDowntimeSeconds: totalDowntime
};
// await cache.set(cacheKey, result, STATUS_HISTORY_CACHE_TTL);
return result;
}

View File

@@ -73,6 +73,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/access-token",
description: "Generate a new access token for a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.AccessToken],
request: {
params: generateAccssTokenParamsSchema,
body: {
content: {
"application/json": {
schema: generateAccessTokenBodySchema
}
}
}
},
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 generateAccessToken(
req: Request,
res: Response,

View File

@@ -176,6 +176,35 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/public-resource/{resourceId}/access-tokens",
description: "List all access tokens for a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.AccessToken],
request: {
params: z.object({
resourceId: z.number()
}),
query: listAccessTokensSchema
},
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 listAccessTokens(
req: Request,
res: Response,

View File

@@ -162,7 +162,7 @@ authenticated.get(
// Site Resource endpoints
authenticated.put(
"/org/:orgId/site-resource",
["/org/:orgId/site-resource", "/org/:orgId/private-resource"],
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createSiteResource),
@@ -171,7 +171,10 @@ authenticated.put(
);
authenticated.get(
"/org/:orgId/site/:siteId/resources",
[
"/org/:orgId/site/:siteId/resources",
"/org/:orgId/site/:siteId/private-resources"
],
verifyApiKeyOrgAccess,
verifyApiKeySiteAccess,
verifyApiKeyHasAction(ActionsEnum.listSiteResources),
@@ -179,21 +182,21 @@ authenticated.get(
);
authenticated.get(
"/org/:orgId/site-resources",
["/org/:orgId/site-resources", "/org/:orgId/private-resources"],
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.listSiteResources),
siteResource.listAllSiteResourcesByOrg
);
authenticated.get(
"/site-resource/:siteResourceId",
["/site-resource/:siteResourceId", "/private-resource/:siteResourceId"],
verifyApiKeySiteResourceAccess,
verifyApiKeyHasAction(ActionsEnum.getSiteResource),
siteResource.getSiteResource
);
authenticated.post(
"/site-resource/:siteResourceId",
["/site-resource/:siteResourceId", "/private-resource/:siteResourceId"],
verifyApiKeySiteResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.updateSiteResource),
@@ -202,7 +205,7 @@ authenticated.post(
);
authenticated.delete(
"/site-resource/:siteResourceId",
["/site-resource/:siteResourceId", "/private-resource/:siteResourceId"],
verifyApiKeySiteResourceAccess,
verifyApiKeyHasAction(ActionsEnum.deleteSiteResource),
logActionAudit(ActionsEnum.deleteSiteResource),
@@ -210,28 +213,40 @@ authenticated.delete(
);
authenticated.get(
"/site-resource/:siteResourceId/roles",
[
"/site-resource/:siteResourceId/roles",
"/private-resource/:siteResourceId/roles"
],
verifyApiKeySiteResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listResourceRoles),
siteResource.listSiteResourceRoles
);
authenticated.get(
"/site-resource/:siteResourceId/users",
[
"/site-resource/:siteResourceId/users",
"/private-resource/:siteResourceId/users"
],
verifyApiKeySiteResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listResourceUsers),
siteResource.listSiteResourceUsers
);
authenticated.get(
"/site-resource/:siteResourceId/clients",
[
"/site-resource/:siteResourceId/clients",
"/private-resource/:siteResourceId/clients"
],
verifyApiKeySiteResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listResourceUsers),
siteResource.listSiteResourceClients
);
authenticated.post(
"/site-resource/:siteResourceId/roles",
[
"/site-resource/:siteResourceId/roles",
"/private-resource/:siteResourceId/roles"
],
verifyApiKeySiteResourceAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -241,7 +256,10 @@ authenticated.post(
);
authenticated.post(
"/site-resource/:siteResourceId/users",
[
"/site-resource/:siteResourceId/users",
"/private-resource/:siteResourceId/users"
],
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceUsers,
verifyLimits,
@@ -251,7 +269,10 @@ authenticated.post(
);
authenticated.post(
"/site-resource/:siteResourceId/roles/add",
[
"/site-resource/:siteResourceId/roles/add",
"/private-resource/:siteResourceId/roles/add"
],
verifyApiKeySiteResourceAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -261,7 +282,10 @@ authenticated.post(
);
authenticated.post(
"/site-resource/:siteResourceId/roles/remove",
[
"/site-resource/:siteResourceId/roles/remove",
"/private-resource/:siteResourceId/roles/remove"
],
verifyApiKeySiteResourceAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -271,7 +295,10 @@ authenticated.post(
);
authenticated.post(
"/site-resource/:siteResourceId/users/add",
[
"/site-resource/:siteResourceId/users/add",
"/private-resource/:siteResourceId/users/add"
],
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceUsers,
verifyLimits,
@@ -281,7 +308,10 @@ authenticated.post(
);
authenticated.post(
"/site-resource/:siteResourceId/users/remove",
[
"/site-resource/:siteResourceId/users/remove",
"/private-resource/:siteResourceId/users/remove"
],
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceUsers,
verifyLimits,
@@ -291,7 +321,10 @@ authenticated.post(
);
authenticated.post(
"/site-resource/:siteResourceId/clients",
[
"/site-resource/:siteResourceId/clients",
"/private-resource/:siteResourceId/clients"
],
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceClients,
verifyLimits,
@@ -301,7 +334,10 @@ authenticated.post(
);
authenticated.post(
"/site-resource/:siteResourceId/clients/add",
[
"/site-resource/:siteResourceId/clients/add",
"/private-resource/:siteResourceId/clients/add"
],
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceClients,
verifyLimits,
@@ -311,7 +347,10 @@ authenticated.post(
);
authenticated.post(
"/site-resource/:siteResourceId/clients/remove",
[
"/site-resource/:siteResourceId/clients/remove",
"/private-resource/:siteResourceId/clients/remove"
],
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceClients,
verifyLimits,
@@ -321,7 +360,7 @@ authenticated.post(
);
authenticated.post(
"/client/:clientId/site-resources",
["/client/:clientId/site-resources", "/client/:clientId/private-resources"],
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourceUsers),
logActionAudit(ActionsEnum.setResourceUsers),
@@ -329,7 +368,7 @@ authenticated.post(
);
authenticated.put(
"/org/:orgId/resource",
["/org/:orgId/resource", "/org/:orgId/public-resource"],
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createResource),
@@ -338,7 +377,10 @@ authenticated.put(
);
authenticated.put(
"/org/:orgId/site/:siteId/resource",
[
"/org/:orgId/site/:siteId/resource",
"/org/:orgId/site/:siteId/public-resource"
],
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createResource),
@@ -347,14 +389,14 @@ authenticated.put(
);
authenticated.get(
"/site/:siteId/resources",
["/site/:siteId/resources", "/site/:siteId/public-resources"],
verifyApiKeySiteAccess,
verifyApiKeyHasAction(ActionsEnum.listResources),
resource.listResources
);
authenticated.get(
"/org/:orgId/resources",
["/org/:orgId/resources", "/org/:orgId/public-resources"],
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.listResources),
resource.listResources
@@ -442,42 +484,45 @@ authenticated.delete(
);
authenticated.get(
"/resource/:resourceId/roles",
["/resource/:resourceId/roles", "/public-resource/:resourceId/roles"],
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listResourceRoles),
resource.listResourceRoles
);
authenticated.get(
"/resource/:resourceId/users",
["/resource/:resourceId/users", "/public-resource/:resourceId/users"],
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listResourceUsers),
resource.listResourceUsers
);
authenticated.get(
"/resource/:resourceId",
["/resource/:resourceId", "/public-resource/:resourceId"],
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.getResource),
resource.getResource
);
authenticated.get(
"/resource-policy/:resourcePolicyId",
[
"/resource-policy/:resourcePolicyId",
"/public-resource-policy/:resourcePolicyId"
],
verifyApiKeyResourcePolicyAccess,
verifyApiKeyHasAction(ActionsEnum.getResourcePolicy),
policy.getResourcePolicy
);
authenticated.get(
"/resource/:resourceId/policies",
["/resource/:resourceId/policies", "/public-resource/:resourceId/policies"],
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.getResourcePolicy),
resource.getResourcePolicies
);
authenticated.post(
"/resource/:resourceId",
["/resource/:resourceId", "/public-resource/:resourceId"],
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.updateResource),
@@ -486,14 +531,17 @@ authenticated.post(
);
authenticated.put(
"/resource-policy/:resourcePolicyId",
[
"/resource-policy/:resourcePolicyId",
"/public-resource-policy/:resourcePolicyId"
],
verifyApiKeyResourcePolicyAccess,
verifyApiKeyHasAction(ActionsEnum.updateResourcePolicy),
policy.updateResourcePolicy
);
authenticated.delete(
"/resource/:resourceId",
["/resource/:resourceId", "/public-resource/:resourceId"],
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.deleteResource),
logActionAudit(ActionsEnum.deleteResource),
@@ -501,7 +549,7 @@ authenticated.delete(
);
authenticated.put(
"/resource/:resourceId/target",
["/resource/:resourceId/target", "/public-resource/:resourceId/target"],
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createTarget),
@@ -510,14 +558,14 @@ authenticated.put(
);
authenticated.get(
"/resource/:resourceId/targets",
["/resource/:resourceId/targets", "/public-resource/:resourceId/targets"],
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listTargets),
target.listTargets
);
authenticated.put(
"/resource/:resourceId/rule",
["/resource/:resourceId/rule", "/public-resource/:resourceId/rule"],
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createResourceRule),
@@ -526,14 +574,17 @@ authenticated.put(
);
authenticated.get(
"/resource/:resourceId/rules",
["/resource/:resourceId/rules", "/public-resource/:resourceId/rules"],
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listResourceRules),
resource.listResourceRules
);
authenticated.post(
"/resource/:resourceId/rule/:ruleId",
[
"/resource/:resourceId/rule/:ruleId",
"/public-resource/:resourceId/rule/:ruleId"
],
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.updateResourceRule),
@@ -542,7 +593,10 @@ authenticated.post(
);
authenticated.delete(
"/resource/:resourceId/rule/:ruleId",
[
"/resource/:resourceId/rule/:ruleId",
"/public-resource/:resourceId/rule/:ruleId"
],
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.deleteResourceRule),
logActionAudit(ActionsEnum.deleteResourceRule),
@@ -624,7 +678,7 @@ authenticated.post(
);
authenticated.post(
"/resource/:resourceId/roles",
["/resource/:resourceId/roles", "/public-resource/:resourceId/roles"],
verifyApiKeyResourceAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -634,7 +688,7 @@ authenticated.post(
);
authenticated.post(
"/resource/:resourceId/users",
["/resource/:resourceId/users", "/public-resource/:resourceId/users"],
verifyApiKeyResourceAccess,
verifyApiKeySetResourceUsers,
verifyLimits,
@@ -644,7 +698,10 @@ authenticated.post(
);
authenticated.put(
"/resource-policy/:resourcePolicyId/access-control",
[
"/resource-policy/:resourcePolicyId/access-control",
"/public-resource-policy/:resourcePolicyId/access-control"
],
verifyApiKeyResourcePolicyAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -656,7 +713,10 @@ authenticated.put(
);
authenticated.put(
"/resource-policy/:resourcePolicyId/password",
[
"/resource-policy/:resourcePolicyId/password",
"/public-resource-policy/:resourcePolicyId/password"
],
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyPassword),
@@ -665,7 +725,10 @@ authenticated.put(
);
authenticated.put(
"/resource-policy/:resourcePolicyId/pincode",
[
"/resource-policy/:resourcePolicyId/pincode",
"/public-resource-policy/:resourcePolicyId/pincode"
],
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyPincode),
@@ -674,7 +737,10 @@ authenticated.put(
);
authenticated.put(
"/resource-policy/:resourcePolicyId/header-auth",
[
"/resource-policy/:resourcePolicyId/header-auth",
"/public-resource-policy/:resourcePolicyId/header-auth"
],
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyHeaderAuth),
@@ -683,7 +749,10 @@ authenticated.put(
);
authenticated.put(
"/resource-policy/:resourcePolicyId/whitelist",
[
"/resource-policy/:resourcePolicyId/whitelist",
"/public-resource-policy/:resourcePolicyId/whitelist"
],
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyWhitelist),
@@ -692,7 +761,10 @@ authenticated.put(
);
authenticated.put(
"/resource-policy/:resourcePolicyId/rules",
[
"/resource-policy/:resourcePolicyId/rules",
"/public-resource-policy/:resourcePolicyId/rules"
],
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyRules),
@@ -701,7 +773,10 @@ authenticated.put(
);
authenticated.post(
"/resource/:resourceId/roles/add",
[
"/resource/:resourceId/roles/add",
"/public-resource/:resourceId/roles/add"
],
verifyApiKeyResourceAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -711,7 +786,10 @@ authenticated.post(
);
authenticated.post(
"/resource/:resourceId/roles/remove",
[
"/resource/:resourceId/roles/remove",
"/public-resource/:resourceId/roles/remove"
],
verifyApiKeyResourceAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -721,7 +799,10 @@ authenticated.post(
);
authenticated.post(
"/resource/:resourceId/users/add",
[
"/resource/:resourceId/users/add",
"/public-resource/:resourceId/users/add"
],
verifyApiKeyResourceAccess,
verifyApiKeySetResourceUsers,
verifyLimits,
@@ -731,7 +812,10 @@ authenticated.post(
);
authenticated.post(
"/resource/:resourceId/users/remove",
[
"/resource/:resourceId/users/remove",
"/public-resource/:resourceId/users/remove"
],
verifyApiKeyResourceAccess,
verifyApiKeySetResourceUsers,
verifyLimits,
@@ -741,7 +825,7 @@ authenticated.post(
);
authenticated.post(
`/resource/:resourceId/password`,
[`/resource/:resourceId/password`, `/public-resource/:resourceId/password`],
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePassword),
@@ -750,7 +834,7 @@ authenticated.post(
);
authenticated.post(
`/resource/:resourceId/pincode`,
[`/resource/:resourceId/pincode`, `/public-resource/:resourceId/pincode`],
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePincode),
@@ -759,7 +843,10 @@ authenticated.post(
);
authenticated.post(
`/resource/:resourceId/header-auth`,
[
`/resource/:resourceId/header-auth`,
`/public-resource/:resourceId/header-auth`
],
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourceHeaderAuth),
@@ -768,7 +855,10 @@ authenticated.post(
);
authenticated.post(
`/resource/:resourceId/whitelist`,
[
`/resource/:resourceId/whitelist`,
`/public-resource/:resourceId/whitelist`
],
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourceWhitelist),
@@ -777,7 +867,10 @@ authenticated.post(
);
authenticated.post(
`/resource/:resourceId/whitelist/add`,
[
`/resource/:resourceId/whitelist/add`,
`/public-resource/:resourceId/whitelist/add`
],
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourceWhitelist),
@@ -785,7 +878,10 @@ authenticated.post(
);
authenticated.post(
`/resource/:resourceId/whitelist/remove`,
[
`/resource/:resourceId/whitelist/remove`,
`/public-resource/:resourceId/whitelist/remove`
],
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourceWhitelist),
@@ -793,14 +889,20 @@ authenticated.post(
);
authenticated.get(
`/resource/:resourceId/whitelist`,
[
`/resource/:resourceId/whitelist`,
`/public-resource/:resourceId/whitelist`
],
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.getResourceWhitelist),
resource.getResourceWhitelist
);
authenticated.post(
`/resource/:resourceId/access-token`,
[
`/resource/:resourceId/access-token`,
`/public-resource/:resourceId/access-token`
],
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.generateAccessToken),
@@ -809,7 +911,10 @@ authenticated.post(
);
authenticated.post(
`/resource/:resourceId/session-token`,
[
`/resource/:resourceId/session-token`,
`/public-resource/:resourceId/session-token`
],
verifyApiKeyResourceAccess,
verifyApiKeyUserAccess,
verifyLimits,
@@ -834,7 +939,10 @@ authenticated.get(
);
authenticated.get(
`/resource/:resourceId/access-tokens`,
[
`/resource/:resourceId/access-tokens`,
`/public-resource/:resourceId/access-tokens`
],
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listAccessTokens),
accessToken.listAccessTokens
@@ -1164,7 +1272,7 @@ authenticated.get(
);
authenticated.get(
"/org/:orgId/resource-names",
["/org/:orgId/resource-names", "/org/:orgId/public-resource-names"],
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.listResources),
resource.listAllResourceNames

View File

@@ -191,6 +191,19 @@ registry.registerPath({
responses: {}
});
registry.registerPath({
method: "get",
path: "/public-resource-policy/{resourcePolicyId}",
description: "Get a resource policy by its resourcePolicyId.",
tags: [OpenAPITags.Policy],
request: {
params: z.object({
resourcePolicyId: z.number()
})
},
responses: {}
});
export async function getResourcePolicy(
req: Request,
res: Response,

View File

@@ -54,6 +54,25 @@ registry.registerPath({
responses: {}
});
registry.registerPath({
method: "post",
path: "/public-resource-policy/{resourceId}/access-control",
description:
"Set access control users for a resource policy, including SSO, users, roles, Identity provider.",
tags: [OpenAPITags.Policy, OpenAPITags.User],
request: {
params: setResourcePolicyAccessControlParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyAcccessControlBodySchema
}
}
}
},
responses: {}
});
export async function setResourcePolicyAccessControl(
req: Request,
res: Response,

View File

@@ -43,6 +43,25 @@ registry.registerPath({
responses: {}
});
registry.registerPath({
method: "put",
path: "/public-resource-policy/{resourcePolicyId}/header-auth",
description:
"Set or update the header authentication for a resource policy. If user and password is not provided, it will remove the header authentication.",
tags: [OpenAPITags.Policy],
request: {
params: setResourcePolicyHeaderAuthParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyHeaderAuthBodySchema
}
}
}
},
responses: {}
});
export async function setResourcePolicyHeaderAuth(
req: Request,
res: Response,

View File

@@ -38,6 +38,25 @@ registry.registerPath({
responses: {}
});
registry.registerPath({
method: "put",
path: "/public-resource-policy/{resourcePolicyId}/password",
description:
"Set the password for a resource policy. Setting the password to null will remove it.",
tags: [OpenAPITags.Policy],
request: {
params: setResourcePolicyPasswordParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyPasswordBodySchema
}
}
}
},
responses: {}
});
export async function setResourcePolicyPassword(
req: Request,
res: Response,

View File

@@ -41,6 +41,25 @@ registry.registerPath({
responses: {}
});
registry.registerPath({
method: "put",
path: "/public-resource-policy/{resourcePolicyId}/pincode",
description:
"Set the PIN code for a resource policy. Setting the PIN code to null will remove it.",
tags: [OpenAPITags.Policy],
request: {
params: setResourcePolicyPincodeParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyPincodeBodySchema
}
}
}
},
responses: {}
});
export async function setResourcePolicyPincode(
req: Request,
res: Response,

View File

@@ -61,6 +61,25 @@ registry.registerPath({
responses: {}
});
registry.registerPath({
method: "put",
path: "/public-resource-policy/{resourcePolicyId}/rules",
description:
"Set all rules for a resource policy at once. This will replace all existing rules.",
tags: [OpenAPITags.Policy],
request: {
params: setResourcePolicyRulesParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyRulesBodySchema
}
}
}
},
responses: {}
});
export async function setResourcePolicyRules(
req: Request,
res: Response,

View File

@@ -46,6 +46,25 @@ registry.registerPath({
responses: {}
});
registry.registerPath({
method: "put",
path: "/public-resource-policy/{resourcePolicyId}/whitelist",
description:
"Set email whitelist for a resource policy. This will replace all existing emails.",
tags: [OpenAPITags.Policy],
request: {
params: setResourcePolicyWhitelistParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyWhitelistBodySchema
}
}
}
},
responses: {}
});
export async function setResourcePolicyWhitelist(
req: Request,
res: Response,

View File

@@ -36,6 +36,24 @@ registry.registerPath({
responses: {}
});
registry.registerPath({
method: "put",
path: "/public-resource-policy/{resourcePolicyId}",
description: "Update a resource policy.",
tags: [OpenAPITags.Org, OpenAPITags.Policy],
request: {
params: updateResourcePolicyParamsSchema,
body: {
content: {
"application/json": {
schema: updateResourcePolicyBodySchema
}
}
}
},
responses: {}
});
export async function updateResourcePolicy(
req: Request,
res: Response,

View File

@@ -63,6 +63,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/whitelist/add",
description: "Add a single email to the resource whitelist.",
tags: [OpenAPITags.PublicResource],
request: {
params: addEmailToResourceWhitelistParamsSchema,
body: {
content: {
"application/json": {
schema: addEmailToResourceWhitelistBodySchema
}
}
}
},
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 addEmailToResourceWhitelist(
req: Request,
res: Response,

View File

@@ -59,6 +59,40 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/roles/add",
description:
"Add a single role to a resource. When the resource has an inline policy defined (no shared resource policy assigned), the role is added to the inline policy instead of directly to the resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Role],
request: {
params: addRoleToResourceParamsSchema,
body: {
content: {
"application/json": {
schema: addRoleToResourceBodySchema
}
}
}
},
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 addRoleToResource(
req: Request,
res: Response,

View File

@@ -59,6 +59,40 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/users/add",
description:
"Add a single user to a resource. When the resource has an inline policy defined (no shared resource policy assigned), the user is added to the inline policy instead of directly to the resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.User],
request: {
params: addUserToResourceParamsSchema,
body: {
content: {
"application/json": {
schema: addUserToResourceBodySchema
}
}
}
},
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 addUserToResource(
req: Request,
res: Response,

View File

@@ -182,6 +182,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "put",
path: "/org/{orgId}/public-resource",
description: "Create a resource.",
tags: [OpenAPITags.PublicResource],
request: {
params: createResourceParamsSchema,
body: {
content: {
"application/json": {
schema: createHttpResourceSchema.or(createRawResourceSchema)
}
}
}
},
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 createResource(
req: Request,
res: Response,

View File

@@ -61,6 +61,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "put",
path: "/public-resource/{resourceId}/rule",
description: "Create a resource rule.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Rule],
request: {
params: createResourceRuleParamsSchema,
body: {
content: {
"application/json": {
schema: createResourceRuleSchema
}
}
}
},
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 createResourceRule(
req: Request,
res: Response,

View File

@@ -44,6 +44,32 @@ registry.registerPath({
}
});
registry.registerPath({
method: "delete",
path: "/public-resource/{resourceId}",
description: "Delete a resource.",
tags: [OpenAPITags.PublicResource],
request: {
params: deleteResourceSchema
},
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 deleteResource(
req: Request,
res: Response,

View File

@@ -41,6 +41,32 @@ registry.registerPath({
}
});
registry.registerPath({
method: "delete",
path: "/public-resource/{resourceId}/rule/{ruleId}",
description: "Delete a resource rule.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Rule],
request: {
params: deleteResourceRuleSchema
},
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 deleteResourceRule(
req: Request,
res: Response,

View File

@@ -116,6 +116,34 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/public-resource/{resourceId}",
description: "Get a resource by resourceId.",
tags: [OpenAPITags.PublicResource],
request: {
params: z.object({
resourceId: z.number()
})
},
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 getResource(
req: Request,
res: Response,

View File

@@ -33,6 +33,17 @@ registry.registerPath({
responses: {}
});
registry.registerPath({
method: "get",
path: "/public-resource/{resourceId}/policies",
description: "Get the inline and shared policies associated with a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Policy],
request: {
params: getResourcePoliciesParamsSchema
},
responses: {}
});
export async function getResourcePolicies(
req: Request,
res: Response,

View File

@@ -66,6 +66,32 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/public-resource/{resourceId}/whitelist",
description: "Get the whitelist of emails for a specific resource.",
tags: [OpenAPITags.PublicResource],
request: {
params: getResourceWhitelistSchema
},
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 getResourceWhitelist(
req: Request,
res: Response,

View File

@@ -57,6 +57,34 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/org/{orgId}/public-resource-names",
description: "List all resource names for an organization.",
tags: [OpenAPITags.PublicResource],
request: {
params: z.object({
orgId: z.string()
})
},
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 listAllResourceNames(
req: Request,
res: Response,

View File

@@ -70,6 +70,32 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/public-resource/{resourceId}/roles",
description: "List all roles for a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Role],
request: {
params: listResourceRolesSchema
},
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 listResourceRoles(
req: Request,
res: Response,

View File

@@ -94,6 +94,33 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/public-resource/{resourceId}/rules",
description: "List rules for a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Rule],
request: {
params: listResourceRulesParamsSchema,
query: listResourceRulesSchema
},
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 listResourceRules(
req: Request,
res: Response,

View File

@@ -60,6 +60,32 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/public-resource/{resourceId}/users",
description: "List all users for a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.User],
request: {
params: listResourceUsersSchema
},
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 listResourceUsers(
req: Request,
res: Response,

View File

@@ -425,6 +425,35 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/org/{orgId}/public-resources",
description: "List resources for an organization.",
tags: [OpenAPITags.PublicResource],
request: {
params: z.object({
orgId: z.string()
}),
query: listResourcesSchema
},
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 listResources(
req: Request,
res: Response,

View File

@@ -63,6 +63,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/whitelist/remove",
description: "Remove a single email from the resource whitelist.",
tags: [OpenAPITags.PublicResource],
request: {
params: removeEmailFromResourceWhitelistParamsSchema,
body: {
content: {
"application/json": {
schema: removeEmailFromResourceWhitelistBodySchema
}
}
}
},
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 removeEmailFromResourceWhitelist(
req: Request,
res: Response,

View File

@@ -58,6 +58,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/roles/remove",
description: "Remove a single role from a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Role],
request: {
params: removeRoleFromResourceParamsSchema,
body: {
content: {
"application/json": {
schema: removeRoleFromResourceBodySchema
}
}
}
},
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 removeRoleFromResource(
req: Request,
res: Response,

View File

@@ -58,6 +58,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/users/remove",
description: "Remove a single user from a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.User],
request: {
params: removeUserFromResourceParamsSchema,
body: {
content: {
"application/json": {
schema: removeUserFromResourceBodySchema
}
}
}
},
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 removeUserFromResource(
req: Request,
res: Response,

View File

@@ -60,6 +60,40 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/header-auth",
description:
"Set or update the header authentication for a resource. If user and password is not provided, it will remove the header authentication.",
tags: [OpenAPITags.PublicResource],
request: {
params: setResourceAuthMethodsParamsSchema,
body: {
content: {
"application/json": {
schema: setResourceAuthMethodsBodySchema
}
}
}
},
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 setResourceHeaderAuth(
req: Request,
res: Response,

View File

@@ -58,6 +58,40 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/password",
description:
"Set the password for a resource. Setting the password to null will remove it.",
tags: [OpenAPITags.PublicResource],
request: {
params: setResourceAuthMethodsParamsSchema,
body: {
content: {
"application/json": {
schema: setResourceAuthMethodsBodySchema
}
}
}
},
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 setResourcePassword(
req: Request,
res: Response,

View File

@@ -58,6 +58,40 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/pincode",
description:
"Set the PIN code for a resource. Setting the PIN code to null will remove it.",
tags: [OpenAPITags.PublicResource],
request: {
params: setResourceAuthMethodsParamsSchema,
body: {
content: {
"application/json": {
schema: setResourceAuthMethodsBodySchema
}
}
}
},
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 setResourcePincode(
req: Request,
res: Response,

View File

@@ -52,6 +52,40 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/roles",
description:
"Set roles for a resource. This will replace all existing roles. When the resource has an inline policy defined (no shared resource policy assigned), roles are set on the inline policy instead of directly on the resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Role],
request: {
params: setResourceRolesParamsSchema,
body: {
content: {
"application/json": {
schema: setResourceRolesBodySchema
}
}
}
},
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 setResourceRoles(
req: Request,
res: Response,

View File

@@ -52,6 +52,40 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/users",
description:
"Set users for a resource. This will replace all existing users. When the resource has an inline policy defined (no shared resource policy assigned), users are set on the inline policy instead of directly on the resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.User],
request: {
params: setUserResourcesParamsSchema,
body: {
content: {
"application/json": {
schema: setUserResourcesBodySchema
}
}
}
},
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 setResourceUsers(
req: Request,
res: Response,

View File

@@ -66,6 +66,40 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/whitelist",
description:
"Set email whitelist for a resource. This will replace all existing emails.",
tags: [OpenAPITags.PublicResource],
request: {
params: setResourceWhitelistParamsSchema,
body: {
content: {
"application/json": {
schema: setResourceWhitelistBodySchema
}
}
}
},
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 setResourceWhitelist(
req: Request,
res: Response,

View File

@@ -273,6 +273,42 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}",
description:
"Update a resource. Policy fields (sso, mfa, pincode, password, whitelist) update the inline policy when no shared resource policy is assigned; when a shared policy is assigned those fields override the shared policy for this resource only.",
tags: [OpenAPITags.PublicResource],
request: {
params: updateResourceParamsSchema,
body: {
content: {
"application/json": {
schema: updateHttpResourceBodySchema.and(
updateRawResourceBodySchema
)
}
}
}
},
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 updateResource(
req: Request,
res: Response,

View File

@@ -78,6 +78,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/rule/{ruleId}",
description: "Update a resource rule.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Rule],
request: {
params: updateResourceRuleParamsSchema,
body: {
content: {
"application/json": {
schema: updateResourceRuleSchema
}
}
}
},
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 updateResourceRule(
req: Request,
res: Response,

View File

@@ -1,62 +0,0 @@
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
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 {
getCachedStatusHistory,
statusHistoryQuerySchema,
StatusHistoryResponse
} from "@server/lib/statusHistory";
const siteParamsSchema = z.object({
siteId: z.string().transform((v) => parseInt(v, 10))
});
export async function getBatchedSiteStatusHistory(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedParams = siteParamsSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedParams.error).toString()
)
);
}
const parsedQuery = statusHistoryQuerySchema.safeParse(req.query);
if (!parsedQuery.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedQuery.error).toString()
)
);
}
const entityType = "site";
const entityId = parsedParams.data.siteId;
const { days } = parsedQuery.data;
const data = await getCachedStatusHistory(entityType, entityId, days);
return response<StatusHistoryResponse>(res, {
data,
success: true,
error: false,
message: "Status history retrieved successfully",
status: HttpCode.OK
});
} catch (error) {
logger.error(error);
return next(
createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred")
);
}
}

View File

@@ -62,6 +62,40 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/private-resource/{siteResourceId}/clients/add",
description:
"Add a single client to a site resource. Clients with a userId cannot be added.",
tags: [OpenAPITags.PrivateResource, OpenAPITags.Client],
request: {
params: addClientToSiteResourceParamsSchema,
body: {
content: {
"application/json": {
schema: addClientToSiteResourceBodySchema
}
}
}
},
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 addClientToSiteResource(
req: Request,
res: Response,

View File

@@ -62,6 +62,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/private-resource/{siteResourceId}/roles/add",
description: "Add a single role to a site resource.",
tags: [OpenAPITags.PrivateResource, OpenAPITags.Role],
request: {
params: addRoleToSiteResourceParamsSchema,
body: {
content: {
"application/json": {
schema: addRoleToSiteResourceBodySchema
}
}
}
},
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 addRoleToSiteResource(
req: Request,
res: Response,

View File

@@ -62,6 +62,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/private-resource/{siteResourceId}/users/add",
description: "Add a single user to a site resource.",
tags: [OpenAPITags.PrivateResource, OpenAPITags.User],
request: {
params: addUserToSiteResourceParamsSchema,
body: {
content: {
"application/json": {
schema: addUserToSiteResourceBodySchema
}
}
}
},
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 addUserToSiteResource(
req: Request,
res: Response,

View File

@@ -67,6 +67,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/client/{clientId}/private-resources",
description: "Add a machine client to multiple site resources at once.",
tags: [OpenAPITags.Client],
request: {
params: batchAddClientToSiteResourcesParamsSchema,
body: {
content: {
"application/json": {
schema: batchAddClientToSiteResourcesBodySchema
}
}
}
},
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 batchAddClientToSiteResources(
req: Request,
res: Response,

View File

@@ -237,6 +237,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "put",
path: "/org/{orgId}/private-resource",
description: "Create a new site resource.",
tags: [OpenAPITags.PrivateResource],
request: {
params: createSiteResourceParamsSchema,
body: {
content: {
"application/json": {
schema: createSiteResourceSchema
}
}
}
},
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 createSiteResource(
req: Request,
res: Response,

View File

@@ -49,6 +49,32 @@ registry.registerPath({
}
});
registry.registerPath({
method: "delete",
path: "/private-resource/{siteResourceId}",
description: "Delete a site resource.",
tags: [OpenAPITags.PrivateResource],
request: {
params: deleteSiteResourceParamsSchema
},
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 deleteSiteResource(
req: Request,
res: Response,

View File

@@ -83,6 +83,36 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/private-resource/{siteResourceId}",
description: "Get a specific site resource by siteResourceId.",
tags: [OpenAPITags.PrivateResource],
request: {
params: z.object({
siteResourceId: z.number(),
siteId: z.number(),
orgId: z.string()
})
},
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()
})
}
}
}
}
});
registry.registerPath({
method: "get",
path: "/org/{orgId}/site/{siteId}/resource/nice/{niceId}",

View File

@@ -244,6 +244,33 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/org/{orgId}/private-resources",
description: "List all site resources for an organization.",
tags: [OpenAPITags.PrivateResource],
request: {
params: listAllSiteResourcesByOrgParamsSchema,
query: listAllSiteResourcesByOrgQuerySchema
},
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 listAllSiteResourcesByOrg(
req: Request,
res: Response,

View File

@@ -61,6 +61,32 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/private-resource/{siteResourceId}/clients",
description: "List all clients for a site resource.",
tags: [OpenAPITags.PrivateResource, OpenAPITags.Client],
request: {
params: listSiteResourceClientsSchema
},
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 listSiteResourceClients(
req: Request,
res: Response,

View File

@@ -62,6 +62,32 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/private-resource/{siteResourceId}/roles",
description: "List all roles for a site resource.",
tags: [OpenAPITags.PrivateResource, OpenAPITags.Role],
request: {
params: listSiteResourceRolesSchema
},
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 listSiteResourceRoles(
req: Request,
res: Response,

View File

@@ -65,6 +65,32 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/private-resource/{siteResourceId}/users",
description: "List all users for a site resource.",
tags: [OpenAPITags.PrivateResource, OpenAPITags.User],
request: {
params: listSiteResourceUsersSchema
},
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 listSiteResourceUsers(
req: Request,
res: Response,

View File

@@ -81,6 +81,33 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/org/{orgId}/site/{siteId}/private-resources",
description: "List site resources for a site.",
tags: [OpenAPITags.PrivateResource],
request: {
params: listSiteResourcesParamsSchema,
query: listSiteResourcesQuerySchema
},
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 listSiteResources(
req: Request,
res: Response,

View File

@@ -62,6 +62,40 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/private-resource/{siteResourceId}/clients/remove",
description:
"Remove a single client from a site resource. Clients with a userId cannot be removed.",
tags: [OpenAPITags.PrivateResource, OpenAPITags.Client],
request: {
params: removeClientFromSiteResourceParamsSchema,
body: {
content: {
"application/json": {
schema: removeClientFromSiteResourceBodySchema
}
}
}
},
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 removeClientFromSiteResource(
req: Request,
res: Response,

View File

@@ -62,6 +62,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/private-resource/{siteResourceId}/roles/remove",
description: "Remove a single role from a site resource.",
tags: [OpenAPITags.PrivateResource, OpenAPITags.Role],
request: {
params: removeRoleFromSiteResourceParamsSchema,
body: {
content: {
"application/json": {
schema: removeRoleFromSiteResourceBodySchema
}
}
}
},
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 removeRoleFromSiteResource(
req: Request,
res: Response,

View File

@@ -62,6 +62,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/private-resource/{siteResourceId}/users/remove",
description: "Remove a single user from a site resource.",
tags: [OpenAPITags.PrivateResource, OpenAPITags.User],
request: {
params: removeUserFromSiteResourceParamsSchema,
body: {
content: {
"application/json": {
schema: removeUserFromSiteResourceBodySchema
}
}
}
},
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 removeUserFromSiteResource(
req: Request,
res: Response,

View File

@@ -62,6 +62,40 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/private-resource/{siteResourceId}/clients",
description:
"Set clients for a site resource. This will replace all existing clients. Clients with a userId cannot be added.",
tags: [OpenAPITags.PrivateResource, OpenAPITags.Client],
request: {
params: setSiteResourceClientsParamsSchema,
body: {
content: {
"application/json": {
schema: setSiteResourceClientsBodySchema
}
}
}
},
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 setSiteResourceClients(
req: Request,
res: Response,

View File

@@ -63,6 +63,40 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/private-resource/{siteResourceId}/roles",
description:
"Set roles for a site resource. This will replace all existing roles.",
tags: [OpenAPITags.PrivateResource, OpenAPITags.Role],
request: {
params: setSiteResourceRolesParamsSchema,
body: {
content: {
"application/json": {
schema: setSiteResourceRolesBodySchema
}
}
}
},
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 setSiteResourceRoles(
req: Request,
res: Response,

View File

@@ -64,6 +64,40 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/private-resource/{siteResourceId}/users",
description:
"Set users for a site resource. This will replace all existing users.",
tags: [OpenAPITags.PrivateResource, OpenAPITags.User],
request: {
params: setSiteResourceUsersParamsSchema,
body: {
content: {
"application/json": {
schema: setSiteResourceUsersBodySchema
}
}
}
},
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 setSiteResourceUsers(
req: Request,
res: Response,

View File

@@ -237,6 +237,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "post",
path: "/private-resource/{siteResourceId}",
description: "Update a site resource.",
tags: [OpenAPITags.PrivateResource],
request: {
params: updateSiteResourceParamsSchema,
body: {
content: {
"application/json": {
schema: updateSiteResourceSchema
}
}
}
},
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 updateSiteResource(
req: Request,
res: Response,

View File

@@ -122,6 +122,39 @@ registry.registerPath({
}
});
registry.registerPath({
method: "put",
path: "/public-resource/{resourceId}/target",
description: "Create a target for a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Target],
request: {
params: createTargetParamsSchema,
body: {
content: {
"application/json": {
schema: createTargetSchema
}
}
}
},
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 createTarget(
req: Request,
res: Response,

View File

@@ -115,6 +115,33 @@ registry.registerPath({
}
});
registry.registerPath({
method: "get",
path: "/public-resource/{resourceId}/targets",
description: "List targets for a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Target],
request: {
params: listTargetsParamsSchema,
query: listTargetsSchema
},
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 listTargets(
req: Request,
res: Response,

View File

@@ -640,28 +640,6 @@ export const orgQueries = {
};
}
}),
batchedSiteStatusHistory: ({
siteIds,
days = 90
}: {
siteIds: number[];
days?: number;
}) =>
queryOptions({
queryKey: [
"SITE_STATUS_HISTORY",
"BATCHED",
siteIds,
days
] as const,
queryFn: async ({ signal, meta }) => {
// TODO
// const res = await meta!.api.get<
// AxiosResponse<StatusHistoryResponse>
// >(`/site/${siteId}/status-history?days=${days}`, { signal });
// return res.data.data;
}
}),
siteStatusHistory: ({
siteId,
days = 90