Skip to content

Commit c10347d

Browse files
authored
feat(rbac): allow editing permission policies (#1037)
feat(rbac): edit permission policies
1 parent 993da38 commit c10347d

33 files changed

+766
-347
lines changed

plugins/rbac/dev/index.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { TestApiProvider } from '@backstage/test-utils';
99

1010
import {
1111
PermissionPolicy,
12-
Policy,
1312
Role,
1413
RoleBasedPolicy,
1514
} from '@janus-idp/backstage-plugin-rbac-common';
@@ -71,9 +70,10 @@ class MockRBACApi implements RBACAPI {
7170
return { status: 200 } as Response;
7271
}
7372

74-
async updatePolicy(
75-
_oldPolicy: RoleBasedPolicy,
76-
_newPolicy: RoleBasedPolicy,
73+
async updatePolicies(
74+
_entityReference: string,
75+
_oldPolicies: RoleBasedPolicy[],
76+
_newPolicies: RoleBasedPolicy[],
7777
): Promise<Response> {
7878
return { status: 204 } as Response;
7979
}
@@ -92,7 +92,7 @@ class MockRBACApi implements RBACAPI {
9292

9393
async deletePolicies(
9494
_entityRef: string,
95-
_policies: Policy[],
95+
_policies: RoleBasedPolicy[],
9696
): Promise<Response> {
9797
return {
9898
ok: true,
@@ -105,7 +105,7 @@ class MockRBACApi implements RBACAPI {
105105
return { status: 200 } as Response;
106106
}
107107

108-
async createPolicy(_data: any): Promise<Response> {
108+
async createPolicies(_policies: RoleBasedPolicy[]): Promise<Response> {
109109
return { status: 200 } as Response;
110110
}
111111
}

plugins/rbac/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"@backstage/plugin-permission-react": "^0.4.16",
3434
"@backstage/theme": "^0.4.3",
3535
"@janus-idp/backstage-plugin-rbac-common": "1.2.0",
36+
"@janus-idp/shared-react": "2.3.0",
3637
"@material-ui/core": "^4.9.13",
3738
"@material-ui/icons": "^4.11.3",
3839
"@material-ui/lab": "^4.0.0-alpha.45",

plugins/rbac/src/api/RBACBackendClient.ts

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ import {
66

77
import {
88
PermissionPolicy,
9-
Policy,
109
Role,
1110
RoleBasedPolicy,
1211
} from '@janus-idp/backstage-plugin-rbac-common';
1312

14-
import { CreateRoleError, MemberEntity } from '../types';
13+
import { MemberEntity, RoleError } from '../types';
1514
import { getKindNamespaceName } from '../utils/rbac-utils';
1615

1716
// @public
@@ -23,17 +22,21 @@ export type RBACAPI = {
2322
entityReference: string,
2423
) => Promise<RoleBasedPolicy[] | Response>;
2524
deleteRole: (role: string) => Promise<Response>;
26-
deletePolicies: (role: string, policy: Policy[]) => Promise<Response>;
2725
getRole: (role: string) => Promise<Role[] | Response>;
2826
getMembers: () => Promise<MemberEntity[] | Response>;
29-
listPermissions: () => Promise<PermissionPolicy[]>;
30-
createRole: (role: Role) => Promise<CreateRoleError | Response>;
31-
updateRole: (oldRole: Role, newRole: Role) => Promise<Response>;
32-
updatePolicy: (
33-
oldPolicy: RoleBasedPolicy,
34-
newPolicy: RoleBasedPolicy,
35-
) => Promise<Response>;
36-
createPolicy: (data: any) => Promise<Response>;
27+
listPermissions: () => Promise<PermissionPolicy[] | Response>;
28+
createRole: (role: Role) => Promise<RoleError | Response>;
29+
updateRole: (oldRole: Role, newRole: Role) => Promise<RoleError | Response>;
30+
updatePolicies: (
31+
entityReference: string,
32+
oldPolicy: RoleBasedPolicy[],
33+
newPolicy: RoleBasedPolicy[],
34+
) => Promise<RoleError | Response>;
35+
createPolicies: (polices: RoleBasedPolicy[]) => Promise<RoleError | Response>;
36+
deletePolicies: (
37+
entityReference: string,
38+
polices: RoleBasedPolicy[],
39+
) => Promise<RoleError | Response>;
3740
};
3841

3942
export type Options = {
@@ -176,6 +179,9 @@ export class RBACBackendClient implements RBACAPI {
176179
},
177180
},
178181
);
182+
if (jsonResponse.status !== 200 && jsonResponse.status !== 204) {
183+
return jsonResponse;
184+
}
179185
return jsonResponse.json();
180186
}
181187

@@ -217,21 +223,27 @@ export class RBACBackendClient implements RBACAPI {
217223
body: JSON.stringify(body),
218224
},
219225
);
220-
if (jsonResponse.status !== 200 && jsonResponse.status !== 201) {
226+
if (
227+
jsonResponse.status !== 200 &&
228+
jsonResponse.status !== 201 &&
229+
jsonResponse.status !== 204
230+
) {
221231
return jsonResponse.json();
222232
}
223233
return jsonResponse;
224234
}
225235

226-
async updatePolicy(oldPolicy: RoleBasedPolicy, newPolicy: RoleBasedPolicy) {
236+
async updatePolicies(
237+
entityReference: string,
238+
oldPolicies: RoleBasedPolicy[],
239+
newPolicies: RoleBasedPolicy[],
240+
) {
227241
const { token: idToken } = await this.identityApi.getCredentials();
228242
const backendUrl = this.configApi.getString('backend.baseUrl');
229-
const { kind, namespace, name } = getKindNamespaceName(
230-
oldPolicy.entityReference as string,
231-
);
243+
const { kind, namespace, name } = getKindNamespaceName(entityReference);
232244
const body = {
233-
oldPolicy,
234-
newPolicy,
245+
oldPolicy: oldPolicies,
246+
newPolicy: newPolicies,
235247
};
236248
const jsonResponse = await fetch(
237249
`${backendUrl}/api/permission/policies/${kind}/${namespace}/${name}`,
@@ -251,7 +263,7 @@ export class RBACBackendClient implements RBACAPI {
251263
return jsonResponse;
252264
}
253265

254-
async deletePolicies(entityReference: string, policies: Policy[]) {
266+
async deletePolicies(entityReference: string, policies: RoleBasedPolicy[]) {
255267
const { token: idToken } = await this.identityApi.getCredentials();
256268
const backendUrl = this.configApi.getString('backend.baseUrl');
257269
const { kind, namespace, name } = getKindNamespaceName(entityReference);
@@ -267,10 +279,18 @@ export class RBACBackendClient implements RBACAPI {
267279
method: 'DELETE',
268280
},
269281
);
282+
283+
if (
284+
jsonResponse.status !== 200 &&
285+
jsonResponse.status !== 201 &&
286+
jsonResponse.status !== 204
287+
) {
288+
return jsonResponse.json();
289+
}
270290
return jsonResponse;
271291
}
272292

273-
async createPolicy(data: RoleBasedPolicy[]) {
293+
async createPolicies(policies: RoleBasedPolicy[]) {
274294
const { token: idToken } = await this.identityApi.getCredentials();
275295
const backendUrl = this.configApi.getString('backend.baseUrl');
276296
const jsonResponse = await fetch(`${backendUrl}/api/permission/policies`, {
@@ -280,7 +300,7 @@ export class RBACBackendClient implements RBACAPI {
280300
Accept: 'application/json',
281301
...(idToken && { Authorization: `Bearer ${idToken}` }),
282302
},
283-
body: JSON.stringify(data),
303+
body: JSON.stringify(policies),
284304
});
285305
if (jsonResponse.status !== 200 && jsonResponse.status !== 201) {
286306
return jsonResponse.json();

plugins/rbac/src/components/CreateRole/AddMembersForm.tsx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,21 @@ export const AddMembersForm = ({
4747
};
4848

4949
const membersOptions: SelectedMember[] = membersData.members
50-
? membersData.members.map((member: MemberEntity, index: number) => ({
51-
label: member.spec?.profile?.displayName ?? member.metadata.name,
52-
description: getDescription(member),
53-
etag:
50+
? membersData.members.map((member: MemberEntity, index: number) => {
51+
const tag =
5452
member.metadata.etag ??
55-
`${member.metadata.name}-${member.kind}-${index}`,
56-
type: member.kind,
57-
namespace: member.metadata.namespace,
58-
members: getMembersCount(member),
59-
ref: stringifyEntityRef(member),
60-
}))
53+
`${member.metadata.name}-${member.kind}-${index}`;
54+
return {
55+
id: tag,
56+
label: member.spec?.profile?.displayName ?? member.metadata.name,
57+
description: getDescription(member),
58+
etag: tag,
59+
type: member.kind,
60+
namespace: member.metadata.namespace,
61+
members: getMembersCount(member),
62+
ref: stringifyEntityRef(member),
63+
};
64+
})
6165
: ([] as SelectedMember[]);
6266

6367
return (

plugins/rbac/src/components/CreateRole/CreateRolePage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export const CreateRolePage = () => {
4545
formTitle: 'Create Role',
4646
nameAndDescriptionTitle: 'Enter name and description of role ',
4747
usersAndGroupsTitle: 'Add users and groups',
48-
permissionPoliciesTitle: '',
48+
permissionPoliciesTitle: 'Add permission policies',
4949
}}
5050
membersData={{
5151
members: Array.isArray(members)

plugins/rbac/src/components/CreateRole/EditRolePage.tsx

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
import { catalogEntityReadPermission } from '@backstage/plugin-catalog-common/alpha';
1313
import { RequirePermission } from '@backstage/plugin-permission-react';
1414

15+
import { usePermissionPolicies } from '../../hooks/usePermissionPolicies';
1516
import { useSelectedMembers } from '../../hooks/useSelectedMembers';
1617
import { RoleForm } from './RoleForm';
1718
import { RoleFormValues } from './types';
@@ -24,44 +25,40 @@ export const EditRolePage = () => {
2425
roleName ? `${roleKind}:${roleNamespace}/${roleName}` : '',
2526
);
2627

28+
const { data: permissionPolicies } = usePermissionPolicies(
29+
`${roleKind}:${roleNamespace}/${roleName}`,
30+
);
31+
2732
const initialValues: RoleFormValues = {
2833
name: roleName || '',
2934
namespace: roleNamespace || 'default',
3035
kind: roleKind || 'role',
3136
description: '',
3237
selectedMembers,
33-
permissionPoliciesRows: [
34-
{
35-
plugin: '',
36-
permission: '',
37-
policies: [
38-
{ label: 'Create', checked: false },
39-
{ label: 'Read', checked: false },
40-
{ label: 'Update', checked: false },
41-
{ label: 'Delete', checked: false },
42-
],
43-
},
44-
],
38+
permissionPoliciesRows: permissionPolicies,
4539
};
4640
const renderPage = () => {
4741
if (loading) {
4842
return <Progress />;
4943
} else if (roleError?.name) {
5044
return (
51-
<ErrorPage status={roleError.name} statusMessage={roleError.message} />
45+
<ErrorPage
46+
status={roleError?.name}
47+
statusMessage={roleError?.message}
48+
/>
5249
);
5350
}
5451
return (
5552
<>
56-
<Header title="Edit Role" />
53+
<Header title="Edit role" type="RBAC" typeLink="/rbac" />
5754
<Content>
5855
<RoleForm
5956
initialValues={initialValues}
6057
titles={{
6158
formTitle: 'Edit Role',
6259
nameAndDescriptionTitle: 'Edit name and description of role ',
6360
usersAndGroupsTitle: 'Edit users and groups',
64-
permissionPoliciesTitle: '',
61+
permissionPoliciesTitle: 'Edit permission policies',
6562
}}
6663
roleName={
6764
roleName ? `${roleKind}:${roleNamespace}/${roleName}` : ''

0 commit comments

Comments
 (0)