Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: custom root roles #3975

Merged
merged 11 commits into from
Jun 14, 2023
Merged

feat: custom root roles #3975

merged 11 commits into from
Jun 14, 2023

Conversation

nunogois
Copy link
Member

@nunogois nunogois commented Jun 13, 2023

About the changes

Implements custom root roles, encompassing a lot of different areas of the project, and slightly refactoring the current roles logic. It includes quite a clean up.

This feature itself is behind a flag: customRootRoles

This feature covers root roles in:

  • Users;
  • Service Accounts;
  • Groups;

Apologies in advance. I may have gotten a bit carried away 🙈

Roles

We now have a new admin tab called "Roles" where we can see all root roles and manage custom ones. We are not allowed to edit or remove predefined roles.
image
This meant slightly pushing away the existing roles to project-roles instead. One idea we want to explore in the future is to unify both types of roles in the UI instead of having 2 separate tabs. This includes modernizing project roles to fit more into our current design and decisions.

Hovering the permissions cell expands detailed information about the role:
image

Create and edit role

Here's how the role form looks like (create / edit):
image
Here I categorized permissions so it's easier to visualize and manage from a UX perspective.

I'm using the same endpoint as before. I tried to unify the logic and get rid of the projectRole specific hooks. What distinguishes custom root roles from custom project roles is the extra root-custom type we see on the payload. By default we assume custom (custom project role) instead, which should help in terms of backwards compatibility.

Delete role

When we delete a custom role we try to help the end user make an informed decision by listing all the entities which currently use this custom root role:
image
As mentioned in the screenshot, when deleting a custom role, we demote all entities associated with it to the predefined Viewer role.
EDIT: Apparently we currently block this from the API (access-service deleteRole) with a message:
image
What should the correct behavior be?

Role selector

I added a new easy-to-use role selector component that is present in:

  • Users
    image
  • Service Accounts
    image
  • Groups
    image

Role description

I also added a new role description component that you can see below the dropdown in the selector component, but it's also used to better describe each role in the respective tables:
image

I'm not listing all the permissions of predefined roles. Those simply show the description in the tooltip:
image

Role badge

Groups is a bit different, since it uses a list of cards, so I added yet another component - Role badge:
image

I'm using this same component on the profile tab:
image

Discussion points

  • Are we being defensive enough with the use of the flag? Should we cover more?
  • Are we breaking backwards compatibility in any way?
  • What should we do when removing a role? Block or demote?
  • Maybe some existing permission-related issues will surface with this change: Are we being specific enough with our permissions? A lot of places are simply checking for ADMIN;
  • We may want to get rid of the API roles coupling we have with the users and SAs and instead use the new hooks (e.g. useRoles) explicitly;
  • We should update the docs;
  • Maybe we could allow the user to add a custom role directly from the role selector component;

@vercel
Copy link

vercel bot commented Jun 13, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
unleash-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 14, 2023 1:31pm
unleash-monorepo-frontend ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 14, 2023 1:31pm

Copy link
Contributor

@gastonfournier gastonfournier left a comment

Choose a reason for hiding this comment

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

WIP some comments

src/lib/services/access-service.ts Outdated Show resolved Hide resolved
interface IRole {
id: number;
name: string;
project: string | null;
description: string;
type: string;
permissions?: IPermission[];
Copy link
Contributor

Choose a reason for hiding this comment

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

Here I'd add a new interface extending IRole, something like:

interface IRoleWithPermissions extends IRole {
    permissions: IPermission[];
}

Copy link
Contributor

@gastonfournier gastonfournier left a comment

Choose a reason for hiding this comment

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

I think this is good enough to merge and test. There's a couple of minor things but I don't think they're blockers

Comment on lines +31 to +35
<Route path="project-roles/new" element={<CreateProjectRole />} />
<Route
path="project-roles/:id/edit"
element={<EditProjectRole />}
/>
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if we should keep the same URL as before for project roles or just add a new one for root-roles? I see pros and cons with both approaches, the main concern is that we are changing the meaning of the existing resource (but this is not on the API level, so this should be fine)

Copy link
Member Author

Choose a reason for hiding this comment

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

Since the goal is to eventually merge both root roles and project roles on the same tab, I don't think we should prioritize this for now.

Comment on lines +79 to +93
const allChecked = rootPermissions.every(
(permission: IPermission) => checkedPermissionsCopy[permission.id]
);

if (allChecked) {
rootPermissions.forEach((permission: IPermission) => {
delete checkedPermissionsCopy[permission.id];
});
} else {
rootPermissions.forEach((permission: IPermission) => {
checkedPermissionsCopy[permission.id] = {
...permission,
};
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like a refactoring opportunity as this code is repeated in a couple of places

src/lib/services/access-service.ts Show resolved Hide resolved
const baseRole = {
...(await this.validateRole(role)),
roleType: CUSTOM_ROLE_TYPE,
roleType,
Copy link
Contributor

Choose a reason for hiding this comment

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

Note for the reviewers CUSTOM_PROJECT_ROLE_TYPE has currently the same value as CUSTOM_ROLE_TYPE had

Co-authored-by: Gastón Fournier <gaston@getunleash.io>
@nunogois nunogois merged commit bb026c0 into main Jun 14, 2023
17 checks passed
@nunogois nunogois deleted the feat-custom-root-roles branch June 14, 2023 13:40
nunogois added a commit that referenced this pull request Jun 15, 2023
https://linear.app/unleash/issue/2-1135/address-3975-pr-comments-by-refactoring-some-of-the-new-custom-root

This pull request addresses the majority of the comments raised in issue
#3975 and lays the groundwork for unifying roles. The idea is for
project roles to also be managed in the "Roles" tab, and several
components, such as `RoleForm` and the `useRoleForm` can potentially be
reused.

I'll leave the further investigation and implementation of unifying
roles to be addressed in a separate task.

As a mostly unrelated UI fix, this also adds an arrow to the tooltip in
the `RoleBadge` component.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

2 participants