Compare commits

...

2 Commits

Author SHA1 Message Date
Owen d47449b082 Add notes about inline policy to api endpoints 2026-06-10 10:24:31 -07:00
Owen 665806dfe8 Add some documentation; pull the override values 2026-06-10 10:03:16 -07:00
7 changed files with 75 additions and 16 deletions
+1 -1
View File
@@ -984,7 +984,7 @@
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyOwnDescription": "This resource has its own authentication and access rules controls.",
"resourceSharedPolicyInheritedDescription": "This resource inherits authentication and access rules controls from <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource to add to the policy. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "Access Controls",
"resourceUsersRolesDescription": "Configure which users and roles can visit this resource",
+2 -1
View File
@@ -28,7 +28,8 @@ const addRoleToResourceParamsSchema = z
registry.registerPath({
method: "post",
path: "/resource/{resourceId}/roles/add",
description: "Add a single role to a resource.",
description:
"Add a single role to a resource. When the resource has an inline policy defined (no shared resource policy assigned), the role is added to the inline policy instead of directly to the resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Role],
request: {
params: addRoleToResourceParamsSchema,
+2 -1
View File
@@ -28,7 +28,8 @@ const addUserToResourceParamsSchema = z
registry.registerPath({
method: "post",
path: "/resource/{resourceId}/users/add",
description: "Add a single user to a resource.",
description:
"Add a single user to a resource. When the resource has an inline policy defined (no shared resource policy assigned), the user is added to the inline policy instead of directly to the resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.User],
request: {
params: addUserToResourceParamsSchema,
+33 -5
View File
@@ -1,4 +1,4 @@
import { db, resources } from "@server/db";
import { db, resourcePolicies, resources } from "@server/db";
import response from "@server/lib/response";
import stoi from "@server/lib/stoi";
import logger from "@server/logger";
@@ -41,6 +41,15 @@ async function query(resourceId?: number, niceId?: string, orgId?: string) {
}
}
async function queryInlinePolicy(resourcePolicyId: number) {
const [res] = await db
.select()
.from(resourcePolicies)
.where(eq(resourcePolicies.resourcePolicyId, resourcePolicyId))
.limit(1);
return res;
}
export type GetResourceResponse = Omit<
NonNullable<Awaited<ReturnType<typeof query>>>,
"headers"
@@ -132,12 +141,31 @@ export async function getResource(
);
}
const isInlinePolicy =
resource.resourcePolicyId === null &&
resource.defaultResourcePolicyId !== null;
let returnData = resource;
if (isInlinePolicy) {
// get the policy
const policy = await queryInlinePolicy(
resource.defaultResourcePolicyId!
);
returnData = {
...returnData,
sso: policy?.sso || null,
emailWhitelistEnabled: policy?.emailWhitelistEnabled || null,
applyRules: policy?.applyRules || null,
skipToIdpId: policy?.idpId || null
};
}
return response<GetResourceResponse>(res, {
data: {
...resource,
headers: resource.headers
? JSON.parse(resource.headers)
: resource.headers
...returnData,
headers: returnData.headers
? JSON.parse(returnData.headers)
: returnData.headers
},
success: true,
error: false,
+1 -1
View File
@@ -22,7 +22,7 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/roles",
description:
"Set roles for a resource. This will replace all existing roles.",
"Set roles for a resource. This will replace all existing roles. When the resource has an inline policy defined (no shared resource policy assigned), roles are set on the inline policy instead of directly on the resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.Role],
request: {
params: setResourceRolesParamsSchema,
+1 -1
View File
@@ -22,7 +22,7 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/users",
description:
"Set users for a resource. This will replace all existing users.",
"Set users for a resource. This will replace all existing users. When the resource has an inline policy defined (no shared resource policy assigned), users are set on the inline policy instead of directly on the resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.User],
request: {
params: setUserResourcesParamsSchema,
+35 -6
View File
@@ -66,16 +66,38 @@ const updateHttpResourceBodySchema = z
.optional(),
subdomain: z.string().nullable().optional(),
ssl: z.boolean().optional(),
sso: z.boolean().optional(),
sso: z
.boolean()
.optional()
.describe(
"When no shared resource policy is assigned (resourcePolicyId is null), updates the resource's inline policy. When a shared policy is assigned, this value overrides the shared policy for this resource."
),
blockAccess: z.boolean().optional(),
emailWhitelistEnabled: z.boolean().optional(),
applyRules: z.boolean().optional(),
emailWhitelistEnabled: z
.boolean()
.optional()
.describe(
"When no shared resource policy is assigned (resourcePolicyId is null), updates the resource's inline policy. When a shared policy is assigned, this value overrides the shared policy for this resource."
),
applyRules: z
.boolean()
.optional()
.describe(
"When no shared resource policy is assigned (resourcePolicyId is null), updates the resource's inline policy. When a shared policy is assigned, this value overrides the shared policy for this resource."
),
domainId: z.string().optional(),
enabled: z.boolean().optional(),
stickySession: z.boolean().optional(),
tlsServerName: z.string().nullable().optional(),
setHostHeader: z.string().nullable().optional(),
skipToIdpId: z.int().positive().nullable().optional(),
skipToIdpId: z
.int()
.positive()
.nullable()
.optional()
.describe(
"When no shared resource policy is assigned (resourcePolicyId is null), updates the resource's inline policy. When a shared policy is assigned, this value overrides the shared policy for this resource."
),
headers: z
.array(z.strictObject({ name: z.string(), value: z.string() }))
.nullable()
@@ -91,7 +113,13 @@ const updateHttpResourceBodySchema = z
pamMode: z.enum(["passthrough", "push"]).optional(),
authDaemonMode: z.enum(["site", "remote", "native"]).optional(),
authDaemonPort: z.int().min(1).max(65535).nullable().optional(),
resourcePolicyId: z.number().nullable().optional()
resourcePolicyId: z
.number()
.nullable()
.optional()
.describe(
"ID of the resource policy to apply to this resource. Set to null to remove the resource policy and fall back to the inline policy settings."
)
})
.refine((data) => Object.keys(data).length > 0, {
error: "At least one field must be provided for update"
@@ -211,7 +239,8 @@ const updateRawResourceBodySchema = z
registry.registerPath({
method: "post",
path: "/resource/{resourceId}",
description: "Update a resource.",
description:
"Update a resource. Policy fields (sso, mfa, pincode, password, whitelist) update the inline policy when no shared resource policy is assigned; when a shared policy is assigned those fields override the shared policy for this resource only.",
tags: [OpenAPITags.PublicResource],
request: {
params: updateResourceParamsSchema,