Skip to content

Commit 4d4c1e5

Browse files
authored
Merge pull request #1673 from rocket-admin/backend_ceard_permissions_priority
feat: refactor authorization logic to load policies per group and improve error handling
2 parents d3db0ad + 47d2ae8 commit 4d4c1e5

1 file changed

Lines changed: 24 additions & 29 deletions

File tree

backend/src/entities/cedar-authorization/cedar-authorization.service.ts

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -186,47 +186,42 @@ export class CedarAuthorizationService implements ICedarAuthorizationService, On
186186
const userGroups = await this.globalDbContext.groupRepository.findAllUserGroupsInConnection(connectionId, userId);
187187
if (userGroups.length === 0) return false;
188188

189-
const userGroupIds = userGroups.map((g) => g.id);
190-
const policies = await this.loadPoliciesForUser(connectionId, userId, userGroupIds);
191-
if (!policies) return false;
189+
const groupPolicies = await this.loadPoliciesPerGroup(connectionId, userGroups);
190+
if (groupPolicies.length === 0) return false;
192191

193192
const entities = buildCedarEntities(userId, userGroups, connectionId, tableName, dashboardId);
194193

195-
const call = {
196-
principal: { type: CEDAR_USER_TYPE, id: userId },
197-
action: { type: CEDAR_ACTION_TYPE, id: action },
198-
resource: { type: resourceType as string, id: resourceId },
199-
context: {},
200-
policies: { staticPolicies: policies },
201-
entities: entities,
202-
schema: this.schema,
203-
};
204-
205-
const result = cedarWasm.isAuthorized(call as Parameters<typeof cedarWasm.isAuthorized>[0]);
206-
if (result.type === 'success') {
207-
return result.response.decision === 'allow';
194+
for (const policy of groupPolicies) {
195+
const call = {
196+
principal: { type: CEDAR_USER_TYPE, id: userId },
197+
action: { type: CEDAR_ACTION_TYPE, id: action },
198+
resource: { type: resourceType as string, id: resourceId },
199+
context: {},
200+
policies: { staticPolicies: policy },
201+
entities: entities,
202+
schema: this.schema,
203+
};
204+
205+
const result = cedarWasm.isAuthorized(call as Parameters<typeof cedarWasm.isAuthorized>[0]);
206+
if (result.type === 'success') {
207+
if (result.response.decision === 'allow') {
208+
return true;
209+
}
210+
} else {
211+
this.logger.warn(`Cedar authorization error for group policy: ${JSON.stringify(result.errors)}`);
212+
}
208213
}
209214

210-
this.logger.warn(`Cedar authorization error: ${JSON.stringify(result.errors)}`);
211215
return false;
212216
}
213217

214-
private async loadPoliciesForUser(connectionId: string, userId: string, userGroupIds: string[]): Promise<string | null> {
215-
const cached = Cacher.getCedarPolicyCache(connectionId, userId);
216-
if (cached !== null) return cached;
217-
218+
private async loadPoliciesPerGroup(connectionId: string, userGroups: Array<GroupEntity>): Promise<string[]> {
218219
const groups = await this.globalDbContext.groupRepository.findAllGroupsInConnection(connectionId);
219-
const userGroupIdSet = new Set(userGroupIds);
220-
const policyTexts = groups
220+
const userGroupIdSet = new Set(userGroups.map((g) => g.id));
221+
return groups
221222
.filter((g) => userGroupIdSet.has(g.id))
222223
.map((g) => g.cedarPolicy)
223224
.filter(Boolean);
224-
225-
if (policyTexts.length === 0) return null;
226-
227-
const combined = policyTexts.join('\n\n');
228-
Cacher.setCedarPolicyCache(connectionId, userId, combined);
229-
return combined;
230225
}
231226

232227
private async assertUserNotSuspended(userId: string): Promise<void> {

0 commit comments

Comments
 (0)