Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions backend/src/entities/cedar-authorization/cedar-policy-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ function extractPermitStatements(policyText: string): ParsedPermitStatement[] {

let i = permitIndex + permitKeyword.length;
// Skip whitespace after "permit"
while (i < policyText.length && (policyText[i] === ' ' || policyText[i] === '\t' || policyText[i] === '\n' || policyText[i] === '\r')) {
while (
i < policyText.length &&
(policyText[i] === ' ' || policyText[i] === '\t' || policyText[i] === '\n' || policyText[i] === '\r')
) {
i++;
}

Expand All @@ -122,7 +125,10 @@ function extractPermitStatements(policyText: string): ParsedPermitStatement[] {
const body = policyText.slice(bodyStart, i);
// Skip past ')' and optional whitespace, expect ';'
let j = i + 1;
while (j < policyText.length && (policyText[j] === ' ' || policyText[j] === '\t' || policyText[j] === '\n' || policyText[j] === '\r')) {
while (
j < policyText.length &&
(policyText[j] === ' ' || policyText[j] === '\t' || policyText[j] === '\n' || policyText[j] === '\r')
) {
j++;
}

Expand Down
22 changes: 17 additions & 5 deletions frontend/src/app/lib/cedar-policy-items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,7 @@ export function policyItemsToCedarPolicy(items: CedarPolicyItem[], connectionId:
return policies.join('\n\n');
}

const actionRef =
item.action === 'table:*' || item.action === 'dashboard:*'
? `action like RocketAdmin::Action::"${item.action}"`
: `action == RocketAdmin::Action::"${item.action}"`;
const actionRef = buildActionRef(item.action);
let resource: string;

if (item.action.startsWith('table:')) {
Expand All @@ -154,9 +151,24 @@ export function policyItemsToCedarPolicy(items: CedarPolicyItem[], connectionId:
return policies.join('\n\n');
}

const TABLE_ACTIONS = ['table:read', 'table:add', 'table:edit', 'table:delete'];
const DASHBOARD_ACTIONS = ['dashboard:read', 'dashboard:create', 'dashboard:edit', 'dashboard:delete'];

function buildActionRef(action: string): string {
if (action === 'table:*') {
const list = TABLE_ACTIONS.map((a) => `RocketAdmin::Action::"${a}"`).join(', ');
return `action in [${list}]`;
}
if (action === 'dashboard:*') {
const list = DASHBOARD_ACTIONS.map((a) => `RocketAdmin::Action::"${a}"`).join(', ');
return `action in [${list}]`;
}
return `action == RocketAdmin::Action::"${action}"`;
}

function buildResourceRef(type: string, connectionId: string, id: string | undefined): string {
if (id === '*') {
return `resource like RocketAdmin::${type}::"${connectionId}/*"`;
return `resource`;
}
return `resource == RocketAdmin::${type}::"${connectionId}/${id}"`;
}
22 changes: 17 additions & 5 deletions frontend/src/app/lib/cedar-policy-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { CedarPolicyItem } from './cedar-policy-items';

interface ParsedPermitStatement {
action: string | null;
actions: string[] | null;
resourceType: string | null;
resourceId: string | null;
isWildcard: boolean;
Expand Down Expand Up @@ -225,12 +226,18 @@ function extractPermitStatements(policyText: string): ParsedPermitStatement[] {
}
}

return results;
return results.flatMap(expandActionIn);
}

function expandActionIn(stmt: ParsedPermitStatement): ParsedPermitStatement[] {
if (!stmt.actions || stmt.actions.length === 0) return [stmt];
return stmt.actions.map((action) => ({ ...stmt, action, actions: null }));
}

function parsePermitBody(body: string): ParsedPermitStatement {
const result: ParsedPermitStatement = {
action: null,
actions: null,
resourceType: null,
resourceId: null,
isWildcard: false,
Expand All @@ -240,9 +247,14 @@ function parsePermitBody(body: string): ParsedPermitStatement {
if (actionMatch) {
result.action = actionMatch[1];
} else {
const actionClause = body.match(/,\s*(action)\s*,/);
if (actionClause) {
result.isWildcard = true;
const actionInMatch = body.match(/action\s+in\s*\[([^\]]+)\]/);
if (actionInMatch) {
result.actions = [...actionInMatch[1].matchAll(/RocketAdmin::Action::"([^"]+)"/g)].map((m) => m[1]);
} else {
const actionClause = body.match(/,\s*(action)\s*,/);
if (actionClause) {
result.isWildcard = true;
}
}
}

Expand All @@ -261,7 +273,7 @@ function parsePermitBody(body: string): ParsedPermitStatement {
}

function extractResourceSuffix(resourceId: string | null, connectionId: string): string | null {
if (!resourceId) return null;
if (!resourceId) return '*';
const prefix = `${connectionId}/`;
if (resourceId.startsWith(prefix)) {
return resourceId.slice(prefix.length);
Expand Down
Loading