Pull roles from resource policies

Fixes #3256
This commit is contained in:
Owen
2026-06-12 14:06:57 -07:00
parent d985bfd3a6
commit 471ae98204
2 changed files with 198 additions and 69 deletions

View File

@@ -1,6 +1,12 @@
import { db } from "@server/db";
import { and, eq, inArray } from "drizzle-orm";
import { roleResources, userResources } from "@server/db";
import { and, eq, inArray, isNull, or } from "drizzle-orm";
import {
rolePolicies,
roleResources,
resources,
userPolicies,
userResources
} from "@server/db";
export async function canUserAccessResource({
userId,
@@ -11,9 +17,14 @@ export async function canUserAccessResource({
resourceId: number;
roleIds: number[];
}): Promise<boolean> {
const roleResourceAccess =
const [
roleResourceAccess,
rolePolicyAccess,
userResourceAccess,
userPolicyAccess
] = await Promise.all([
roleIds.length > 0
? await db
? db
.select()
.from(roleResources)
.where(
@@ -23,26 +34,87 @@ export async function canUserAccessResource({
)
)
.limit(1)
: [];
if (roleResourceAccess.length > 0) {
return true;
}
const userResourceAccess = await db
.select()
.from(userResources)
.where(
and(
eq(userResources.userId, userId),
eq(userResources.resourceId, resourceId)
: [],
roleIds.length > 0
? db
.select({
roleId: rolePolicies.roleId,
resourcePolicyId: rolePolicies.resourcePolicyId
})
.from(rolePolicies)
.innerJoin(
resources,
// Shared policy wins; only use default policy when no shared
// policy is assigned to the resource.
or(
eq(
resources.resourcePolicyId,
rolePolicies.resourcePolicyId
),
and(
isNull(resources.resourcePolicyId),
eq(
resources.defaultResourcePolicyId,
rolePolicies.resourcePolicyId
)
)
)
)
.where(
and(
eq(resources.resourceId, resourceId),
inArray(rolePolicies.roleId, roleIds)
)
)
.limit(1)
: [],
db
.select()
.from(userResources)
.where(
and(
eq(userResources.userId, userId),
eq(userResources.resourceId, resourceId)
)
)
)
.limit(1);
.limit(1),
db
.select({
userId: userPolicies.userId,
resourcePolicyId: userPolicies.resourcePolicyId
})
.from(userPolicies)
.innerJoin(
resources,
// Shared policy wins; only use default policy when no shared
// policy is assigned to the resource.
or(
eq(
resources.resourcePolicyId,
userPolicies.resourcePolicyId
),
and(
isNull(resources.resourcePolicyId),
eq(
resources.defaultResourcePolicyId,
userPolicies.resourcePolicyId
)
)
)
)
.where(
and(
eq(resources.resourceId, resourceId),
eq(userPolicies.userId, userId)
)
)
.limit(1)
]);
if (userResourceAccess.length > 0) {
return true;
}
return false;
return (
roleResourceAccess.length > 0 ||
rolePolicyAccess.length > 0 ||
userResourceAccess.length > 0 ||
userPolicyAccess.length > 0
);
}