Skip to content

Cedar policy editor#1667

Open
gugu wants to merge 8 commits intomainfrom
cedar-policy-editor
Open

Cedar policy editor#1667
gugu wants to merge 8 commits intomainfrom
cedar-policy-editor

Conversation

@gugu
Copy link
Contributor

@gugu gugu commented Mar 13, 2026

No description provided.

gugu and others added 3 commits March 13, 2026 14:06
Expose cedarPolicy through backend API (DTOs, responses, use cases) and
add Monaco-based code editor to group-add-dialog and group-name-edit-dialog
in the Angular frontend, allowing users to write Cedar authorization policies
when creating or editing user groups.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the old grid-based permissions form (PermissionsFormComponent) and
standalone permissions dialog (PermissionsAddDialogComponent) with a new
list-based CedarPolicyListComponent. Each policy is shown as a row with
add/edit/delete controls. Remove the "Configure permissions" button from
the users page since permissions are now managed inline in group dialogs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rom items

- Add "All tables" (*) option to table dropdowns in policy list editor
- Generate cedar policy directly from CedarPolicyItem[] via policyItemsToCedarPolicy,
  bypassing the Permissions intermediary to preserve wildcard resource refs
- Wildcard tables produce resource == RocketAdmin::Table::"connId/*"
- Parser handles wildcard table entries and applies them to all tables
- Fix dark theme contrast for table name and empty state text
- Remove "Cedar policy" labels from group dialogs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 13, 2026 20:40
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a Cedar policy editor workflow for user groups, replacing the legacy “permissions” dialog with a form/code-based Cedar policy editor and wiring cedarPolicy through the frontend and backend group APIs.

Changes:

  • Add Cedar policy UI: a policy list form editor + Monaco-based code editor, integrated into create/edit group dialogs.
  • Add frontend utilities for Cedar policy parsing and item↔policy transformations, plus a Monaco language definition for Cedar.
  • Extend backend group/connection DTOs and use-cases to accept and return cedarPolicy, and include it in group responses; remove the old permissions dialog UI.

Reviewed changes

