Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot] 8d50a18de9 Bump the github-actions-dependencies group across 1 directory with 4 updates
Bumps the github-actions-dependencies group with 4 updates in the / directory: [docker/login-action](https://github.com/docker/login-action), [actions/setup-go](https://github.com/actions/setup-go), [actions/setup-node](https://github.com/actions/setup-node) and [actions/stale](https://github.com/actions/stale).


Updates `docker/login-action` from 4.2.0 to 4.4.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/650006c6eb7dba73a995cc03b0b2d7f5ca915bee...af1e73f918a031802d376d3c8bbc3fe56130a9b0)

Updates `actions/setup-go` from 6.4.0 to 7.0.0
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/4a3601121dd01d1626a1e23e37211e3254c1c06c...b7ad1dad31e06c5925ef5d2fc7ad053ef454303e)

Updates `actions/setup-node` from 6.4.0 to 7.0.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e...820762786026740c76f36085b0efc47a31fe5020)

Updates `actions/stale` from 10.3.0 to 10.4.0
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899...1e223db275d687790206a7acac4d1a11bd6fe629)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions-dependencies
- dependency-name: actions/setup-go
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions-dependencies
- dependency-name: actions/setup-node
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions-dependencies
- dependency-name: actions/stale
  dependency-version: 10.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-20 01:34:17 +00:00
