Skip to content

Commit

Permalink
fix(rbac): fix to enable create and edit role buttons on having corre…
Browse files Browse the repository at this point in the history
…ct permissions (janus-idp#1703)
  • Loading branch information
divyanshiGupta committed May 30, 2024
1 parent 4e36115 commit 19a9088
Show file tree
Hide file tree
Showing 14 changed files with 212 additions and 161 deletions.
2 changes: 2 additions & 0 deletions plugins/rbac/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ p, role:default/team_a, policy-entity, create, allow
g, user:default/<login-id/user-name>, role:default/team_a
```

> Note: Even after applying above permissions if the create button is still disabled then please contact your administrator as you might be conditionally restricted to access the create button.
- To fetch the permissions from other plugins like `Kubernetes` and `Jenkins` in the Role Form as mentioned [here](https://github.com/janus-idp/backstage-plugins/blob/main/plugins/rbac-backend/docs/permissions.md), add the following configuration in your `app-config.yaml`:

```yaml title="app-config.yaml"
Expand Down
1 change: 1 addition & 0 deletions plugins/rbac/src/components/CreateRole/AddMembersForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export const AddMembersForm = ({
renderOption={(option: SelectedMember, state) => (
<MembersDropdownOption option={option} state={state} />
)}
noOptionsText="No users and groups found."
clearOnEscape
renderInput={params => (
<TextField
Expand Down
18 changes: 0 additions & 18 deletions plugins/rbac/src/components/CreateRole/CreateRolePage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React from 'react';
import { useAsync } from 'react-use';

import { Content, Header, Page } from '@backstage/core-components';
import { RequirePermission } from '@backstage/plugin-permission-react';

import { render, screen } from '@testing-library/react';

Expand All @@ -22,16 +21,6 @@ jest.mock('./RoleForm', () => ({
RoleForm: () => <div>RoleForm</div>,
}));

jest.mock('@backstage/plugin-permission-react', () => ({
RequirePermission: jest
.fn()
.mockImplementation(({ children }) => <div>{children}</div>),
}));

const mockedPrequirePermission = RequirePermission as jest.MockedFunction<
typeof RequirePermission
>;

jest.mock('@backstage/core-components', () => ({
Page: jest.fn().mockImplementation(({ children }) => (
<div data-testid="mockPage">
Expand Down Expand Up @@ -67,13 +56,6 @@ describe('CreateRolePage', () => {
});

render(<CreateRolePage />);
expect(mockedPrequirePermission).toHaveBeenCalledWith(
expect.objectContaining({
permission: expect.objectContaining({ name: 'catalog.entity.read' }),
resourceRef: expect.stringContaining('catalog-entity'),
}),
expect.anything(),
);
expect(mockedPage).toHaveBeenCalled();
expect(mockedHeader).toHaveBeenCalled();
expect(mockedContent).toHaveBeenCalled();
Expand Down
77 changes: 43 additions & 34 deletions plugins/rbac/src/components/CreateRole/CreateRolePage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import React from 'react';
import { useAsync } from 'react-use';

import { Content, Header, Page } from '@backstage/core-components';
import {
Content,
ErrorPage,
Header,
Page,
Progress,
} from '@backstage/core-components';
import { useApi } from '@backstage/core-plugin-api';
import { catalogEntityReadPermission } from '@backstage/plugin-catalog-common/alpha';
import { RequirePermission } from '@backstage/plugin-permission-react';

import { rbacApiRef } from '../../api/RBACBackendClient';
import { MemberEntity } from '../../types';
Expand All @@ -15,13 +19,19 @@ import { RoleFormValues } from './types';
export const CreateRolePage = () => {
const rbacApi = useApi(rbacApiRef);
const {
loading,
loading: membersLoading,
value: members,
error: membersError,
} = useAsync(async () => {
return await rbacApi.getMembers();
});

const canReadUsersAndGroups =
!membersLoading &&
!membersError &&
Array.isArray(members) &&
members.length > 0;

const initialValues: RoleFormValues = {
name: '',
namespace: 'default',
Expand All @@ -31,35 +41,34 @@ export const CreateRolePage = () => {
permissionPoliciesRows: [initialPermissionPolicyRowValue],
};

return (
<RequirePermission
permission={catalogEntityReadPermission}
resourceRef={catalogEntityReadPermission.resourceType}
>
<Page themeId="tool">
<Header title="Create role" type="RBAC" typeLink=".." />
<Content>
<RoleForm
initialValues={initialValues}
titles={{
formTitle: 'Create Role',
nameAndDescriptionTitle: 'Enter name and description of role ',
usersAndGroupsTitle: 'Add users and groups',
permissionPoliciesTitle: 'Add permission policies',
}}
membersData={{
members: Array.isArray(members)
? members
: ([] as MemberEntity[]),
loading,
error: (membersError as Error) || {
name: (members as Response)?.status,
message: (members as Response)?.statusText,
},
}}
/>
</Content>
</Page>
</RequirePermission>
if (membersLoading) {
return <Progress />;
}

return canReadUsersAndGroups ? (
<Page themeId="tool">
<Header title="Create role" type="RBAC" typeLink=".." />
<Content>
<RoleForm
initialValues={initialValues}
titles={{
formTitle: 'Create Role',
nameAndDescriptionTitle: 'Enter name and description of role ',
usersAndGroupsTitle: 'Add users and groups',
permissionPoliciesTitle: 'Add permission policies',
}}
membersData={{
members: Array.isArray(members) ? members : ([] as MemberEntity[]),
loading: membersLoading,
error: (membersError as unknown as Error) || {
name: (members as unknown as Response)?.status,
message: (members as unknown as Response)?.statusText,
},
}}
/>
</Content>
</Page>
) : (
<ErrorPage statusMessage="Unauthorized to create role" />
);
};
14 changes: 3 additions & 11 deletions plugins/rbac/src/components/CreateRole/EditRolePage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,6 @@ jest.mock('./RoleForm', () => ({
RoleForm: () => <div>RoleForm</div>,
}));

jest.mock('@backstage/plugin-permission-react', () => ({
RequirePermission: jest
.fn()
.mockImplementation(({ permission, resourceRef, children }) => (
<div>
{`${permission} ${resourceRef}`}
{children}
</div>
)),
}));

jest.mock('@backstage/core-components', () => ({
useQueryParamState: () => ['roleName', jest.fn()],
Progress: () => <div>MockedProgressComponent</div>,
Expand Down Expand Up @@ -117,6 +106,7 @@ describe('EditRolePage', () => {
loading: false,
roleError: { name: '', message: '' },
membersError: new Error(''),
canReadUsersAndGroups: true,
});
render(<EditRolePage />);
expect(screen.getByText('Edit Role Page')).toBeInTheDocument();
Expand All @@ -131,6 +121,7 @@ describe('EditRolePage', () => {
role: undefined,
membersError: { name: '', message: '' },
roleError: { name: '', message: '' },
canReadUsersAndGroups: true,
});
render(<EditRolePage />);
expect(screen.queryByText('MockedProgressComponent')).toBeInTheDocument();
Expand All @@ -144,6 +135,7 @@ describe('EditRolePage', () => {
role: undefined,
membersError: { name: 'Error', message: 'Error Message' },
loading: false,
canReadUsersAndGroups: true,
});
render(<EditRolePage />);
expect(screen.queryByText('MockedErrorPageComponent')).toBeInTheDocument();
Expand Down
80 changes: 38 additions & 42 deletions plugins/rbac/src/components/CreateRole/EditRolePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import {
Progress,
useQueryParamState,
} from '@backstage/core-components';
import { catalogEntityReadPermission } from '@backstage/plugin-catalog-common/alpha';
import { RequirePermission } from '@backstage/plugin-permission-react';

import { usePermissionPolicies } from '../../hooks/usePermissionPolicies';
import { useSelectedMembers } from '../../hooks/useSelectedMembers';
Expand All @@ -20,10 +18,17 @@ import { RoleFormValues } from './types';
export const EditRolePage = () => {
const { roleName, roleNamespace, roleKind } = useParams();
const [queryParamState] = useQueryParamState<number>('activeStep');
const { selectedMembers, members, role, loading, roleError, membersError } =
useSelectedMembers(
roleName ? `${roleKind}:${roleNamespace}/${roleName}` : '',
);
const {
selectedMembers,
members,
role,
loading,
roleError,
membersError,
canReadUsersAndGroups,
} = useSelectedMembers(
roleName ? `${roleKind}:${roleNamespace}/${roleName}` : '',
);

const { data: permissionPolicies, conditionsData } = usePermissionPolicies(
`${roleKind}:${roleNamespace}/${roleName}`,
Expand All @@ -37,44 +42,35 @@ export const EditRolePage = () => {
selectedMembers,
permissionPoliciesRows: [...conditionsData, ...permissionPolicies],
};
const renderPage = () => {
if (loading) {
return <Progress />;
} else if (roleError.name) {
return (
<ErrorPage status={roleError.name} statusMessage={roleError.message} />
);
}

if (loading) {
return <Progress />;
} else if (roleError.name) {
return (
<>
<Header title="Edit role" type="RBAC" typeLink=".." />
<Content>
<RoleForm
initialValues={initialValues}
titles={{
formTitle: 'Edit Role',
nameAndDescriptionTitle: 'Edit name and description of role ',
usersAndGroupsTitle: 'Edit users and groups',
permissionPoliciesTitle: 'Edit permission policies',
}}
roleName={
roleName ? `${roleKind}:${roleNamespace}/${roleName}` : ''
}
step={Number(queryParamState)}
membersData={{ members, loading, error: membersError }}
submitLabel="Save"
/>
</Content>
</>
<ErrorPage status={roleError.name} statusMessage={roleError.message} />
);
};
}

return (
<RequirePermission
permission={catalogEntityReadPermission}
resourceRef={catalogEntityReadPermission.resourceType}
>
<Page themeId="tool">{renderPage()}</Page>
</RequirePermission>
return canReadUsersAndGroups ? (
<Page themeId="tool">
<Header title="Edit role" type="RBAC" typeLink=".." />
<Content>
<RoleForm
initialValues={initialValues}
titles={{
formTitle: 'Edit Role',
nameAndDescriptionTitle: 'Edit name and description of role ',
usersAndGroupsTitle: 'Edit users and groups',
permissionPoliciesTitle: 'Edit permission policies',
}}
roleName={roleName ? `${roleKind}:${roleNamespace}/${roleName}` : ''}
step={Number(queryParamState)}
membersData={{ members, loading, error: membersError }}
submitLabel="Save"
/>
</Content>
</Page>
) : (
<ErrorPage statusMessage="Unauthorized to edit role" />
);
};
Loading

0 comments on commit 19a9088

Please sign in to comment.