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: [UIE-8139] - IAM RBAC: add new assigned entities table component part 1 #11588

Conversation

aaleksee-akamai
Copy link
Contributor

@aaleksee-akamai aaleksee-akamai commented Jan 30, 2025

Description 📝

IAM RBAC - new assigned entities table component.

Changes 🔄

List any change(s) relevant to the reviewer.

  • Table for the assigned entities
  • Filtering roles

do not include (will be introduced in the next PR):

  • Any action in the action menu
  • Redirecting to specific entity page by clicking on the entity name

Target release date 🗓️

2/11/25 (dev)

Preview 📷

Include a screenshot or screen recording of the change.

🔒 Use the Mask Sensitive Data setting for security.

💡 Use <video src="" /> tag when including recordings in table.

Before After
Screenshot 2025-01-31 at 10 33 34 AM image

How to test 🧪

Prerequisites

(How to setup test environment)

  • Ensure the Identity and Access Beta flag is enabled in dev tools
  • Ensure the MSW is enabled in dev tools
  • Click on the any username in the users table and go to the tab Assigned Entities or click on the user's menu View Assigned Entities

Verification steps

(How to verify changes)

  • Confirm table renders.
  • Confirm table renders data according to the applied filters
Author Checklists

As an Author, to speed up the review process, I considered 🤔

👀 Doing a self review
❔ Our contribution guidelines
🤏 Splitting feature into small PRs
➕ Adding a changeset
🧪 Providing/improving test coverage
🔐 Removing all sensitive information from the code and PR description
🚩 Using a feature flag to protect the release
👣 Providing comprehensive reproduction steps
📑 Providing or updating our documentation
🕛 Scheduling a pair reviewing session
📱 Providing mobile support
♿ Providing accessibility support


  • I have read and considered all applicable items listed above.

As an Author, before moving this PR from Draft to Open, I confirmed ✅

  • All unit tests are passing
  • TypeScript compilation succeeded without errors
  • Code passes all linting rules

@aaleksee-akamai aaleksee-akamai requested a review from a team as a code owner January 30, 2025 13:43
@aaleksee-akamai aaleksee-akamai requested review from hkhalil-akamai and pmakode-akamai and removed request for a team January 30, 2025 13:43
@aaleksee-akamai aaleksee-akamai self-assigned this Jan 30, 2025
@aaleksee-akamai aaleksee-akamai force-pushed the UIE-8139-iam-rbac-assigned-entities-table-part-1 branch from 1ca7141 to f2f22e7 Compare January 30, 2025 13:45