Copilot reviewed 37 out of 37 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
frontend/src/app/services/users.service.ts Send cedarPolicy when creating/editing groups.
frontend/src/app/services/users.service.spec.ts Update request-body expectation to include cedarPolicy.
frontend/src/app/models/user.ts Add cedarPolicy field to UserGroup.
frontend/src/app/lib/cedar-policy-parser.ts New Cedar policy → permissions parser (frontend).
frontend/src/app/lib/cedar-policy-items.ts New helpers to convert permissions ↔ policy “items” ↔ Cedar text.
frontend/src/app/lib/cedar-policy-generator.ts New Cedar policy generator (currently unused).
frontend/src/app/lib/cedar-monaco-language.ts Register Monaco tokenization rules for Cedar.
frontend/src/app/components/users/users.component.ts Remove auto-opening legacy permissions dialog; adjust dialog widths and typings.
frontend/src/app/components/users/users.component.spec.ts Update dialog-width expectations; remove permissions-dialog test.
frontend/src/app/components/users/users.component.html Remove permissions button; add type="button" to non-submit buttons.
frontend/src/app/components/users/permissions-add-dialog/* Remove legacy permissions dialog component + tests + templates/styles.
frontend/src/app/components/users/group-name-edit-dialog/group-name-edit-dialog.component.ts Add Cedar policy editor (form/code modes) to “Edit group” dialog and send policy on save.
frontend/src/app/components/users/group-name-edit-dialog/group-name-edit-dialog.component.spec.ts Add tests around table loading and Cedar policy prepopulation/mode switching.
frontend/src/app/components/users/group-name-edit-dialog/group-name-edit-dialog.component.html Update dialog UI to include mode toggle + Cedar policy editor; adjust button types.
frontend/src/app/components/users/group-name-edit-dialog/group-name-edit-dialog.component.css Add layout styles for the policy editor area.
frontend/src/app/components/users/group-add-dialog/group-add-dialog.component.ts Add Cedar policy editor to “Create group” dialog and send policy on create.
frontend/src/app/components/users/group-add-dialog/group-add-dialog.component.spec.ts Add tests around table loading and mode switching; update create call expectation.
frontend/src/app/components/users/group-add-dialog/group-add-dialog.component.html Add mode toggle + Cedar policy editor UI; adjust button types.
frontend/src/app/components/users/group-add-dialog/group-add-dialog.component.css Add layout styles for the policy editor area.
frontend/src/app/components/users/cedar-policy-list/cedar-policy-list.component.ts New component for adding/editing/removing policy items in “form” mode.
frontend/src/app/components/users/cedar-policy-list/cedar-policy-list.component.spec.ts New tests for CedarPolicyListComponent.
frontend/src/app/components/users/cedar-policy-list/cedar-policy-list.component.html Template for policy item list + add/edit controls.
frontend/src/app/components/users/cedar-policy-list/cedar-policy-list.component.css Styles for policy list UI.
backend/src/entities/group/utils/biuld-found-group-response.dto.ts Include cedarPolicy in group response DTO builder.
backend/src/entities/group/use-cases/update-group-title.use.case.ts Accept optional cedarPolicy on title update; invalidate Cedar policy cache.
backend/src/entities/group/dto/update-group-title.dto.ts Add optional cedarPolicy to DTO.
backend/src/entities/group/dto/found-group-response.dto.ts Add optional cedarPolicy to group response DTO.
backend/src/entities/group/application/data-sctructures/found-user-groups.ds.ts Add optional cedarPolicy to group DS.
backend/src/entities/connection/utils/build-found-user-group-in-connection-dto.util.ts Include cedarPolicy in group-in-connection DTO.
backend/src/entities/connection/use-cases/create-group-in-connection.use.case.ts Accept optional cedarPolicy on group creation; invalidate Cedar policy cache.
backend/src/entities/connection/connection.controller.ts Pass cedarPolicy from request body into create-group use case; minor import formatting.
backend/src/entities/connection/application/dto/found-user-groups-in-connection.dto.ts Add optional cedarPolicy.
backend/src/entities/connection/application/dto/create-group-in-connection.dto.ts Add optional cedarPolicy to create-group DTO.
backend/src/entities/connection/application/data-structures/create-group-in-connection.ds.ts Add optional cedarPolicy to DS.
Comments suppressed due to low confidence (1)

frontend/src/app/components/users/users.component.spec.ts:31

  • compileComponents() is asynchronous, but this test setup does not await it (or return the Promise). That can make the suite flaky because tests may run before compilation finishes. Make the beforeEach async and await ...compileComponents(), or return the Promise from beforeEach.
		TestBed.configureTestingModule({
			imports: [MatSnackBarModule, MatDialogModule, Angulartics2Module.forRoot(), UsersComponent],
			providers: [provideHttpClient(), provideRouter([]), { provide: MatDialogRef, useValue: {} }],
		}).compileComponents();

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +39 to 43
savedGroup.cedarPolicy =
cedarPolicy ??
generateCedarPolicyForGroup(connectionId, false, {
connection: { connectionId, accessLevel: AccessLevelEnum.none },
group: { groupId: savedGroup.id, accessLevel: AccessLevelEnum.none },
Comment on lines +44 to +45
groupToUpdate.cedarPolicy = cedarPolicy;
Cacher.invalidateCedarPolicyCache(groupToUpdate.connection.id);
Comment on lines +113 to +116
if (mode === 'code') {
// Form → Code: convert policy items directly to cedar text
this.cedarPolicy = policyItemsToCedarPolicy(this.policyItems, this.connectionID, '__new__');
this.cedarPolicyModel = {
Comment on lines +58 to +62
.overrideComponent(GroupAddDialogComponent, {
remove: { imports: [CodeEditorModule] },
add: { imports: [MockCodeEditorComponent], schemas: [NO_ERRORS_SCHEMA] },
})
.compileComponents();
Comment on lines +10 to +14
export function parseCedarPolicy(
policyText: string,
connectionId: string,
groupId: string,
availableTables: TablePermission[],
Comment on lines +8 to +12
export const POLICY_ACTIONS = [
{ value: '*', label: 'Full access (all permissions)', needsTable: false },
{ value: 'connection:read', label: 'Connection: Read', needsTable: false },
{ value: 'connection:edit', label: 'Connection: Full access', needsTable: false },
{ value: 'group:read', label: 'Group: Read', needsTable: false },
Comment on lines +1 to +5
import { AccessLevel, Permissions } from '../models/user';

export function generateCedarPolicy(connectionId: string, permissions: Permissions): string {
const policies: string[] = [];
const connectionRef = `RocketAdmin::Connection::"${connectionId}"`;
Comment on lines +67 to +71
.overrideComponent(GroupNameEditDialogComponent, {
remove: { imports: [CodeEditorModule] },
add: { imports: [MockCodeEditorComponent], schemas: [NO_ERRORS_SCHEMA] },
})
.compileComponents();
gugu and others added 4 commits March 14, 2026 09:43
- Generate `resource like RocketAdmin::Table::"connId/*"` instead of `==`
- Update parser to recognize both `==` and `like` for resource matching

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Group actions into optgroups: General, Connection, Group, Table
- Add table:* action that expands to all four table permits
- Collapse per-table full access into single table:* policy item
- Use needsTable from POLICY_ACTIONS lookup instead of string prefix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rename "Full access" to "Full table access" for table:* action
- Generate single permit with action like RocketAdmin::Action::"table:*"
- Fix duplicate action == in permit template
- Parser handles table:* action and action like operator

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gugu
Copy link
Contributor Author

gugu commented Mar 16, 2026

blocked by #1668

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants