Pull the rules and the policy information

This commit is contained in:
Owen
2026-06-03 15:33:15 -07:00
parent 40125c717c
commit cc5bec1d83
3 changed files with 159 additions and 46 deletions

View File

@@ -36,7 +36,8 @@ import {
ResourcePolicyHeaderAuth ResourcePolicyHeaderAuth
} from "@server/db"; } from "@server/db";
import { alias } from "drizzle-orm/sqlite-core"; import { alias } from "drizzle-orm/sqlite-core";
import { and, eq, inArray, or, sql } from "drizzle-orm"; import { and, eq, inArray, isNull, or, sql } from "drizzle-orm";
import logger from "@server/logger";
export type ResourceWithAuth = { export type ResourceWithAuth = {
resource: Resource | null; resource: Resource | null;
@@ -44,6 +45,7 @@ export type ResourceWithAuth = {
password: ResourcePassword | ResourcePolicyPassword | null; password: ResourcePassword | ResourcePolicyPassword | null;
headerAuth: ResourceHeaderAuth | ResourcePolicyHeaderAuth | null; headerAuth: ResourceHeaderAuth | ResourcePolicyHeaderAuth | null;
headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null; headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null;
applyRules: boolean;
org: Org; org: Org;
}; };
@@ -213,9 +215,14 @@ export async function getResourceByDomain(
const effectivePolicyHeaderAuth = hasSharedPolicy const effectivePolicyHeaderAuth = hasSharedPolicy
? result.sharedPolicyHeaderAuth ? result.sharedPolicyHeaderAuth
: (result.defaultPolicyHeaderAuth ?? null); : (result.defaultPolicyHeaderAuth ?? null);
const effectiveApplyRules =
(hasSharedPolicy
? (result.sharedPolicy?.applyRules ?? false)
: (result.defaultPolicy?.applyRules ?? false)) ||
result.resources.applyRules;
return { return {
resource: result.resources, resource: { ...result.resources, applyRules: effectiveApplyRules }, // doing this for backward compatability so the remote nodes get the value as part of the resource struct
pincode: effectivePolicyPincode ?? result.resourcePincode, pincode: effectivePolicyPincode ?? result.resourcePincode,
password: effectivePolicyPassword ?? result.resourcePassword, password: effectivePolicyPassword ?? result.resourcePassword,
headerAuth: effectivePolicyHeaderAuth ?? result.resourceHeaderAuth, headerAuth: effectivePolicyHeaderAuth ?? result.resourceHeaderAuth,
@@ -227,6 +234,7 @@ export async function getResourceByDomain(
effectivePolicyHeaderAuth.extendedCompatibility effectivePolicyHeaderAuth.extendedCompatibility
} as ResourceHeaderAuthExtendedCompatibility) } as ResourceHeaderAuthExtendedCompatibility)
: result.resourceHeaderAuthExtendedCompatibility, : result.resourceHeaderAuthExtendedCompatibility,
applyRules: effectiveApplyRules,
org: result.orgs org: result.orgs
}; };
} }
@@ -290,7 +298,21 @@ export async function getRoleResourceAccess(
.from(rolePolicies) .from(rolePolicies)
.innerJoin( .innerJoin(
resources, resources,
eq(resources.resourcePolicyId, rolePolicies.resourcePolicyId) // 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( .where(
and( and(
@@ -330,7 +352,21 @@ export async function getUserResourceAccess(
.from(userPolicies) .from(userPolicies)
.innerJoin( .innerJoin(
resources, resources,
eq(resources.resourcePolicyId, userPolicies.resourcePolicyId) // 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( .where(
and( and(
@@ -368,9 +404,20 @@ export async function getResourceRules(
.from(resourcePolicyRules) .from(resourcePolicyRules)
.innerJoin( .innerJoin(
resources, resources,
// Shared policy wins; only use default policy when no shared
// policy is assigned to the resource.
or(
eq( eq(
resources.resourcePolicyId, resources.resourcePolicyId,
resourcePolicyRules.resourcePolicyId resourcePolicyRules.resourcePolicyId
),
and(
isNull(resources.resourcePolicyId),
eq(
resources.defaultResourcePolicyId,
resourcePolicyRules.resourcePolicyId
)
)
) )
) )
.where(eq(resources.resourceId, resourceId)) .where(eq(resources.resourceId, resourceId))

View File

@@ -60,7 +60,7 @@ import {
userOrgRoles, userOrgRoles,
roles roles
} from "@server/db"; } from "@server/db";
import { eq, and, inArray, isNotNull, ne, or, sql } from "drizzle-orm"; import { eq, and, inArray, isNotNull, isNull, ne, or, sql } from "drizzle-orm";
import { alias } from "drizzle-orm/sqlite-core"; import { alias } from "drizzle-orm/sqlite-core";
import { response } from "@server/lib/response"; import { response } from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
@@ -670,21 +670,28 @@ hybridRouter.get(
}); });
} }
const effectivePolicyPincode = const hasSharedPolicy = result.sharedPolicy !== null;
result.sharedPolicyPincode ??
result.defaultPolicyPincode ?? const effectivePolicyPincode = hasSharedPolicy
null; ? result.sharedPolicyPincode
const effectivePolicyPassword = : (result.defaultPolicyPincode ?? null);
result.sharedPolicyPassword ?? const effectivePolicyPassword = hasSharedPolicy
result.defaultPolicyPassword ?? ? result.sharedPolicyPassword
null; : (result.defaultPolicyPassword ?? null);
const effectivePolicyHeaderAuth = const effectivePolicyHeaderAuth = hasSharedPolicy
result.sharedPolicyHeaderAuth ?? ? result.sharedPolicyHeaderAuth
result.defaultPolicyHeaderAuth ?? : (result.defaultPolicyHeaderAuth ?? null);
null; const effectiveApplyRules =
(hasSharedPolicy
? (result.sharedPolicy?.applyRules ?? false)
: (result.defaultPolicy?.applyRules ?? false)) ||
result.resources.applyRules;
const resourceWithAuth: ResourceWithAuth = { const resourceWithAuth: ResourceWithAuth = {
resource: result.resources, resource: {
...result.resources,
applyRules: effectiveApplyRules
},
pincode: effectivePolicyPincode ?? result.resourcePincode, pincode: effectivePolicyPincode ?? result.resourcePincode,
password: effectivePolicyPassword ?? result.resourcePassword, password: effectivePolicyPassword ?? result.resourcePassword,
headerAuth: headerAuth:
@@ -1272,9 +1279,18 @@ hybridRouter.get(
.from(rolePolicies) .from(rolePolicies)
.innerJoin( .innerJoin(
resources, resources,
or(
eq( eq(
resources.resourcePolicyId, resources.resourcePolicyId,
rolePolicies.resourcePolicyId rolePolicies.resourcePolicyId
),
and(
isNull(resources.resourcePolicyId),
eq(
resources.defaultResourcePolicyId,
rolePolicies.resourcePolicyId
)
)
) )
) )
.where( .where(
@@ -1386,9 +1402,18 @@ hybridRouter.get(
.from(rolePolicies) .from(rolePolicies)
.innerJoin( .innerJoin(
resources, resources,
or(
eq( eq(
resources.resourcePolicyId, resources.resourcePolicyId,
rolePolicies.resourcePolicyId rolePolicies.resourcePolicyId
),
and(
isNull(resources.resourcePolicyId),
eq(
resources.defaultResourcePolicyId,
rolePolicies.resourcePolicyId
)
)
) )
) )
.where( .where(
@@ -1477,7 +1502,9 @@ hybridRouter.get(
); );
} }
const userResourceAccess = await db const [directUserAccess, viaPoliciesUserAccess] = await Promise.all(
[
db
.select() .select()
.from(userResources) .from(userResources)
.where( .where(
@@ -1486,10 +1513,41 @@ hybridRouter.get(
eq(userResources.resourceId, resourceId) eq(userResources.resourceId, resourceId)
) )
) )
.limit(1); .limit(1),
db
.select({
userId: userPolicies.userId,
resourcePolicyId: userPolicies.resourcePolicyId
})
.from(userPolicies)
.innerJoin(
resources,
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)
]
);
const result = const result =
userResourceAccess.length > 0 ? userResourceAccess[0] : null; directUserAccess[0] ?? viaPoliciesUserAccess[0] ?? null;
return response<typeof userResources.$inferSelect | null>(res, { return response<typeof userResources.$inferSelect | null>(res, {
data: result, data: result,
@@ -1580,9 +1638,18 @@ hybridRouter.get(
.from(resourcePolicyRules) .from(resourcePolicyRules)
.innerJoin( .innerJoin(
resources, resources,
or(
eq( eq(
resources.resourcePolicyId, resources.resourcePolicyId,
resourcePolicyRules.resourcePolicyId resourcePolicyRules.resourcePolicyId
),
and(
isNull(resources.resourcePolicyId),
eq(
resources.defaultResourcePolicyId,
resourcePolicyRules.resourcePolicyId
)
)
) )
) )
.where(eq(resources.resourceId, resourceId)) .where(eq(resources.resourceId, resourceId))

View File

@@ -144,6 +144,7 @@ export async function verifyResourceSession(
| ResourcePolicyHeaderAuth | ResourcePolicyHeaderAuth
| null; | null;
headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null; headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null;
applyRules: boolean;
org: Org; org: Org;
} }
| undefined = localCache.get(resourceCacheKey); | undefined = localCache.get(resourceCacheKey);
@@ -175,6 +176,7 @@ export async function verifyResourceSession(
const { const {
resource, resource,
applyRules,
pincode, pincode,
password, password,
headerAuth, headerAuth,
@@ -220,7 +222,7 @@ export async function verifyResourceSession(
} }
// check the rules // check the rules
if (resource.applyRules) { if (applyRules) {
const action = await checkRules( const action = await checkRules(
resource.resourceId, resource.resourceId,
clientIp, clientIp,
@@ -876,10 +878,7 @@ function allowed(
message: "Access allowed", message: "Access allowed",
status: HttpCode.OK status: HttpCode.OK
}; };
logger.debug( logger.debug("Access allowed, response data:", data);
"++++++++++++++++++++++++++++++++++Access allowed, response data:",
data
);
return response<VerifyUserResponse>(res, data); return response<VerifyUserResponse>(res, data);
} }