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

[AN-149] Add ability to edit namespace permissions #5203

Open
wants to merge 9 commits into
base: dev
Choose a base branch
from

Conversation

salonishah11
Copy link
Contributor

@salonishah11 salonishah11 commented Dec 16, 2024

Jira Ticket: https://broadworkbench.atlassian.net/browse/AN-149

Summary of changes:

What

  • Add ability to edit namespace permissions

Why

  • FC UI migration

Testing strategy

  • manual testing
  • unit tests

Workflows List
Screenshot 2024-12-16 at 10 05 01 AM

Edit modal
Screenshot 2024-12-16 at 10 06 06 AM

Error message is shown when user doesn't have edit permissions
Screenshot 2024-12-19 at 6 31 16 PM

@@ -47,6 +47,19 @@ export const Methods = (signal?: AbortSignal) => ({
return res.json();
},

getNamespacePermissions: async (namespace: string): Promise<MethodConfigACL> => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just for me, could you clarify what a namespace is, and what the new name will be if there will be a change as part of the PR Adam is working on?
It looks to me like a namespace is the same thing as a workflow / modal but I think I am missing a critical nuance here sorry

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So it is similar to workspace namespace where one namespace can have many different workflows/methods inside a namespace. And similar to its workspace friend, a workflow/method namespace can have separate set of permissions (which are maintained in Agora and not Sam).

In the new world, its new name based on mockups is going to be collection.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ohhh, TIL that workspaces had namespaces 🫨
But the collection idea makes sense to me, thanks!

Copy link
Collaborator

@LizBaldo LizBaldo left a comment

Choose a reason for hiding this comment

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

LGTM! My understanding from reading the code change is that before, a user could only edit permissions for a snapshot, not the namespace, and so you refactored the permission provider and modal to be able to handle both?

I only have some minor clarifying requests but none should be a blocker for merging, thank you!


type MethodsNamespaceAjaxNeeds = Pick<MethodsAjaxContract, 'getNamespacePermissions' | 'setNamespacePermissions'>;

const mockSnapshotAjax = () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just curious as to why these two mocks have to be set up in a lightly different way? the mockNamespaceAjax seems a bit more straightforward?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The Ajax calls inside the mockSnapshotAjax are inside a nested method object and hence they were harder to mock out. I had issue previously (in another PR) where I had difficulty mocking similar nested calls and hence I just did here what I had done there.

@@ -47,6 +47,19 @@ export const Methods = (signal?: AbortSignal) => ({
return res.json();
},

getNamespacePermissions: async (namespace: string): Promise<MethodConfigACL> => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ohhh, TIL that workspaces had namespaces 🫨
But the collection idea makes sense to me, thanks!

getPermissions: async (
namespace: string,
_name?: string | undefined,
_snapshotId?: number | undefined,
Copy link
Collaborator

Choose a reason for hiding this comment

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

The idea here is that a snapshotID would never be provided correct?

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 for namespace permissions editing, both name and snapshotId are not required. But since the PermissionsProvider is the same for both namespace and snapshot I need to have it here in the function parameters. As a result I have marked both name and snapshotId with _ which indicated that they are "purposefully not being used"

export interface PermissionsProvider {
getPermissions: (
namespace: string,
name?: string | undefined,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this the name of the namespace or the snapshot, or something else? It feels a bit ambiguous to me

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the name of the method. Namespace parameter itself is the name of the namespace

@salonishah11
Copy link
Contributor Author

My understanding from reading the code change is that before, a user could only edit permissions for a snapshot, not the namespace, and so you refactored the permission provider and modal to be able to handle both?

@LizBaldo yes that is correct. Hence the PermissionsProvider has parameters that handle for both editing namespace as well as snapshot permissions.

src/libs/ajax/methods/providers/PermissionsProvider.ts Outdated Show resolved Hide resolved
src/libs/ajax/methods/providers/PermissionsProvider.ts Outdated Show resolved Hide resolved

type MethodsNamespaceAjaxNeeds = Pick<MethodsAjaxContract, 'getNamespacePermissions' | 'setNamespacePermissions'>;

const mockSnapshotAjax = () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be possible to type the mocks and remove the typecasts here as was done in #5187

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right. That is more for readability right? I don't have strong opinion either way. If you think its a good idea I can create a type for it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, for readability and to help make sure your mocks are set up correctly I believe. Miguel would know more about the benefits.

src/pages/methods/WorkflowList.tsx Outdated Show resolved Hide resolved
headerRenderer: () => <HeaderCell>Actions</HeaderCell>,
cellRenderer: ({ rowIndex }) => {
const { namespace, managers } = paginatedWorkflows[rowIndex];
const isNamespaceOwner = _.includes(getTerraUser().email?.toLowerCase(), _.map(_.toLower, managers));
Copy link
Contributor

Choose a reason for hiding this comment

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

This checks if the user is a method owner, not a namespace owner. I verified that if there is a method that I am not an owner of in a namespace that I am an owner of, Firecloud UI allows me to edit the namespace permissions from that method's row in the table, but this component does not.

Copy link
Contributor Author

@salonishah11 salonishah11 Dec 19, 2024

Choose a reason for hiding this comment

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

Huh that is interesting. I will take a look. Thanks!

Copy link
Contributor Author

@salonishah11 salonishah11 Dec 19, 2024

Choose a reason for hiding this comment

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

I see what happens in FC UI. It doesn't stop me from opening the permissions modal to edit namespace permissions even when I don't have permissions. And then in the modal when it realizes I don't have permission to edit it fails with below error
Screenshot 2024-12-19 at 12 00 30 PM

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 have updated this behavior to be similar to FC UI. So now the Edit namespace permissions in the Actions menu will always be enabled. But if the user doesn't have edit permissions they will be show an error message in the modal that they don't have permissions to edit the settings.

Copy link
Contributor Author

@salonishah11 salonishah11 Dec 19, 2024

Choose a reason for hiding this comment

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

For post-holidays:

We had a talk during standup and came to a conclusion that we might need to have a discussion on how we can make namespaces more useful. It seems that when User A gives User B 'Owner' permissions on a namespace, it essentially only allows User B to create new methods in that namespace. User B does not inherit the permission to read/edit any pre-existing methods that were created by User A in that namespace. Similarly any new methods created by User B is not visible to User A. Users can only read/edit methods of other users if they have permissions on a snapshot of that method.

Also, the 'Reader' role on namespace setting is unclear as User B doesn't even have read access to methods created by User A in that namespace.

await user.click(screen.getByRole('button', { name: 'Edit namespace permissions' }));

// Assert
expect(
Copy link
Contributor

Choose a reason for hiding this comment

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

It wouldn't hurt to add something after this that checks that the workflow list actually uses the namespace permissions provider and not the snapshot one for its permissions modal.

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 am not sure what would that test prove? Because in the code we actually set it to namespace vs snapshot one right? And the check to ensure right methods were called I think is already covered in PermissionsModal and PermissionsProvider test

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, it would be more of a regression unit test. I suggested it because none of the WorkflowList tests make sure the right API call is ultimately made for this particular permissions modal, but we don't need it if you don't think it's necessary

Copy link
Contributor

@sam-schu sam-schu left a comment

Choose a reason for hiding this comment

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

Approving given there will be a team decision on where to go with namespace permissions after the break, and the most important issue (not being able to edit namespace permissions from a method you don't own) has been addressed. Thanks for picking up where I left off with the Firecloud UI migration, we're so close!

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.

4 participants