improvement(policies): policies UI update#5524
Conversation
…tions and migrate to v3 components
…date related components to v3
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
…les and improve accessibility
…project templates and identity sections
… RolePermissionsSection with UnstableAccordion for better policy management
…t and improve error path formatting
…omponents with v3 styles
Greptile SummaryThis PR updates the permissions/policies UI across role management, project templates, and member/identity privilege sections — migrating to v3 accordion components, replacing checkboxes with a multi-select, adding per-action condition validation, and improving validation error messaging. The overall direction is sound, but several issues need to be resolved before merging:
Confidence Score: 2/5
Important Files Changed
Last reviewed commit: 51fb482 |
frontend/src/pages/project/RoleDetailsBySlugPage/components/RolePermissionsSection.tsx
Outdated
Show resolved
Hide resolved
...emplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateEditRoleForm.tsx
Outdated
Show resolved
Hide resolved
...emberProjectAdditionalPrivilegeSection/MembershipProjectAdditionalPrivilegeModifySection.tsx
Outdated
Show resolved
Hide resolved
…eMemo dependencies
…mplates and member details sections
…ed modal handling
08ed617 to
022b663
Compare
…th dynamic conditions
… structure in ConditionsFields
…permission handling
…e permissions section
…for validation errors in project templates and privilege sections
…s for legacy actions in permission-fns
|
@greptileai re-review this PR and update the summary |
frontend/src/pages/project/RoleDetailsBySlugPage/components/ProjectRoleModifySection.utils.tsx
Outdated
Show resolved
Hide resolved
Additional Comments (6)
These test actions must be removed from the backend before merging, or the feature needs to be hidden behind a feature flag.
The Example: actions A allows // Current (buggy):
return actionsWithRestrictions.reduce<string[]>((acc, action) => {
const allowed = actionConditionsMap[action];
if (!allowed) return acc;
if (acc.length === 0) return allowed; // ← incorrectly fires after an empty intersection too
return acc.filter((cond) => allowed.includes(cond));
}, []);
// Fix: use a separate "initialized" flag or a null sentinel
let result: string[] | null = null;
for (const action of actionsWithRestrictions) {
const allowed = actionConditionsMap[action];
if (!allowed) continue;
result = result === null ? allowed : result.filter((cond) => allowed.includes(cond));
}
return result ?? allConditions;While only two test actions exist today, this function is designed to be general-purpose and will break as soon as a third restricted action is introduced.
The previous implementation used The new implementation moves to The net effect is: clicking "Discard" wipes the entire form instead of restoring the saved permissions. This same regression exists in The fix is to reset to the loaded data explicitly: onClick={() => {
if (role) reset({ ...role, permissions: rolePermission2Form(role.permissions) });
}}
The tooltip wrapper is rendered for every selected action chip even when const MultiValueWithTooltip = <T extends ActionOption>(props: MultiValueProps<T>) => {
const { data } = props;
return (
<Tooltip>
<TooltipTrigger asChild>
<div>
<components.MultiValue {...props} />
</div>
</TooltipTrigger>
- {data.description && <TooltipContent>{data.description}</TooltipContent>}
+ {data.description ? <TooltipContent>{data.description}</TooltipContent> : null}
</Tooltip>
);
};Also note: If
The old "Cancel" button called This means clicking "Discard" on an existing role template completely wipes the displayed permissions rather than discarding the unsaved edits. The fix should either restore onClick={() => {
if (role) reset({ ...role, permissions: rolePermission2Form(role.permissions) });
else onGoBack();
}}
Same pattern as the other forms. The form is initialized with: defaultValues: {
slug: "",
temporaryAccess: { isTemporary: false },
permissions: {}
}Calling Fix: onClick={() => {
if (privilegeDetails) {
reset({
...privilegeDetails,
permissions: rolePermission2Form(privilegeDetails.permissions),
temporaryAccess: privilegeDetails.isTemporary ? { ... } : { isTemporary: false }
});
}
}} |
…privilege sections to include role and privilege details
Additional Comments (6)
These test actions must be removed from the backend before merging, or the feature needs to be hidden behind a feature flag.
The Example: actions A allows // Current (buggy):
return actionsWithRestrictions.reduce<string[]>((acc, action) => {
const allowed = actionConditionsMap[action];
if (!allowed) return acc;
if (acc.length === 0) return allowed; // ← incorrectly fires after an empty intersection too
return acc.filter((cond) => allowed.includes(cond));
}, []);
// Fix: use a separate "initialized" flag or a null sentinel
let result: string[] | null = null;
for (const action of actionsWithRestrictions) {
const allowed = actionConditionsMap[action];
if (!allowed) continue;
result = result === null ? allowed : result.filter((cond) => allowed.includes(cond));
}
return result ?? allConditions;While only two test actions exist today, this function is designed to be general-purpose and will break as soon as a third restricted action is introduced.
The previous implementation used The new implementation moves to The net effect is: clicking "Discard" wipes the entire form instead of restoring the saved permissions. This same regression exists in The fix is to reset to the loaded data explicitly: onClick={() => {
if (role) reset({ ...role, permissions: rolePermission2Form(role.permissions) });
}}
The tooltip wrapper is rendered for every selected action chip even when const MultiValueWithTooltip = <T extends ActionOption>(props: MultiValueProps<T>) => {
const { data } = props;
return (
<Tooltip>
<TooltipTrigger asChild>
<div>
<components.MultiValue {...props} />
</div>
</TooltipTrigger>
- {data.description && <TooltipContent>{data.description}</TooltipContent>}
+ {data.description ? <TooltipContent>{data.description}</TooltipContent> : null}
</Tooltip>
);
};Also note: If
The old "Cancel" button called This means clicking "Discard" on an existing role template completely wipes the displayed permissions rather than discarding the unsaved edits. The fix should either restore onClick={() => {
if (role) reset({ ...role, permissions: rolePermission2Form(role.permissions) });
else onGoBack();
}}
Same pattern as the other forms. The form is initialized with: defaultValues: {
slug: "",
temporaryAccess: { isTemporary: false },
permissions: {}
}Calling Fix: onClick={() => {
if (privilegeDetails) {
reset({
...privilegeDetails,
permissions: rolePermission2Form(privilegeDetails.permissions),
temporaryAccess: privilegeDetails.isTemporary ? { ... } : { isTemporary: false }
});
}
}} |
…privilege sections to include role and privilege details
…to handle disallowed actions and improve error messaging
…enhance user feedback on selected actions
…on keys for actions across various subjects
…nal subjects and condition keys for enhanced clarity
…or messaging and styling adjustments
scott-ray-wilson
left a comment
There was a problem hiding this comment.
looks great overall! some comments and reminders for testing code
frontend/src/pages/project/RoleDetailsBySlugPage/components/ConditionsFields.tsx
Show resolved
Hide resolved
frontend/src/pages/project/RoleDetailsBySlugPage/components/ConditionsFields.tsx
Outdated
Show resolved
Hide resolved
frontend/src/pages/project/RoleDetailsBySlugPage/components/ProjectRoleModifySection.utils.tsx
Outdated
Show resolved
Hide resolved
frontend/src/pages/project/RoleDetailsBySlugPage/components/ProjectRoleModifySection.utils.tsx
Outdated
Show resolved
Hide resolved
frontend/src/pages/project/RoleDetailsBySlugPage/components/ProjectRoleModifySection.utils.tsx
Outdated
Show resolved
Hide resolved
frontend/src/pages/project/RoleDetailsBySlugPage/components/ProjectRoleModifySection.utils.tsx
Outdated
Show resolved
Hide resolved
frontend/src/pages/project/RoleDetailsBySlugPage/components/RolePermissionsSection.tsx
Outdated
Show resolved
Hide resolved
…lt values and reset functionality
frontend/src/pages/project/RoleDetailsBySlugPage/components/AddPoliciesButton.tsx
Outdated
Show resolved
Hide resolved
frontend/src/pages/project/RoleDetailsBySlugPage/components/ProjectRoleModifySection.utils.tsx
Outdated
Show resolved
Hide resolved
frontend/src/pages/project/RoleDetailsBySlugPage/components/ProjectRoleModifySection.utils.tsx
Outdated
Show resolved
Hide resolved
… clean up action allowed conditions
…ty and consistency in access management
Context
This PR updates the policies/permissions UI and improves permission condition handling across role management, project templates, and member/identity privilege sections.
UnstableAccordionfor policy management in roles, project templates, and privilege sectionsimportSecret,duplicateSecret) with per-action condition restrictionsuseWatchand optimizeduseMemofor permission handlingmenuPortalContainerReffor correct modal positioning in privilege sectionscheckForInvalidPermissionCombinationfor invalid permission combinationsTest actions:
importSecretandduplicateSecretare temporary test actions added to simplify API and UI testing for reviewers. They will be removed before merge.Screenshots
Project role:

Project role validation:

Read-only:

Additional privileges:

Project template:

Steps to verify the change
UI
Dynamic conditions (using test actions):
environmentforimportSecret;secretPathis not allowed).API
importSecretorduplicateSecretand allowed conditions (e.g.environmentonly) → 201.Documentation
internals/permissions/project-permissionsType
Checklist