91 changed files with 250 additions and 2585 deletions
+5 -5
View File
@@ -77,7 +77,7 @@ jobs:
fi
- name: Log in to Docker Hub
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry: docker.io
username: ${{ secrets.DOCKER_HUB_USERNAME }}
@@ -149,7 +149,7 @@ jobs:
fi
- name: Log in to Docker Hub
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry: docker.io
username: ${{ secrets.DOCKER_HUB_USERNAME }}
@@ -204,7 +204,7 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Log in to Docker Hub
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry: docker.io
username: ${{ secrets.DOCKER_HUB_USERNAME }}
@@ -264,7 +264,7 @@ jobs:
shell: bash
- name: Install Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: 1.25
@@ -407,7 +407,7 @@ jobs:
shell: bash
- name: Login to GitHub Container Registry (for cosign)
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10.3.0
- uses: actions/stale@1e223db275d687790206a7acac4d1a11bd6fe629 # v10.4.0
with:
days-before-stale: 14
days-before-close: 14
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Install Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
+2 -2
View File
@@ -5,7 +5,7 @@ go 1.25.0
require (
github.com/charmbracelet/huh v1.0.0
github.com/charmbracelet/lipgloss v1.1.0
golang.org/x/term v0.45.0
golang.org/x/term v0.44.0
gopkg.in/yaml.v3 v3.0.1
)
@@ -33,6 +33,6 @@ require (
github.com/rivo/uniseg v0.4.7 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/sync v0.15.0 // indirect
golang.org/x/sys v0.47.0 // indirect
golang.org/x/sys v0.46.0 // indirect
golang.org/x/text v0.23.0 // indirect
)
+4 -4
View File
@@ -69,10 +69,10 @@ golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+7 -10
View File
@@ -934,7 +934,7 @@
"newtVersion": "Version",
"architecture": "Architecture",
"sites": "Sites",
"siteWgAnyClients": "Use any WireGuard client to connect. You will have to address private resources using the peer IP.",
"siteWgAnyClients": "Use any WireGuard client to connect. You will have to address internal resources using the peer IP.",
"siteWgCompatibleAllClients": "Compatible with all WireGuard clients",
"siteWgManualConfigurationRequired": "Manual configuration required",
"userErrorNotAdminOrOwner": "User is not an admin or owner",
@@ -1995,9 +1995,6 @@
"domainPickerSubdomain": "Subdomain: {subdomain}",
"domainPickerNamespace": "Namespace: {namespace}",
"domainPickerShowMore": "Show More",
"domainPickerNoDomainsAvailableTitle": "No domains available",
"domainPickerNoDomainsAvailableDescription": "You don't have any domains set up yet. Create a domain to continue.",
"domainPickerNoDomainsAvailableAction": "Go to Domains",
"regionSelectorTitle": "Select Region",
"domainPickerRemoteExitNodeWarning": "Provided domains are not supported when sites connect to remote exit nodes. For resources to be available on remote nodes, use a custom domain instead.",
"regionSelectorInfo": "Selecting a region helps us provide better performance for your location. You do not have to be in the same region as your server.",
@@ -2361,7 +2358,7 @@
"resourcesTableProxyResources": "Public",
"resourcesTableClientResources": "Private",
"resourcesTableNoProxyResourcesFound": "No proxy resources found.",
"resourcesTableNoInternalResourcesFound": "No private resources found.",
"resourcesTableNoInternalResourcesFound": "No internal resources found.",
"resourcesTableDestination": "Destination",
"resourcesTableAlias": "Alias",
"resourcesTableAliasAddress": "Alias Address",
@@ -2384,9 +2381,9 @@
"editInternalResourceDialogCancel": "Cancel",
"editInternalResourceDialogSaveResource": "Save Resource",
"editInternalResourceDialogSuccess": "Success",
"editInternalResourceDialogInternalResourceUpdatedSuccessfully": "Private resource updated successfully",
"editInternalResourceDialogInternalResourceUpdatedSuccessfully": "Internal resource updated successfully",
"editInternalResourceDialogError": "Error",
"editInternalResourceDialogFailedToUpdateInternalResource": "Failed to update private resource",
"editInternalResourceDialogFailedToUpdateInternalResource": "Failed to update internal resource",
"editInternalResourceDialogNameRequired": "Name is required",
"editInternalResourceDialogNameMaxLength": "Name must be less than 255 characters",
"editInternalResourceDialogProxyPortMin": "Proxy port must be at least 1",
@@ -2412,7 +2409,7 @@
"editInternalResourceDialogAlias": "Alias",
"editInternalResourceDialogAliasDescription": "An optional internal DNS alias for this resource.",
"createInternalResourceDialogNoSitesAvailable": "No Sites Available",
"createInternalResourceDialogNoSitesAvailableDescription": "You need to have at least one Newt site with a subnet configured to create private resources.",
"createInternalResourceDialogNoSitesAvailableDescription": "You need to have at least one Newt site with a subnet configured to create internal resources.",
"createInternalResourceDialogClose": "Close",
"createInternalResourceDialogCreateClientResource": "Create Private Resource",
"createInternalResourceDialogCreateClientResourceDescription": "Create a new resource that will only be accessible to clients connected to the organization",
@@ -2441,9 +2438,9 @@
"createInternalResourceDialogCancel": "Cancel",
"createInternalResourceDialogCreateResource": "Create Resource",
"createInternalResourceDialogSuccess": "Success",
"createInternalResourceDialogInternalResourceCreatedSuccessfully": "Private resource created successfully",
"createInternalResourceDialogInternalResourceCreatedSuccessfully": "Internal resource created successfully",
"createInternalResourceDialogError": "Error",
"createInternalResourceDialogFailedToCreateInternalResource": "Failed to create private resource",
"createInternalResourceDialogFailedToCreateInternalResource": "Failed to create internal resource",
"createInternalResourceDialogNameRequired": "Name is required",
"createInternalResourceDialogNameMaxLength": "Name must be less than 255 characters",
"createInternalResourceDialogPleaseSelectSite": "Please select a site",
+11 -13
View File
@@ -30,14 +30,14 @@ export const NotifyTrialExpiring = ({
const isLastDay = daysRemaining === 1;
const previewText = hasEnded
? `Your cloud trial for ${orgName} has ended.`
? `Your trial for ${orgName} has ended.`
: isLastDay
? `Your cloud trial for ${orgName} ends tomorrow.`
: `Your cloud trial for ${orgName} ends in ${daysRemaining} days.`;
? `Your trial for ${orgName} ends tomorrow.`
: `Your trial for ${orgName} ends in ${daysRemaining} days.`;
const heading = hasEnded
? "Your Cloud Trial Ended"
: "Your Cloud Trial is Ending Soon";
? "Your Trial Ended"
: "Your Trial is Ending Soon";
return (
<Html>
@@ -55,7 +55,7 @@ export const NotifyTrialExpiring = ({
{hasEnded ? (
<>
<EmailText>
Your cloud free trial for{" "}
Your free trial for{" "}
<strong>{orgName}</strong> ended on{" "}
<strong>{trialEndsAt}</strong>. Your account
has been moved to the free plan, which
@@ -64,11 +64,10 @@ export const NotifyTrialExpiring = ({
<EmailText>
Some features and resources may now be
restricted. To restore full access and
continue using all the features you had
during your trial, please upgrade to a paid
plan. This does not effect any self hosted
licenses.
restricted. To restore full
access and continue using all the features
you had during your trial, please upgrade to
a paid plan.
</EmailText>
<EmailText>
@@ -94,8 +93,7 @@ export const NotifyTrialExpiring = ({
<EmailText>
After your trial ends, your account will be
moved to the free plan and some
functionality may be restricted. This does
not effect any self hosted licenses.
functionality may be restricted.
</EmailText>
<EmailText>
+2 -3
View File
@@ -12,7 +12,7 @@ import { logIncomingMiddleware } from "./middlewares/logIncoming";
import helmet from "helmet";
import swaggerUi from "swagger-ui-express";
import { OpenApiGeneratorV3 } from "@asteasolutions/zod-to-openapi";
import { registry, openApiTags } from "./openApi";
import { registry } from "./openApi";
import fs from "fs";
import path from "path";
import { APP_PATH } from "./lib/consts";
@@ -181,8 +181,7 @@ function getOpenApiDocumentation() {
version: "v1",
title: "Pangolin Integration API"
},
servers: [{ url: "/v1" }],
tags: openApiTags
servers: [{ url: "/v1" }]
});
if (!process.env.DISABLE_GEN_OPENAPI) {
+3 -34
View File
@@ -15,41 +15,10 @@ function getSegmentRegex(patternPart: string): RegExp {
return regex;
}
// Decodes percent-encoding (so an encoded slash like `%2F` is treated as a
// real path separator, matching what most backends will do) and then
// resolves `.` / `..` segments, so a request like `/public%2F..%2Fadmin/`
// or `/public/../admin/` is matched as `/admin/`, not as a literal segment
// or a wildcard-swallowed sequence under `/public/*`.
function decodeAndResolvePath(p: string): string[] {
const rawParts = p.split("/").filter(Boolean);
const resolved: string[] = [];
for (const rawPart of rawParts) {
let part: string;
try {
part = decodeURIComponent(rawPart);
} catch {
part = rawPart;
}
// an encoded slash can turn one raw segment into several real ones
for (const segment of part.split("/").filter(Boolean)) {
if (segment === ".") {
continue;
} else if (segment === "..") {
resolved.pop();
} else {
resolved.push(segment);
}
}
}
return resolved;
}
export function isPathAllowed(pattern: string, path: string): boolean {
const patternParts = pattern.split("/").filter(Boolean);
const pathParts = decodeAndResolvePath(path);
const normalize = (p: string) => p.split("/").filter(Boolean);
const patternParts = normalize(pattern);
const pathParts = normalize(path);
function matchSegments(
patternIndex: number,
+8 -19
View File
@@ -4,34 +4,23 @@ export const registry = new OpenAPIRegistry();
export enum OpenAPITags {
Site = "Site",
PublicResource = "Public Resource",
Target = "Resource Target",
PrivateResource = "Private Resource",
Client = "Client",
Org = "Organization",
Domain = "Domain",
PublicResourcePolicy = "Public Resource Policy",
PublicResource = "Public Resource",
PrivateResource = "Private Resource",
Policy = "Policy",
Role = "Role",
User = "User",
Rule = "Rule",
Invitation = "User Invitation",
Target = "Resource Target",
Rule = "Rule",
AccessToken = "Access Token",
GlobalIdp = "Identity Provider (Global)",
OrgIdp = "Identity Provider (Organization Only)",
Client = "Client",
ApiKey = "API Key",
SiteProvisioningKey = "Site Provisioning Key",
Domain = "Domain",
Blueprint = "Blueprint",
Ssh = "SSH",
Logs = "Logs",
EventStreamingDestination = "Event Streaming Destination",
AlertRule = "Alert Rule",
HealthCheck = "Health Check",
PublicResourcePolicyLegacy = "Public Resource Policy (Legacy)",
PublicResourceLegacy = "Public Resource (Legacy)",
PrivateResourceLegacy = "Private Resource (Legacy)"
Logs = "Logs"
}
// Order here controls the order tags are displayed in Swagger UI
export const openApiTags = Object.values(OpenAPITags).map((name) => ({
name
}));
@@ -191,7 +191,7 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/alert-rule",
description: "Create an alert rule for a specific organization.",
tags: [OpenAPITags.AlertRule],
tags: [OpenAPITags.Org],
request: {
params: paramsSchema,
body: {
@@ -34,7 +34,7 @@ registry.registerPath({
method: "delete",
path: "/org/{orgId}/alert-rule/{alertRuleId}",
description: "Delete an alert rule for a specific organization.",
tags: [OpenAPITags.AlertRule],
tags: [OpenAPITags.Org],
request: {
params: paramsSchema
},
@@ -48,7 +48,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/alert-rule/{alertRuleId}",
description: "Get a specific alert rule for an organization.",
tags: [OpenAPITags.AlertRule],
tags: [OpenAPITags.Org],
request: {
params: paramsSchema
},
@@ -90,7 +90,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/alert-rules",
description: "List all alert rules for a specific organization.",
tags: [OpenAPITags.AlertRule],
tags: [OpenAPITags.Org],
request: {
query: querySchema,
params: paramsSchema
@@ -158,7 +158,7 @@ registry.registerPath({
method: "post",
path: "/org/{orgId}/alert-rule/{alertRuleId}",
description: "Update an alert rule for a specific organization.",
tags: [OpenAPITags.AlertRule],
tags: [OpenAPITags.Org],
request: {
params: paramsSchema,
body: {
@@ -52,7 +52,7 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/event-streaming-destination",
description: "Create an event streaming destination for a specific organization.",
tags: [OpenAPITags.EventStreamingDestination],
tags: [OpenAPITags.Org],
request: {
params: paramsSchema,
body: {
@@ -35,7 +35,7 @@ registry.registerPath({
path: "/org/{orgId}/event-streaming-destination/{destinationId}",
description:
"Delete an event streaming destination for a specific organization.",
tags: [OpenAPITags.EventStreamingDestination],
tags: [OpenAPITags.Org],
request: {
params: paramsSchema
},
@@ -109,7 +109,7 @@ registry.registerPath({
path: "/org/{orgId}/event-streaming-destination",
description:
"List all event streaming destinations for a specific organization.",
tags: [OpenAPITags.EventStreamingDestination],
tags: [OpenAPITags.Org],
request: {
query: querySchema,
params: paramsSchema
@@ -55,7 +55,7 @@ registry.registerPath({
method: "post",
path: "/org/{orgId}/event-streaming-destination/{destinationId}",
description: "Update an event streaming destination for a specific organization.",
tags: [OpenAPITags.EventStreamingDestination],
tags: [OpenAPITags.Org],
request: {
params: paramsSchema,
body: {
@@ -75,7 +75,7 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/health-check",
description: "Create a health check for a specific organization.",
tags: [OpenAPITags.HealthCheck],
tags: [OpenAPITags.Org],
request: {
params: paramsSchema,
body: {
@@ -37,7 +37,7 @@ registry.registerPath({
method: "delete",
path: "/org/{orgId}/health-check/{healthCheckId}",
description: "Delete a health check for a specific organization.",
tags: [OpenAPITags.HealthCheck],
tags: [OpenAPITags.Org],
request: {
params: paramsSchema
},
@@ -63,7 +63,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/health-checks",
description: "List health checks for an organization.",
tags: [OpenAPITags.HealthCheck],
tags: [OpenAPITags.Org],
request: {
params: paramsSchema,
query: querySchema
@@ -109,7 +109,7 @@ registry.registerPath({
method: "post",
path: "/org/{orgId}/health-check/{healthCheckId}",
description: "Update a health check for a specific organization.",
tags: [OpenAPITags.HealthCheck],
tags: [OpenAPITags.Org],
request: {
params: paramsSchema,
body: {
-152
View File
@@ -17,10 +17,6 @@ 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 * as policy from "#private/routers/policy";
import * as eventStreamingDestination from "#private/routers/eventStreamingDestination";
import * as alertRule from "#private/routers/alertRule";
import * as healthChecks from "#private/routers/healthChecks";
import {
verifyApiKeyHasAction,
@@ -30,7 +26,6 @@ import {
verifyApiKeyRoleAccess,
verifyApiKeyUserAccess,
verifyApiKeySiteProvisioningKeyAccess,
verifyApiKeyResourcePolicyAccess,
verifyLimits
} from "@server/middlewares";
import * as user from "#private/routers/user";
@@ -264,150 +259,3 @@ authenticated.patch(
logActionAudit(ActionsEnum.updateSiteProvisioningKey),
siteProvisioning.updateSiteProvisioningKey
);
authenticated.get(
["/org/:orgId/resource-policies", "/org/:orgId/public-resource-policies"],
verifyValidLicense,
verifyValidSubscription(tierMatrix.resourcePolicies),
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.listResourcePolicies),
logActionAudit(ActionsEnum.listResourcePolicies),
policy.listResourcePolicies
);
authenticated.post(
["/org/:orgId/resource-policy", "/org/:orgId/public-resource-policy"],
verifyValidLicense,
verifyValidSubscription(tierMatrix.resourcePolicies),
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createResourcePolicy),
logActionAudit(ActionsEnum.createResourcePolicy),
policy.createResourcePolicy
);
authenticated.delete(
[
"/resource-policy/:resourcePolicyId",
"/public-resource-policy/:resourcePolicyId"
],
verifyApiKeyResourcePolicyAccess,
verifyValidLicense,
verifyValidSubscription(tierMatrix.resourcePolicies),
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.deleteResourcePolicy),
logActionAudit(ActionsEnum.deleteResourcePolicy),
policy.deleteResourcePolicy
);
authenticated.put(
"/org/:orgId/event-streaming-destination",
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createEventStreamingDestination),
logActionAudit(ActionsEnum.createEventStreamingDestination),
eventStreamingDestination.createEventStreamingDestination
);
authenticated.post(
"/org/:orgId/event-streaming-destination/:destinationId",
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.updateEventStreamingDestination),
logActionAudit(ActionsEnum.updateEventStreamingDestination),
eventStreamingDestination.updateEventStreamingDestination
);
authenticated.delete(
"/org/:orgId/event-streaming-destination/:destinationId",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.deleteEventStreamingDestination),
logActionAudit(ActionsEnum.deleteEventStreamingDestination),
eventStreamingDestination.deleteEventStreamingDestination
);
authenticated.get(
"/org/:orgId/event-streaming-destinations",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.listEventStreamingDestinations),
eventStreamingDestination.listEventStreamingDestinations
);
authenticated.put(
"/org/:orgId/alert-rule",
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createAlertRule),
logActionAudit(ActionsEnum.createAlertRule),
alertRule.createAlertRule
);
authenticated.post(
"/org/:orgId/alert-rule/:alertRuleId",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.updateAlertRule),
logActionAudit(ActionsEnum.updateAlertRule),
alertRule.updateAlertRule
);
authenticated.delete(
"/org/:orgId/alert-rule/:alertRuleId",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.deleteAlertRule),
logActionAudit(ActionsEnum.deleteAlertRule),
alertRule.deleteAlertRule
);
authenticated.get(
"/org/:orgId/alert-rules",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.listAlertRules),
alertRule.listAlertRules
);
authenticated.get(
"/org/:orgId/alert-rule/:alertRuleId",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.getAlertRule),
alertRule.getAlertRule
);
authenticated.get(
"/org/:orgId/health-checks",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.listHealthChecks),
healthChecks.listHealthChecks
);
authenticated.put(
"/org/:orgId/health-check",
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createHealthCheck),
logActionAudit(ActionsEnum.createHealthCheck),
healthChecks.createHealthCheck
);
authenticated.post(
"/org/:orgId/health-check/:healthCheckId",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.updateHealthCheck),
logActionAudit(ActionsEnum.updateHealthCheck),
healthChecks.updateHealthCheck
);
authenticated.delete(
"/org/:orgId/health-check/:healthCheckId",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.deleteHealthCheck),
logActionAudit(ActionsEnum.deleteHealthCheck),
healthChecks.deleteHealthCheck
);
authenticated.get(
"/org/:orgId/health-check/:healthCheckId/status-history",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.getTarget),
healthChecks.getHealthCheckStatusHistory
);
@@ -121,7 +121,7 @@ registry.registerPath({
method: "post",
path: "/org/{orgId}/resource-policy",
description: "Create a resource policy.",
tags: [OpenAPITags.PublicResourcePolicy],
tags: [OpenAPITags.Org, OpenAPITags.Policy],
request: {
params: createResourcePolicyParamsSchema,
body: {
@@ -31,7 +31,7 @@ registry.registerPath({
method: "delete",
path: "/resource-policy/{resourcePolicyId}",
description: "Delete a resource policy.",
tags: [OpenAPITags.PublicResourcePolicy],
tags: [OpenAPITags.Policy],
request: {
params: deleteResourcePolicySchema
},
@@ -79,7 +79,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/resource-policies",
description: "List resource policies for an organization.",
tags: [OpenAPITags.PublicResourcePolicy],
tags: [OpenAPITags.Org, OpenAPITags.Policy],
request: {
params: z.object({
orgId: z.string()
@@ -45,39 +45,6 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/access-token",
description: "Generate a new access token for a resource.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
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,
@@ -159,35 +159,6 @@ registry.registerPath({
method: "get",
path: "/resource/{resourceId}/access-tokens",
description: "List all access tokens for a resource.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
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({
@@ -236,38 +236,6 @@ function runTests() {
"Root path should not match non-root path"
);
// Path traversal / encoded-slash bypass regression tests
assertEquals(
isPathAllowed("public/*", "public/../admin"),
false,
"Literal .. traversal out of an allowed prefix must not match"
);
assertEquals(
isPathAllowed("public/*", "public%2F..%2Fadmin"),
false,
"Encoded-slash traversal out of an allowed prefix must not match"
);
assertEquals(
isPathAllowed("public/*", "public%2f..%2fadmin%2ffile"),
false,
"Encoded-slash traversal is case-insensitively decoded before matching"
);
assertEquals(
isPathAllowed("admin/*", "public/../admin/secret"),
true,
".. traversal INTO a restricted path should still be caught by its own rule"
);
assertEquals(
isPathAllowed("public/*", "public%2Ffoo"),
true,
"Encoded slash without traversal should still resolve and match normally"
);
assertEquals(
isPathAllowed("public/*", "public/./foo"),
true,
"Single-dot segments are a no-op and should not affect matching"
);
console.log("All path matching tests passed!");
}
+1 -1
View File
@@ -418,7 +418,7 @@ export async function verifyResourceSession(
}
// check for HTTP Basic Auth header
const clientHeaderAuthKey = `headerAuth:${resource.resourceId}:${clientHeaderAuth}`;
const clientHeaderAuthKey = `headerAuth:${clientHeaderAuth}`;
if (headerAuth && clientHeaderAuth) {
if (localCache.get(clientHeaderAuthKey)) {
logger.debug(
+1 -26
View File
@@ -32,35 +32,10 @@ const UpdateDomainResponseDataSchema = z.object({
});
registry.registerPath({
method: "post",
path: "/org/{orgId}/domain/{domainId}",
description: "Update a domain by domainId.",
tags: [OpenAPITags.Domain],
request: {
params: z.object({
domainId: z.string(),
orgId: z.string()
})
},
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: createApiResponseSchema(UpdateDomainResponseDataSchema)
}
}
}
}
});
registry.registerPath({
method: "patch",
path: "/org/{orgId}/domain/{domainId}",
description:
"Update a domain by domainId. Deprecated: use POST instead.",
deprecated: true,
description: "Update a domain by domainId.",
tags: [OpenAPITags.Domain],
request: {
params: z.object({
+60 -266
View File
@@ -163,7 +163,7 @@ authenticated.get(
// Site Resource endpoints
authenticated.put(
["/org/:orgId/site-resource", "/org/:orgId/private-resource"],
"/org/:orgId/site-resource",
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createSiteResource),
@@ -172,10 +172,7 @@ authenticated.put(
);
authenticated.get(
[
"/org/:orgId/site/:siteId/resources",
"/org/:orgId/site/:siteId/private-resources"
],
"/org/:orgId/site/:siteId/resources",
verifyApiKeyOrgAccess,
verifyApiKeySiteAccess,
verifyApiKeyHasAction(ActionsEnum.listSiteResources),
@@ -183,21 +180,21 @@ authenticated.get(
);
authenticated.get(
["/org/:orgId/site-resources", "/org/:orgId/private-resources"],
"/org/:orgId/site-resources",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.listSiteResources),
siteResource.listAllSiteResourcesByOrg
);
authenticated.get(
["/site-resource/:siteResourceId", "/private-resource/:siteResourceId"],
"/site-resource/:siteResourceId",
verifyApiKeySiteResourceAccess,
verifyApiKeyHasAction(ActionsEnum.getSiteResource),
siteResource.getSiteResource
);
authenticated.post(
["/site-resource/:siteResourceId", "/private-resource/:siteResourceId"],
"/site-resource/:siteResourceId",
verifyApiKeySiteResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.updateSiteResource),
@@ -206,7 +203,7 @@ authenticated.post(
);
authenticated.delete(
["/site-resource/:siteResourceId", "/private-resource/:siteResourceId"],
"/site-resource/:siteResourceId",
verifyApiKeySiteResourceAccess,
verifyApiKeyHasAction(ActionsEnum.deleteSiteResource),
logActionAudit(ActionsEnum.deleteSiteResource),
@@ -214,40 +211,28 @@ authenticated.delete(
);
authenticated.get(
[
"/site-resource/:siteResourceId/roles",
"/private-resource/:siteResourceId/roles"
],
"/site-resource/:siteResourceId/roles",
verifyApiKeySiteResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listResourceRoles),
siteResource.listSiteResourceRoles
);
authenticated.get(
[
"/site-resource/:siteResourceId/users",
"/private-resource/:siteResourceId/users"
],
"/site-resource/:siteResourceId/users",
verifyApiKeySiteResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listResourceUsers),
siteResource.listSiteResourceUsers
);
authenticated.get(
[
"/site-resource/:siteResourceId/clients",
"/private-resource/:siteResourceId/clients"
],
"/site-resource/:siteResourceId/clients",
verifyApiKeySiteResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listResourceUsers),
siteResource.listSiteResourceClients
);
authenticated.post(
[
"/site-resource/:siteResourceId/roles",
"/private-resource/:siteResourceId/roles"
],
"/site-resource/:siteResourceId/roles",
verifyApiKeySiteResourceAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -257,10 +242,7 @@ authenticated.post(
);
authenticated.post(
[
"/site-resource/:siteResourceId/users",
"/private-resource/:siteResourceId/users"
],
"/site-resource/:siteResourceId/users",
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceUsers,
verifyLimits,
@@ -270,10 +252,7 @@ authenticated.post(
);
authenticated.post(
[
"/site-resource/:siteResourceId/roles/add",
"/private-resource/:siteResourceId/roles/add"
],
"/site-resource/:siteResourceId/roles/add",
verifyApiKeySiteResourceAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -283,10 +262,7 @@ authenticated.post(
);
authenticated.post(
[
"/site-resource/:siteResourceId/roles/remove",
"/private-resource/:siteResourceId/roles/remove"
],
"/site-resource/:siteResourceId/roles/remove",
verifyApiKeySiteResourceAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -296,10 +272,7 @@ authenticated.post(
);
authenticated.post(
[
"/site-resource/:siteResourceId/users/add",
"/private-resource/:siteResourceId/users/add"
],
"/site-resource/:siteResourceId/users/add",
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceUsers,
verifyLimits,
@@ -309,10 +282,7 @@ authenticated.post(
);
authenticated.post(
[
"/site-resource/:siteResourceId/users/remove",
"/private-resource/:siteResourceId/users/remove"
],
"/site-resource/:siteResourceId/users/remove",
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceUsers,
verifyLimits,
@@ -322,10 +292,7 @@ authenticated.post(
);
authenticated.post(
[
"/site-resource/:siteResourceId/clients",
"/private-resource/:siteResourceId/clients"
],
"/site-resource/:siteResourceId/clients",
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceClients,
verifyLimits,
@@ -335,10 +302,7 @@ authenticated.post(
);
authenticated.post(
[
"/site-resource/:siteResourceId/clients/add",
"/private-resource/:siteResourceId/clients/add"
],
"/site-resource/:siteResourceId/clients/add",
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceClients,
verifyLimits,
@@ -348,10 +312,7 @@ authenticated.post(
);
authenticated.post(
[
"/site-resource/:siteResourceId/clients/remove",
"/private-resource/:siteResourceId/clients/remove"
],
"/site-resource/:siteResourceId/clients/remove",
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceClients,
verifyLimits,
@@ -361,7 +322,7 @@ authenticated.post(
);
authenticated.post(
["/client/:clientId/site-resources", "/client/:clientId/private-resources"],
"/client/:clientId/site-resources",
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourceUsers),
logActionAudit(ActionsEnum.setResourceUsers),
@@ -369,7 +330,7 @@ authenticated.post(
);
authenticated.put(
["/org/:orgId/resource", "/org/:orgId/public-resource"],
"/org/:orgId/resource",
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createResource),
@@ -378,10 +339,7 @@ authenticated.put(
);
authenticated.put(
[
"/org/:orgId/site/:siteId/resource",
"/org/:orgId/site/:siteId/public-resource"
],
"/org/:orgId/site/:siteId/resource",
verifyApiKeyOrgAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createResource),
@@ -390,14 +348,14 @@ authenticated.put(
);
authenticated.get(
["/site/:siteId/resources", "/site/:siteId/public-resources"],
"/site/:siteId/resources",
verifyApiKeySiteAccess,
verifyApiKeyHasAction(ActionsEnum.listResources),
resource.listResources
);
authenticated.get(
["/org/:orgId/resources", "/org/:orgId/public-resources"],
"/org/:orgId/resources",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.listResources),
resource.listResources
@@ -426,15 +384,6 @@ authenticated.put(
domain.createOrgDomain
);
authenticated.post(
"/org/:orgId/domain/:domainId",
verifyApiKeyOrgAccess,
verifyApiKeyDomainAccess,
verifyApiKeyHasAction(ActionsEnum.updateOrgDomain),
domain.updateOrgDomain
);
// Deprecated: use POST instead. Kept for backward compatibility.
authenticated.patch(
"/org/:orgId/domain/:domainId",
verifyApiKeyOrgAccess,
@@ -494,45 +443,42 @@ authenticated.delete(
);
authenticated.get(
["/resource/:resourceId/roles", "/public-resource/:resourceId/roles"],
"/resource/:resourceId/roles",
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listResourceRoles),
resource.listResourceRoles
);
authenticated.get(
["/resource/:resourceId/users", "/public-resource/:resourceId/users"],
"/resource/:resourceId/users",
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listResourceUsers),
resource.listResourceUsers
);
authenticated.get(
["/resource/:resourceId", "/public-resource/:resourceId"],
"/resource/:resourceId",
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.getResource),
resource.getResource
);
authenticated.get(
[
"/resource-policy/:resourcePolicyId",
"/public-resource-policy/:resourcePolicyId"
],
"/resource-policy/:resourcePolicyId",
verifyApiKeyResourcePolicyAccess,
verifyApiKeyHasAction(ActionsEnum.getResourcePolicy),
policy.getResourcePolicy
);
authenticated.get(
["/resource/:resourceId/policies", "/public-resource/:resourceId/policies"],
"/resource/:resourceId/policies",
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.getResourcePolicy),
resource.getResourcePolicies
);
authenticated.post(
["/resource/:resourceId", "/public-resource/:resourceId"],
"/resource/:resourceId",
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.updateResource),
@@ -540,29 +486,15 @@ authenticated.post(
resource.updateResource
);
authenticated.post(
[
"/resource-policy/:resourcePolicyId",
"/public-resource-policy/:resourcePolicyId"
],
verifyApiKeyResourcePolicyAccess,
verifyApiKeyHasAction(ActionsEnum.updateResourcePolicy),
policy.updateResourcePolicy
);
// Deprecated: use POST instead. Kept for backward compatibility.
authenticated.put(
[
"/resource-policy/:resourcePolicyId",
"/public-resource-policy/:resourcePolicyId"
],
"/resource-policy/:resourcePolicyId",
verifyApiKeyResourcePolicyAccess,
verifyApiKeyHasAction(ActionsEnum.updateResourcePolicy),
policy.updateResourcePolicy
);
authenticated.delete(
["/resource/:resourceId", "/public-resource/:resourceId"],
"/resource/:resourceId",
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.deleteResource),
logActionAudit(ActionsEnum.deleteResource),
@@ -570,7 +502,7 @@ authenticated.delete(
);
authenticated.put(
["/resource/:resourceId/target", "/public-resource/:resourceId/target"],
"/resource/:resourceId/target",
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createTarget),
@@ -579,14 +511,14 @@ authenticated.put(
);
authenticated.get(
["/resource/:resourceId/targets", "/public-resource/:resourceId/targets"],
"/resource/:resourceId/targets",
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listTargets),
target.listTargets
);
authenticated.put(
["/resource/:resourceId/rule", "/public-resource/:resourceId/rule"],
"/resource/:resourceId/rule",
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.createResourceRule),
@@ -595,17 +527,14 @@ authenticated.put(
);
authenticated.get(
["/resource/:resourceId/rules", "/public-resource/:resourceId/rules"],
"/resource/:resourceId/rules",
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listResourceRules),
resource.listResourceRules
);
authenticated.post(
[
"/resource/:resourceId/rule/:ruleId",
"/public-resource/:resourceId/rule/:ruleId"
],
"/resource/:resourceId/rule/:ruleId",
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.updateResourceRule),
@@ -614,10 +543,7 @@ authenticated.post(
);
authenticated.delete(
[
"/resource/:resourceId/rule/:ruleId",
"/public-resource/:resourceId/rule/:ruleId"
],
"/resource/:resourceId/rule/:ruleId",
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.deleteResourceRule),
logActionAudit(ActionsEnum.deleteResourceRule),
@@ -699,7 +625,7 @@ authenticated.post(
);
authenticated.post(
["/resource/:resourceId/roles", "/public-resource/:resourceId/roles"],
"/resource/:resourceId/roles",
verifyApiKeyResourceAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -709,7 +635,7 @@ authenticated.post(
);
authenticated.post(
["/resource/:resourceId/users", "/public-resource/:resourceId/users"],
"/resource/:resourceId/users",
verifyApiKeyResourceAccess,
verifyApiKeySetResourceUsers,
verifyLimits,
@@ -718,11 +644,8 @@ authenticated.post(
resource.setResourceUsers
);
authenticated.post(
[
"/resource-policy/:resourcePolicyId/access-control",
"/public-resource-policy/:resourcePolicyId/access-control"
],
authenticated.put(
"/resource-policy/:resourcePolicyId/access-control",
verifyApiKeyResourcePolicyAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -733,27 +656,8 @@ authenticated.post(
policy.setResourcePolicyAccessControl
);
// Deprecated: use POST instead. Kept for backward compatibility.
authenticated.put(
[
"/resource-policy/:resourcePolicyId/access-control",
"/public-resource-policy/:resourcePolicyId/access-control"
],
verifyApiKeyResourcePolicyAccess,
verifyApiKeyRoleAccess,
verifyLimits,
verifyUserHasAction(ActionsEnum.setResourcePolicyUsers),
verifyUserHasAction(ActionsEnum.setResourcePolicyRoles),
logActionAudit(ActionsEnum.setResourcePolicyUsers),
logActionAudit(ActionsEnum.setResourcePolicyRoles),
policy.setResourcePolicyAccessControl
);
authenticated.post(
[
"/resource-policy/:resourcePolicyId/password",
"/public-resource-policy/:resourcePolicyId/password"
],
"/resource-policy/:resourcePolicyId/password",
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyPassword),
@@ -761,24 +665,8 @@ authenticated.post(
policy.setResourcePolicyPassword
);
// Deprecated: use POST instead. Kept for backward compatibility.
authenticated.put(
[
"/resource-policy/:resourcePolicyId/password",
"/public-resource-policy/:resourcePolicyId/password"
],
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyPassword),
logActionAudit(ActionsEnum.setResourcePolicyPassword),
policy.setResourcePolicyPassword
);
authenticated.post(
[
"/resource-policy/:resourcePolicyId/pincode",
"/public-resource-policy/:resourcePolicyId/pincode"
],
"/resource-policy/:resourcePolicyId/pincode",
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyPincode),
@@ -786,24 +674,8 @@ authenticated.post(
policy.setResourcePolicyPincode
);
// Deprecated: use POST instead. Kept for backward compatibility.
authenticated.put(
[
"/resource-policy/:resourcePolicyId/pincode",
"/public-resource-policy/:resourcePolicyId/pincode"
],
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyPincode),
logActionAudit(ActionsEnum.setResourcePolicyPincode),
policy.setResourcePolicyPincode
);
authenticated.post(
[
"/resource-policy/:resourcePolicyId/header-auth",
"/public-resource-policy/:resourcePolicyId/header-auth"
],
"/resource-policy/:resourcePolicyId/header-auth",
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyHeaderAuth),
@@ -811,24 +683,8 @@ authenticated.post(
policy.setResourcePolicyHeaderAuth
);
// Deprecated: use POST instead. Kept for backward compatibility.
authenticated.put(
[
"/resource-policy/:resourcePolicyId/header-auth",
"/public-resource-policy/:resourcePolicyId/header-auth"
],
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyHeaderAuth),
logActionAudit(ActionsEnum.setResourcePolicyHeaderAuth),
policy.setResourcePolicyHeaderAuth
);
authenticated.post(
[
"/resource-policy/:resourcePolicyId/whitelist",
"/public-resource-policy/:resourcePolicyId/whitelist"
],
"/resource-policy/:resourcePolicyId/whitelist",
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyWhitelist),
@@ -836,37 +692,8 @@ authenticated.post(
policy.setResourcePolicyWhitelist
);
// Deprecated: use POST instead. Kept for backward compatibility.
authenticated.put(
[
"/resource-policy/:resourcePolicyId/whitelist",
"/public-resource-policy/:resourcePolicyId/whitelist"
],
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyWhitelist),
logActionAudit(ActionsEnum.setResourcePolicyWhitelist),
policy.setResourcePolicyWhitelist
);
authenticated.post(
[
"/resource-policy/:resourcePolicyId/rules",
"/public-resource-policy/:resourcePolicyId/rules"
],
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyRules),
logActionAudit(ActionsEnum.setResourcePolicyRules),
policy.setResourcePolicyRules
);
// Deprecated: use POST instead. Kept for backward compatibility.
authenticated.put(
[
"/resource-policy/:resourcePolicyId/rules",
"/public-resource-policy/:resourcePolicyId/rules"
],
"/resource-policy/:resourcePolicyId/rules",
verifyApiKeyResourcePolicyAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePolicyRules),
@@ -875,10 +702,7 @@ authenticated.put(
);
authenticated.post(
[
"/resource/:resourceId/roles/add",
"/public-resource/:resourceId/roles/add"
],
"/resource/:resourceId/roles/add",
verifyApiKeyResourceAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -888,10 +712,7 @@ authenticated.post(
);
authenticated.post(
[
"/resource/:resourceId/roles/remove",
"/public-resource/:resourceId/roles/remove"
],
"/resource/:resourceId/roles/remove",
verifyApiKeyResourceAccess,
verifyApiKeyRoleAccess,
verifyLimits,
@@ -901,10 +722,7 @@ authenticated.post(
);
authenticated.post(
[
"/resource/:resourceId/users/add",
"/public-resource/:resourceId/users/add"
],
"/resource/:resourceId/users/add",
verifyApiKeyResourceAccess,
verifyApiKeySetResourceUsers,
verifyLimits,
@@ -914,10 +732,7 @@ authenticated.post(
);
authenticated.post(
[
"/resource/:resourceId/users/remove",
"/public-resource/:resourceId/users/remove"
],
"/resource/:resourceId/users/remove",
verifyApiKeyResourceAccess,
verifyApiKeySetResourceUsers,
verifyLimits,
@@ -927,7 +742,7 @@ authenticated.post(
);
authenticated.post(
[`/resource/:resourceId/password`, `/public-resource/:resourceId/password`],
`/resource/:resourceId/password`,
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePassword),
@@ -936,7 +751,7 @@ authenticated.post(
);
authenticated.post(
[`/resource/:resourceId/pincode`, `/public-resource/:resourceId/pincode`],
`/resource/:resourceId/pincode`,
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourcePincode),
@@ -945,10 +760,7 @@ authenticated.post(
);
authenticated.post(
[
`/resource/:resourceId/header-auth`,
`/public-resource/:resourceId/header-auth`
],
`/resource/:resourceId/header-auth`,
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourceHeaderAuth),
@@ -957,10 +769,7 @@ authenticated.post(
);
authenticated.post(
[
`/resource/:resourceId/whitelist`,
`/public-resource/:resourceId/whitelist`
],
`/resource/:resourceId/whitelist`,
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourceWhitelist),
@@ -969,10 +778,7 @@ authenticated.post(
);
authenticated.post(
[
`/resource/:resourceId/whitelist/add`,
`/public-resource/:resourceId/whitelist/add`
],
`/resource/:resourceId/whitelist/add`,
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourceWhitelist),
@@ -980,10 +786,7 @@ authenticated.post(
);
authenticated.post(
[
`/resource/:resourceId/whitelist/remove`,
`/public-resource/:resourceId/whitelist/remove`
],
`/resource/:resourceId/whitelist/remove`,
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourceWhitelist),
@@ -991,20 +794,14 @@ authenticated.post(
);
authenticated.get(
[
`/resource/:resourceId/whitelist`,
`/public-resource/:resourceId/whitelist`
],
`/resource/:resourceId/whitelist`,
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.getResourceWhitelist),
resource.getResourceWhitelist
);
authenticated.post(
[
`/resource/:resourceId/access-token`,
`/public-resource/:resourceId/access-token`
],
`/resource/:resourceId/access-token`,
verifyApiKeyResourceAccess,
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.generateAccessToken),
@@ -1028,10 +825,7 @@ authenticated.get(
);
authenticated.get(
[
`/resource/:resourceId/access-tokens`,
`/public-resource/:resourceId/access-tokens`
],
`/resource/:resourceId/access-tokens`,
verifyApiKeyResourceAccess,
verifyApiKeyHasAction(ActionsEnum.listAccessTokens),
accessToken.listAccessTokens
@@ -1361,7 +1155,7 @@ authenticated.get(
);
authenticated.get(
["/org/:orgId/resource-names", "/org/:orgId/public-resource-names"],
"/org/:orgId/resource-names",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.listResources),
resource.listAllResourceNames
+2 -15
View File
@@ -168,7 +168,7 @@ registry.registerPath({
path: "/org/{orgId}/resource-policy/{niceId}",
description:
"Get a resource policy by orgId and niceId. NiceId is a readable ID for the resource and unique on a per org basis.",
tags: [OpenAPITags.PublicResourcePolicy],
tags: [OpenAPITags.Org, OpenAPITags.Policy],
request: {
params: z.object({
orgId: z.string(),
@@ -182,20 +182,7 @@ registry.registerPath({
method: "get",
path: "/resource-policy/{resourcePolicyId}",
description: "Get a resource policy by its resourcePolicyId.",
tags: [OpenAPITags.PublicResourcePolicyLegacy],
request: {
params: z.object({
resourcePolicyId: z.number()
})
},
responses: {}
});
registry.registerPath({
method: "get",
path: "/public-resource-policy/{resourcePolicyId}",
description: "Get a resource policy by its resourcePolicyId.",
tags: [OpenAPITags.PublicResourcePolicy],
tags: [OpenAPITags.Policy],
request: {
params: z.object({
resourcePolicyId: z.number()
@@ -40,66 +40,7 @@ registry.registerPath({
path: "/resource-policy/{resourceId}/access-control",
description:
"Set access control users for a resource policy, including SSO, users, roles, Identity provider.",
tags: [OpenAPITags.PublicResourcePolicyLegacy],
request: {
params: setResourcePolicyAccessControlParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyAcccessControlBodySchema
}
}
}
},
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.PublicResourcePolicy, OpenAPITags.User],
request: {
params: setResourcePolicyAccessControlParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyAcccessControlBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "put",
path: "/resource-policy/{resourceId}/access-control",
description:
"Set access control users for a resource policy, including SSO, users, roles, Identity provider. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicyLegacy],
request: {
params: setResourcePolicyAccessControlParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyAcccessControlBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "put",
path: "/public-resource-policy/{resourceId}/access-control",
description:
"Set access control users for a resource policy, including SSO, users, roles, Identity provider. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicy, OpenAPITags.User],
tags: [OpenAPITags.Policy, OpenAPITags.User],
request: {
params: setResourcePolicyAccessControlParamsSchema,
body: {
@@ -24,71 +24,12 @@ const setResourcePolicyHeaderAuthBodySchema = z.strictObject({
.nullable()
});
registry.registerPath({
method: "post",
path: "/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.PublicResourcePolicyLegacy],
request: {
params: setResourcePolicyHeaderAuthParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyHeaderAuthBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "post",
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.PublicResourcePolicy],
request: {
params: setResourcePolicyHeaderAuthParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyHeaderAuthBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "put",
path: "/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. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicyLegacy],
request: {
params: setResourcePolicyHeaderAuthParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyHeaderAuthBodySchema
}
}
}
},
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. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicy],
"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: {
@@ -19,71 +19,12 @@ const setResourcePolicyPasswordBodySchema = z.strictObject({
password: z.string().min(4).max(100).nullable()
});
registry.registerPath({
method: "post",
path: "/resource-policy/{resourcePolicyId}/password",
description:
"Set the password for a resource policy. Setting the password to null will remove it.",
tags: [OpenAPITags.PublicResourcePolicyLegacy],
request: {
params: setResourcePolicyPasswordParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyPasswordBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "post",
path: "/public-resource-policy/{resourcePolicyId}/password",
description:
"Set the password for a resource policy. Setting the password to null will remove it.",
tags: [OpenAPITags.PublicResourcePolicy],
request: {
params: setResourcePolicyPasswordParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyPasswordBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "put",
path: "/resource-policy/{resourcePolicyId}/password",
description:
"Set the password for a resource policy. Setting the password to null will remove it. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicyLegacy],
request: {
params: setResourcePolicyPasswordParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyPasswordBodySchema
}
}
}
},
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. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicy],
"Set the password for a resource policy. Setting the password to null will remove it.",
tags: [OpenAPITags.Policy],
request: {
params: setResourcePolicyPasswordParamsSchema,
body: {
@@ -22,71 +22,12 @@ const setResourcePolicyPincodeBodySchema = z.strictObject({
.or(z.null())
});
registry.registerPath({
method: "post",
path: "/resource-policy/{resourcePolicyId}/pincode",
description:
"Set the PIN code for a resource policy. Setting the PIN code to null will remove it.",
tags: [OpenAPITags.PublicResourcePolicyLegacy],
request: {
params: setResourcePolicyPincodeParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyPincodeBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "post",
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.PublicResourcePolicy],
request: {
params: setResourcePolicyPincodeParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyPincodeBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "put",
path: "/resource-policy/{resourcePolicyId}/pincode",
description:
"Set the PIN code for a resource policy. Setting the PIN code to null will remove it. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicyLegacy],
request: {
params: setResourcePolicyPincodeParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyPincodeBodySchema
}
}
}
},
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. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicy],
"Set the PIN code for a resource policy. Setting the PIN code to null will remove it.",
tags: [OpenAPITags.Policy],
request: {
params: setResourcePolicyPincodeParamsSchema,
body: {
@@ -42,71 +42,12 @@ const setResourcePolicyRulesParamsSchema = z.strictObject({
resourcePolicyId: z.string().transform(Number).pipe(z.int().positive())
});
registry.registerPath({
method: "post",
path: "/resource-policy/{resourcePolicyId}/rules",
description:
"Set all rules for a resource policy at once. This will replace all existing rules.",
tags: [OpenAPITags.PublicResourcePolicyLegacy],
request: {
params: setResourcePolicyRulesParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyRulesBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "post",
path: "/public-resource-policy/{resourcePolicyId}/rules",
description:
"Set all rules for a resource policy at once. This will replace all existing rules.",
tags: [OpenAPITags.PublicResourcePolicy],
request: {
params: setResourcePolicyRulesParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyRulesBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "put",
path: "/resource-policy/{resourcePolicyId}/rules",
description:
"Set all rules for a resource policy at once. This will replace all existing rules. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicyLegacy],
request: {
params: setResourcePolicyRulesParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyRulesBodySchema
}
}
}
},
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. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicy],
"Set all rules for a resource policy at once. This will replace all existing rules.",
tags: [OpenAPITags.Policy],
request: {
params: setResourcePolicyRulesParamsSchema,
body: {
@@ -27,71 +27,12 @@ const setResourcePolicyWhitelistParamsSchema = z.strictObject({
resourcePolicyId: z.string().transform(Number).pipe(z.int().positive())
});
registry.registerPath({
method: "post",
path: "/resource-policy/{resourcePolicyId}/whitelist",
description:
"Set email whitelist for a resource policy. This will replace all existing emails.",
tags: [OpenAPITags.PublicResourcePolicyLegacy],
request: {
params: setResourcePolicyWhitelistParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyWhitelistBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "post",
path: "/public-resource-policy/{resourcePolicyId}/whitelist",
description:
"Set email whitelist for a resource policy. This will replace all existing emails.",
tags: [OpenAPITags.PublicResourcePolicy],
request: {
params: setResourcePolicyWhitelistParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyWhitelistBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "put",
path: "/resource-policy/{resourcePolicyId}/whitelist",
description:
"Set email whitelist for a resource policy. This will replace all existing emails. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicyLegacy],
request: {
params: setResourcePolicyWhitelistParamsSchema,
body: {
content: {
"application/json": {
schema: setResourcePolicyWhitelistBodySchema
}
}
}
},
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. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicy],
"Set email whitelist for a resource policy. This will replace all existing emails.",
tags: [OpenAPITags.Policy],
request: {
params: setResourcePolicyWhitelistParamsSchema,
body: {
+2 -58
View File
@@ -18,67 +18,11 @@ const updateResourcePolicyBodySchema = z.strictObject({
niceId: z.string().min(1).max(255).optional()
});
registry.registerPath({
method: "post",
path: "/resource-policy/{resourcePolicyId}",
description: "Update a resource policy.",
tags: [OpenAPITags.PublicResourcePolicy],
request: {
params: updateResourcePolicyParamsSchema,
body: {
content: {
"application/json": {
schema: updateResourcePolicyBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "post",
path: "/public-resource-policy/{resourcePolicyId}",
description: "Update a resource policy.",
tags: [OpenAPITags.PublicResourcePolicy],
request: {
params: updateResourcePolicyParamsSchema,
body: {
content: {
"application/json": {
schema: updateResourcePolicyBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "put",
path: "/resource-policy/{resourcePolicyId}",
description: "Update a resource policy. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicy],
request: {
params: updateResourcePolicyParamsSchema,
body: {
content: {
"application/json": {
schema: updateResourcePolicyBodySchema
}
}
}
},
responses: {}
});
registry.registerPath({
method: "put",
path: "/public-resource-policy/{resourcePolicyId}",
description: "Update a resource policy. Deprecated: use POST instead.",
deprecated: true,
tags: [OpenAPITags.PublicResourcePolicy],
description: "Update a resource policy.",
tags: [OpenAPITags.Org, OpenAPITags.Policy],
request: {
params: updateResourcePolicyParamsSchema,
body: {
@@ -34,39 +34,6 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/whitelist/add",
description: "Add a single email to the resource whitelist.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
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,
@@ -177,7 +144,10 @@ export async function addEmailToResourceWhitelist(
.from(resourcePolicyWhiteList)
.where(
and(
eq(resourcePolicyWhiteList.resourcePolicyId, policyId),
eq(
resourcePolicyWhiteList.resourcePolicyId,
policyId
),
eq(resourcePolicyWhiteList.email, email)
)
);
@@ -28,40 +28,6 @@ const addRoleToResourceParamsSchema = z
registry.registerPath({
method: "post",
path: "/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.PublicResourceLegacy],
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()
})
}
}
}
}
});
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],
@@ -28,40 +28,6 @@ const addUserToResourceParamsSchema = z
registry.registerPath({
method: "post",
path: "/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.PublicResourceLegacy],
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()
})
}
}
}
}
});
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],
-33
View File
@@ -153,39 +153,6 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/resource",
description: "Create a resource.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "put",
path: "/org/{orgId}/public-resource",
description: "Create a resource.",
tags: [OpenAPITags.PublicResource],
request: {
params: createResourceParamsSchema,
+38 -44
View File
@@ -9,14 +9,16 @@ import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import {
RESOURCE_RULE_MATCH_TYPES,
getResourceRuleValueValidationError
isValidCIDR,
isValidIP,
isValidUrlGlobPattern
} from "@server/lib/validators";
import { OpenAPITags, registry } from "@server/openApi";
import { isValidRegionId } from "@server/db/regions";
const createResourceRuleSchema = z.strictObject({
action: z.enum(["ACCEPT", "DROP", "PASS"]),
match: z.enum(RESOURCE_RULE_MATCH_TYPES),
match: z.enum(["CIDR", "IP", "PATH", "COUNTRY", "ASN", "REGION"]),
value: z.string().min(1),
priority: z.int(),
enabled: z.boolean().optional()
@@ -30,39 +32,6 @@ registry.registerPath({
method: "put",
path: "/resource/{resourceId}/rule",
description: "Create a resource rule.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "put",
path: "/public-resource/{resourceId}/rule",
description: "Create a resource rule.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Rule],
request: {
params: createResourceRuleParamsSchema,
@@ -149,14 +118,39 @@ export async function createResourceRule(
);
}
const valueValidationError = getResourceRuleValueValidationError(
match,
value
);
if (valueValidationError) {
return next(
createHttpError(HttpCode.BAD_REQUEST, valueValidationError)
);
if (match === "CIDR") {
if (!isValidCIDR(value)) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Invalid CIDR provided"
)
);
}
} else if (match === "IP") {
if (!isValidIP(value)) {
return next(
createHttpError(HttpCode.BAD_REQUEST, "Invalid IP provided")
);
}
} else if (match === "PATH") {
if (!isValidUrlGlobPattern(value)) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Invalid URL glob pattern provided"
)
);
}
} else if (match === "REGION") {
if (!isValidRegionId(value)) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Invalid region ID provided"
)
);
}
}
// Create the new resource rule
-26
View File
@@ -22,32 +22,6 @@ registry.registerPath({
method: "delete",
path: "/resource/{resourceId}",
description: "Delete a resource.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "delete",
path: "/public-resource/{resourceId}",
description: "Delete a resource.",
tags: [OpenAPITags.PublicResource],
request: {
params: deleteResourceSchema
@@ -19,32 +19,6 @@ registry.registerPath({
method: "delete",
path: "/resource/{resourceId}/rule/{ruleId}",
description: "Delete a resource rule.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "delete",
path: "/public-resource/{resourceId}/rule/{ruleId}",
description: "Delete a resource rule.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Rule],
request: {
params: deleteResourceRuleSchema
+1 -29
View File
@@ -63,7 +63,7 @@ registry.registerPath({
path: "/org/{orgId}/resource/{niceId}",
description:
"Get a resource by orgId and niceId. NiceId is a readable ID for the resource and unique on a per org basis.",
tags: [OpenAPITags.PublicResourceLegacy],
tags: [OpenAPITags.PublicResource],
request: {
params: z.object({
orgId: z.string(),
@@ -92,34 +92,6 @@ registry.registerPath({
method: "get",
path: "/resource/{resourceId}",
description: "Get a resource by resourceId.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "get",
path: "/public-resource/{resourceId}",
description: "Get a resource by resourceId.",
tags: [OpenAPITags.PublicResource],
request: {
params: z.object({
+2 -15
View File
@@ -25,21 +25,8 @@ export type GetResourcePoliciesResponse = {
registry.registerPath({
method: "get",
path: "/resource/{resourceId}/policies",
description:
"Get the inline and shared policies associated with a resource.",
tags: [OpenAPITags.PublicResourceLegacy],
request: {
params: getResourcePoliciesParamsSchema
},
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.PublicResourcePolicy],
description: "Get the inline and shared policies associated with a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Policy],
request: {
params: getResourcePoliciesParamsSchema
},
@@ -44,32 +44,6 @@ registry.registerPath({
method: "get",
path: "/resource/{resourceId}/whitelist",
description: "Get the whitelist of emails for a specific resource.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
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
@@ -33,34 +33,6 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/resources-names",
description: "List all resource names for an organization.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
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({
@@ -48,32 +48,6 @@ registry.registerPath({
method: "get",
path: "/resource/{resourceId}/roles",
description: "List all roles for a resource.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "get",
path: "/public-resource/{resourceId}/roles",
description: "List all roles for a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Role],
request: {
params: listResourceRolesSchema
@@ -71,33 +71,6 @@ registry.registerPath({
method: "get",
path: "/resource/{resourceId}/rules",
description: "List rules for a resource.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "get",
path: "/public-resource/{resourceId}/rules",
description: "List rules for a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Rule],
request: {
params: listResourceRulesParamsSchema,
@@ -38,32 +38,6 @@ registry.registerPath({
method: "get",
path: "/resource/{resourceId}/users",
description: "List all users for a resource.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "get",
path: "/public-resource/{resourceId}/users",
description: "List all users for a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.User],
request: {
params: listResourceUsersSchema
-29
View File
@@ -409,35 +409,6 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/resources",
description: "List resources for an organization.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "get",
path: "/org/{orgId}/public-resources",
description: "List resources for an organization.",
tags: [OpenAPITags.PublicResource],
request: {
params: z.object({
@@ -34,39 +34,6 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/whitelist/remove",
description: "Remove a single email from the resource whitelist.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
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,
@@ -176,7 +143,10 @@ export async function removeEmailFromResourceWhitelist(
.from(resourcePolicyWhiteList)
.where(
and(
eq(resourcePolicyWhiteList.resourcePolicyId, policyId),
eq(
resourcePolicyWhiteList.resourcePolicyId,
policyId
),
eq(resourcePolicyWhiteList.email, email)
)
);
@@ -194,7 +164,10 @@ export async function removeEmailFromResourceWhitelist(
.delete(resourcePolicyWhiteList)
.where(
and(
eq(resourcePolicyWhiteList.resourcePolicyId, policyId),
eq(
resourcePolicyWhiteList.resourcePolicyId,
policyId
),
eq(resourcePolicyWhiteList.email, email)
)
);
@@ -29,39 +29,6 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/roles/remove",
description: "Remove a single role from a resource.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
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,
@@ -29,39 +29,6 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/users/remove",
description: "Remove a single user from a resource.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
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,
@@ -29,40 +29,6 @@ const setResourceAuthMethodsBodySchema = z.strictObject({
registry.registerPath({
method: "post",
path: "/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.PublicResourceLegacy],
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()
})
}
}
}
}
});
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],
@@ -27,40 +27,6 @@ const setResourceAuthMethodsBodySchema = z.strictObject({
registry.registerPath({
method: "post",
path: "/resource/{resourceId}/password",
description:
"Set the password for a resource. Setting the password to null will remove it.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
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],
@@ -27,40 +27,6 @@ const setResourceAuthMethodsBodySchema = z.strictObject({
registry.registerPath({
method: "post",
path: "/resource/{resourceId}/pincode",
description:
"Set the PIN code for a resource. Setting the PIN code to null will remove it.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
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],
@@ -21,40 +21,6 @@ const setResourceRolesParamsSchema = z.strictObject({
registry.registerPath({
method: "post",
path: "/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.PublicResourceLegacy],
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()
})
}
}
}
}
});
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],
@@ -21,40 +21,6 @@ const setUserResourcesParamsSchema = z.strictObject({
registry.registerPath({
method: "post",
path: "/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.PublicResourceLegacy],
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()
})
}
}
}
}
});
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],
@@ -35,40 +35,6 @@ const setResourceWhitelistParamsSchema = z.strictObject({
registry.registerPath({
method: "post",
path: "/resource/{resourceId}/whitelist",
description:
"Set email whitelist for a resource. This will replace all existing emails.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
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],
-36
View File
@@ -240,42 +240,6 @@ const updateRawResourceBodySchema = z
registry.registerPath({
method: "post",
path: "/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.PublicResourceLegacy],
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()
})
}
}
}
}
});
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],
+57 -46
View File
@@ -9,11 +9,12 @@ import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import {
RESOURCE_RULE_MATCH_TYPES,
getResourceRuleValueValidationError,
ResourceRuleMatchType
isValidCIDR,
isValidIP,
isValidUrlGlobPattern
} from "@server/lib/validators";
import { OpenAPITags, registry } from "@server/openApi";
import { isValidRegionId } from "@server/db/regions";
// Define Zod schema for request parameters validation
const updateResourceRuleParamsSchema = z.strictObject({
@@ -21,7 +22,15 @@ const updateResourceRuleParamsSchema = z.strictObject({
resourceId: z.coerce.number().int().positive()
});
const resourceRuleMatchSchema = z.enum(RESOURCE_RULE_MATCH_TYPES);
const resourceRuleMatchSchema = z.enum([
"CIDR",
"IP",
"PATH",
"COUNTRY",
"COUNTRY_IS_NOT",
"ASN",
"REGION"
]);
// Define Zod schema for request body validation
const updateResourceRuleSchema = z
@@ -40,39 +49,6 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/rule/{ruleId}",
description: "Update a resource rule.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "post",
path: "/public-resource/{resourceId}/rule/{ruleId}",
description: "Update a resource rule.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Rule],
request: {
params: updateResourceRuleParamsSchema,
@@ -164,7 +140,14 @@ export async function updateResourceRule(
resource.resourcePolicyId === null &&
resource.defaultResourcePolicyId !== null;
let existingMatch: ResourceRuleMatchType;
let existingMatch:
| "CIDR"
| "IP"
| "PATH"
| "COUNTRY"
| "COUNTRY_IS_NOT"
| "ASN"
| "REGION";
if (isInlinePolicy) {
const policyId = resource.defaultResourcePolicyId!;
@@ -248,14 +231,42 @@ export async function updateResourceRule(
const { value } = updateData;
if (value !== undefined) {
const valueValidationError = getResourceRuleValueValidationError(
match,
value
);
if (valueValidationError) {
return next(
createHttpError(HttpCode.BAD_REQUEST, valueValidationError)
);
if (match === "CIDR") {
if (!isValidCIDR(value)) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Invalid CIDR provided"
)
);
}
} else if (match === "IP") {
if (!isValidIP(value)) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Invalid IP provided"
)
);
}
} else if (match === "PATH") {
if (!isValidUrlGlobPattern(value)) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Invalid URL glob pattern provided"
)
);
}
} else if (match === "REGION") {
if (!isValidRegionId(value)) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Invalid region ID provided"
)
);
}
}
}
+1 -1
View File
@@ -177,7 +177,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/sites",
description: "List all sites in an organization",
tags: [OpenAPITags.Site],
tags: [OpenAPITags.Org, OpenAPITags.Site],
request: {
params: listSitesParamsSchema,
query: listSitesSchema
@@ -31,40 +31,6 @@ const addClientToSiteResourceParamsSchema = z
registry.registerPath({
method: "post",
path: "/site-resource/{siteResourceId}/clients/add",
description:
"Add a single client to a site resource. Clients with a userId cannot be added.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
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],
@@ -33,39 +33,6 @@ registry.registerPath({
method: "post",
path: "/site-resource/{siteResourceId}/roles/add",
description: "Add a single role to a site resource.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
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,
@@ -33,39 +33,6 @@ registry.registerPath({
method: "post",
path: "/site-resource/{siteResourceId}/users/add",
description: "Add a single user to a site resource.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
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,
@@ -38,39 +38,6 @@ registry.registerPath({
method: "post",
path: "/client/{clientId}/site-resources",
description: "Add a machine client to multiple site resources at once.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
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,
@@ -207,39 +207,6 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/site-resource",
description: "Create a new site resource.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "put",
path: "/org/{orgId}/private-resource",
description: "Create a new site resource.",
tags: [OpenAPITags.PrivateResource],
request: {
params: createSiteResourceParamsSchema,
@@ -27,32 +27,6 @@ registry.registerPath({
method: "delete",
path: "/site-resource/{siteResourceId}",
description: "Delete a site resource.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "delete",
path: "/private-resource/{siteResourceId}",
description: "Delete a site resource.",
tags: [OpenAPITags.PrivateResource],
request: {
params: deleteSiteResourceParamsSchema
@@ -57,36 +57,6 @@ registry.registerPath({
method: "get",
path: "/site-resource/{siteResourceId}",
description: "Get a specific site resource by siteResourceId.",
tags: [OpenAPITags.PrivateResourceLegacy],
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: "/private-resource/{siteResourceId}",
description: "Get a specific site resource by siteResourceId.",
tags: [OpenAPITags.PrivateResource],
request: {
params: z.object({
@@ -230,33 +230,6 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/site-resources",
description: "List all site resources for an organization.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "get",
path: "/org/{orgId}/private-resources",
description: "List all site resources for an organization.",
tags: [OpenAPITags.PrivateResource],
request: {
params: listAllSiteResourcesByOrgParamsSchema,
@@ -39,32 +39,6 @@ registry.registerPath({
method: "get",
path: "/site-resource/{siteResourceId}/clients",
description: "List all clients for a site resource.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
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
@@ -40,32 +40,6 @@ registry.registerPath({
method: "get",
path: "/site-resource/{siteResourceId}/roles",
description: "List all roles for a site resource.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
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
@@ -43,32 +43,6 @@ registry.registerPath({
method: "get",
path: "/site-resource/{siteResourceId}/users",
description: "List all users for a site resource.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
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
@@ -67,33 +67,6 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/site/{siteId}/resources",
description: "List site resources for a site.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "get",
path: "/org/{orgId}/site/{siteId}/private-resources",
description: "List site resources for a site.",
tags: [OpenAPITags.PrivateResource],
request: {
params: listSiteResourcesParamsSchema,
@@ -31,40 +31,6 @@ const removeClientFromSiteResourceParamsSchema = z
registry.registerPath({
method: "post",
path: "/site-resource/{siteResourceId}/clients/remove",
description:
"Remove a single client from a site resource. Clients with a userId cannot be removed.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
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],
@@ -33,39 +33,6 @@ registry.registerPath({
method: "post",
path: "/site-resource/{siteResourceId}/roles/remove",
description: "Remove a single role from a site resource.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
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,
@@ -33,39 +33,6 @@ registry.registerPath({
method: "post",
path: "/site-resource/{siteResourceId}/users/remove",
description: "Remove a single user from a site resource.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
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,
@@ -31,40 +31,6 @@ const setSiteResourceClientsParamsSchema = z
registry.registerPath({
method: "post",
path: "/site-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.PrivateResourceLegacy],
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()
})
}
}
}
}
});
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],
@@ -32,40 +32,6 @@ const setSiteResourceRolesParamsSchema = z
registry.registerPath({
method: "post",
path: "/site-resource/{siteResourceId}/roles",
description:
"Set roles for a site resource. This will replace all existing roles.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
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],
@@ -33,40 +33,6 @@ const setSiteResourceUsersParamsSchema = z
registry.registerPath({
method: "post",
path: "/site-resource/{siteResourceId}/users",
description:
"Set users for a site resource. This will replace all existing users.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
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],
@@ -213,39 +213,6 @@ registry.registerPath({
method: "post",
path: "/site-resource/{siteResourceId}",
description: "Update a site resource.",
tags: [OpenAPITags.PrivateResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "post",
path: "/private-resource/{siteResourceId}",
description: "Update a site resource.",
tags: [OpenAPITags.PrivateResource],
request: {
params: updateSiteResourceParamsSchema,
-33
View File
@@ -93,39 +93,6 @@ registry.registerPath({
method: "put",
path: "/resource/{resourceId}/target",
description: "Create a target for a resource.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "put",
path: "/public-resource/{resourceId}/target",
description: "Create a target for a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Target],
request: {
params: createTargetParamsSchema,
-27
View File
@@ -92,33 +92,6 @@ registry.registerPath({
method: "get",
path: "/resource/{resourceId}/targets",
description: "List targets for a resource.",
tags: [OpenAPITags.PublicResourceLegacy],
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()
})
}
}
}
}
});
registry.registerPath({
method: "get",
path: "/public-resource/{resourceId}/targets",
description: "List targets for a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Target],
request: {
params: listTargetsParamsSchema,
+1 -25
View File
@@ -1,6 +1,6 @@
"use client";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import {
@@ -43,12 +43,10 @@ import {
CheckCircle2,
ChevronsUpDown,
ExternalLink,
Globe,
KeyRound,
Zap
} from "lucide-react";
import { useTranslations } from "next-intl";
import Link from "next/link";
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
import { usePaidStatus } from "@/hooks/usePaidStatus";
import { TierFeature, tierMatrix } from "@server/lib/billing/tierMatrix";
@@ -496,28 +494,6 @@ export default function DomainPicker({
const hasMoreProvided =
sortedAvailableOptions.length > providedDomainsShown;
const noDomainsAvailable =
!loadingDomains &&
organizationDomains.length === 0 &&
(build === "oss" || hideFreeDomain || requiresPaywall);
if (noDomainsAvailable) {
return (
<Alert>
<Globe className="h-4 w-4" />
<AlertTitle>{t("domainPickerNoDomainsAvailableTitle")}</AlertTitle>
<AlertDescription className="space-y-3">
<p>{t("domainPickerNoDomainsAvailableDescription")}</p>
<Button asChild size="sm" variant="outline">
<Link href={`/${orgId}/settings/domains`}>
{t("domainPickerNoDomainsAvailableAction")}
</Link>
</Button>
</AlertDescription>
</Alert>
);
}
return (
<div className="space-y-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">