export const StyledTypography = styled(Typography, {
label: 'StyledTypography',
})(({ theme }) => ({
color:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe we don't need it, as @jaalah-akamai mentioned earlier

Copy link

github-actions bot commented Jan 30, 2025

Coverage Report:
Base Coverage: 78.94%
Current Coverage: 78.94%

roles: EntitiesRole[] | RoleMap[];
}

export const getFilteredRoles = (
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have the same functionality in two components (AssignedRolesTable and AssignedEntitiesTable), with the only difference being the searchableFields. So, I’ve combined the logic for both components and passed searchableFields as a parameter

Copy link
Contributor

Choose a reason for hiding this comment

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

Could we make getSearchableFields an optional field in the options?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, we could make getSearchableFields optional, but for that, we need a default implementation of searchableFields. Right now, this function is only used in two components (that I mentioned above), so making it optional would add flexibility, but it’s worth considering whether it’s necessary at this stage. If we expect to expand its usage further, introducing a default getSearchableFields function could make sense. Otherwise, keeping it explicitly required for now might be a simpler and more controlled approach

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay. At least we should make it part of the options object, no need to have multiple arguments to this function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure, it makes sense, thanks @hkhalil-akamai

value?: string;
}

export const mapEntityTypes = (
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same situation here — the only difference is the ending

@cpathipa cpathipa requested review from cpathipa and removed request for pmakode-akamai January 30, 2025 14:48
@jaalah-akamai jaalah-akamai self-requested a review January 31, 2025 15:29
Comment on lines 146 to 152
<DebouncedSearchTextField
clearable
debounceTime={250}
hideLabel
label="Filter"
onSearch={setQuery}
placeholder="Search"
sx={{ marginRight: 2, width: 410 }}
value={query}
/>
Copy link
Contributor

Choose a reason for hiding this comment

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

Since the search doesn't involve any network requests, do we need to debounce it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yep, remove it, thanks

roles: EntitiesRole[] | RoleMap[];
}

export const getFilteredRoles = (
Copy link
Contributor

Choose a reason for hiding this comment

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

Okay. At least we should make it part of the options object, no need to have multiple arguments to this function.

@hkhalil-akamai
Copy link
Contributor

hkhalil-akamai commented Jan 31, 2025

Does this project have an API spec yet? I noticed that the return type of API getAccountResources is incorrect as the mocked response is an array of type IamAccountResource[].

Also, the accountResourcesFactory is not written according to convention. It should be defined as a single object of type IamAccountResource, not an array. The .buildList() factory method can be used to produce an array for the mock endpoint.

Copy link
Contributor

@jaalah-akamai jaalah-akamai left a comment

Choose a reason for hiding this comment

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

PR looks really good, nice job

The failing test is just due to the name change View User Roles > View Assigned Roles

},
];

const memoizedTableItems = React.useMemo(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would remove this useMemo all together. There's nothing in here that would greatly benefit from it. We wouldn't even need to worry about memoizing getFilteredRoles since that's a pure function and memoization is more for equality checks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cpathipa suggested using memo for the same logic in mine previous PR. So, there is a question - do we need to memoize this to avoid recalculating filtered roles on every render or not? Or maybe I got it wrong, and it needs to be done in a different way?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jaalah-akamai , @cpathipa , just circling back on this — would appreciate your thoughts. Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

I originally suggested using useMemo in the previous PR to avoid recalculating on every render. I think we are using map with a map there. The idea was to optimize performance, but if it's not providing significant benefits, I’m open to revisiting that decision.

if (resource) {
resourceRole.roles.forEach((r: RoleType) => {
result.push({
id: r + '-' + resourceRole.resource_id,
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: lets use template strings

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure, done


if (resource) {
resourceRole.roles.forEach((r: RoleType) => {
result.push({
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: using a map here would a little more straightforward

@aaleksee-akamai aaleksee-akamai force-pushed the UIE-8139-iam-rbac-assigned-entities-table-part-1 branch from f2f22e7 to bda1fdf Compare February 4, 2025 16:12

if (resource) {
result.push(
...resourceRole.roles.map((r: RoleType) => ({
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jaalah-akamai , please check if this is what you mean with using map

Copy link
Contributor

Choose a reason for hiding this comment

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

@aaleksee-akamai I was more saying that by using a map you don't need to have the results variable or push anything to the array since the map returns an array of the values already. Spreading the results of the map and pushing that into the array is redundant.

const addResourceNamesToRoles = (
  assignedRoles: IamUserPermissions,
  resources: IamAccountResource
): EntitiesRole[] => {
  const resourcesRoles = assignedRoles.resource_access;
  const resourcesArray: IamAccountResource[] = Object.values(resources);

  return resourcesRoles.flatMap((resourceRole: ResourceAccess) => {
    const resourceByType = resourcesArray.find(
      (r: IamAccountResource) => r.resource_type === resourceRole.resource_type
    );

    if (resourceByType) {
      const resource = resourceByType.resources.find(
        (res: Resource) => res.id === resourceRole.resource_id
      );

      if (resource) {
        return resourceRole.roles.map((r: RoleType) => ({
          id: r + '-' + resourceRole.resource_id,
          resource_id: resourceRole.resource_id,
          resource_name: resource.name,
          resource_type: resourceRole.resource_type,
          role_name: r,
        }));
      }
    }

    return [];
  });
};

},
];

const memoizedTableItems = React.useMemo(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I originally suggested using useMemo in the previous PR to avoid recalculating on every render. I think we are using map with a map there. The idea was to optimize performance, but if it's not providing significant benefits, I’m open to revisiting that decision.

@aaleksee-akamai aaleksee-akamai force-pushed the UIE-8139-iam-rbac-assigned-entities-table-part-1 branch from bda1fdf to 0d1b863 Compare February 7, 2025 10:47
@aaleksee-akamai aaleksee-akamai force-pushed the UIE-8139-iam-rbac-assigned-entities-table-part-1 branch from 0d1b863 to 72904ee Compare February 10, 2025 09:32
@linode-gh-bot
Copy link
Collaborator

Cloud Manager UI test results

🔺 1 failing test on test run #5 ↗︎

❌ Failing✅ Passing↪️ Skipped🕐 Duration
1 Failing500 Passing2 Skipped117m 51s

Details

Failing Tests
SpecTest
clone-linode.spec.tsclone linode » can clone a Linode from Linode details page

Troubleshooting

Use this command to re-run the failing tests:

yarn cy:run -s "cypress/e2e/core/linodes/clone-linode.spec.ts"

@jaalah-akamai jaalah-akamai added the Approved Multiple approvals and ready to merge! label Feb 10, 2025
@jaalah-akamai jaalah-akamai merged commit 531ac62 into linode:develop Feb 10, 2025
22 of 23 checks passed
Copy link

cypress bot commented Feb 10, 2025

Cloud Manager E2E    Run #7201

Run Properties:  status check passed Passed #7201  •  git commit 531ac62b3e: feat: [UIE-8139] - IAM RBAC: add new assigned entities table component part 1 (#...
Project Cloud Manager E2E
Branch Review develop
Run status status check passed Passed #7201
Run duration 31m 50s
Commit git commit 531ac62b3e: feat: [UIE-8139] - IAM RBAC: add new assigned entities table component part 1 (#...
Committer aaleksee-akamai
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 4
Tests that did not run due to a developer annotating a test with .skip  Pending 2
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 501
View all changes introduced in this branch ↗︎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Approved Multiple approvals and ready to merge! IAM (Identity & Access Management)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants