Skip to content

Commit

Permalink
feat(rbac): list roles
Browse files Browse the repository at this point in the history
  • Loading branch information
debsmita1 committed Nov 23, 2023
1 parent 80499eb commit 724abc6
Show file tree
Hide file tree
Showing 15 changed files with 824 additions and 41 deletions.
2 changes: 1 addition & 1 deletion packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"@backstage/plugin-search-backend-module-pg": "^0.5.15",
"@backstage/plugin-search-backend-node": "^1.2.10",
"@backstage/plugin-techdocs-backend": "^1.8.0",
"@janus-idp/backstage-plugin-rbac-backend": "^1.0.0",
"@janus-idp/backstage-plugin-rbac-backend": "^1.6.4",
"better-sqlite3": "^9.0.0",
"dockerode": "^4.0.0",
"express": "^4.18.2",
Expand Down
120 changes: 118 additions & 2 deletions plugins/rbac/dev/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import {
} from '@backstage/plugin-permission-react';
import { TestApiProvider } from '@backstage/test-utils';

import { Role, RoleBasedPolicy } from '@janus-idp/backstage-plugin-rbac-common';

import { RBACAPI, rbacApiRef } from '../src/api/RBACBackendClient';
import { RbacPage, rbacPlugin } from '../src/plugin';

class MockPermissionApi implements PermissionApi {
Expand All @@ -21,12 +24,125 @@ class MockPermissionApi implements PermissionApi {
}
}

const mockApi = new MockPermissionApi({ result: 'ALLOW' });
class MockRBACApi implements RBACAPI {
readonly resources;

constructor(fixtureData: Role[]) {
this.resources = fixtureData;
}
async getRoles(): Promise<Role[]> {
return this.resources;
}
async getPolicies(): Promise<RoleBasedPolicy[]> {
return [
{
entityReference: 'role:default/guests',
permission: 'catalog-entity',
policy: 'read',
effect: 'deny',
},
{
entityReference: 'role:default/guests',
permission: 'catalog.entity.create',
policy: 'use',
effect: 'deny',
},
{
entityReference: 'role:default/guests',
permission: 'catalog-entity',
policy: 'read',
effect: 'allow',
},
{
entityReference: 'role:default/guests',
permission: 'catalog.entity.create',
policy: 'use',
effect: 'allow',
},
{
entityReference: 'role:default/guests',
permission: 'policy-entity',
policy: 'create',
effect: 'allow',
},
{
entityReference: 'role:default/guests',
permission: 'policy-entity',
policy: 'read',
effect: 'allow',
},
{
entityReference: 'role:default/guests',
permission: 'policy.entity.read',
policy: 'use',
effect: 'allow',
},
{
entityReference: 'role:default/guests',
permission: 'policy-entity',
policy: 'delete',
effect: 'allow',
},
{
entityReference: 'role:default/rbac_admin',
permission: 'policy-entity',
policy: 'read',
effect: 'allow',
},
{
entityReference: 'role:default/rbac_admin',
permission: 'policy-entity',
policy: 'create',
effect: 'allow',
},
{
entityReference: 'role:default/rbac_admin',
permission: 'policy-entity',
policy: 'delete',
effect: 'allow',
},
{
entityReference: 'role:default/rbac_admin',
permission: 'policy-entity',
policy: 'update',
effect: 'allow',
},
];
}

async getUserAuthorization(): Promise<{ status: string }> {
return {
status: 'Authorized',
};
}

async deleteRole(_roleName: string): Promise<number> {
return 204;
}
}

const mockPermissionApi = new MockPermissionApi({ result: 'ALLOW' });
const mockRBACApi = new MockRBACApi([
{
memberReferences: ['user:default/guest'],
name: 'role:default/guests',
},
{
memberReferences: ['user:default/xyz', 'group:default/admins'],
name: 'role:default/rbac_admin',
},
]);

createDevApp()
.registerPlugin(rbacPlugin)
.addPage({
element: (
<TestApiProvider apis={[[permissionApiRef, mockApi]]}>
<TestApiProvider
apis={[
[permissionApiRef, mockPermissionApi],
[rbacApiRef, mockRBACApi],
]}
>
<RbacPage />
</TestApiProvider>
),
Expand Down
9 changes: 5 additions & 4 deletions plugins/rbac/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,17 @@
"tsc": "tsc"
},
"dependencies": {
"@backstage/catalog-model": "^1.4.3",
"@backstage/core-components": "^0.13.6",
"@backstage/core-plugin-api": "^1.7.0",
"@backstage/plugin-permission-react": "^0.4.16",
"@backstage/theme": "^0.4.3",
"@janus-idp/backstage-plugin-rbac-common": "1.1.0",
"@material-ui/core": "^4.9.13",
"@material-ui/icons": "^4.11.3",
"@material-ui/lab": "^4.0.0-alpha.45",
"react-use": "^17.4.0",
"@backstage/plugin-permission-react": "^0.4.16",
"@janus-idp/backstage-plugin-rbac-common": "1.1.0",
"@mui/icons-material": "5.14.11"
"@mui/icons-material": "5.14.11",
"react-use": "^17.4.0"
},
"peerDependencies": {
"react": "^16.13.1 || ^17.0.0"
Expand Down
38 changes: 37 additions & 1 deletion plugins/rbac/src/api/RBACBackendClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ import {
IdentityApi,
} from '@backstage/core-plugin-api';

import { Role, RoleBasedPolicy } from '@janus-idp/backstage-plugin-rbac-common';

// @public
export type RBACAPI = {
getUserAuthorization: () => Promise<{ status: string }>;
getRoles: () => Promise<any>;
getRoles: () => Promise<Role[]>;
getPolicies: () => Promise<RoleBasedPolicy[]>;
deleteRole: (role: string) => Promise<number>;
};

export type Options = {
Expand Down Expand Up @@ -51,4 +55,36 @@ export class RBACBackendClient implements RBACAPI {
});
return jsonResponse.json();
}

async getPolicies() {
const { token: idToken } = await this.identityApi.getCredentials();
const backendUrl = this.configApi.getString('backend.baseUrl');
const jsonResponse = await fetch(`${backendUrl}/api/permission/policies`, {
headers: {
...(idToken && { Authorization: `Bearer ${idToken}` }),
},
});
return jsonResponse.json();
}

async deleteRole(role: string) {
const { token: idToken } = await this.identityApi.getCredentials();
const backendUrl = this.configApi.getString('backend.baseUrl');
const str = role.split(':');
const kind = str[0];
const namespace = str[1].split('/')[0];
const name = str[1].split('/')[1];
const jsonResponse = await fetch(
`${backendUrl}/api/permission/roles/${kind}/${namespace}/${name}`,
{
headers: {
...(idToken && { Authorization: `Bearer ${idToken}` }),
'Content-Type': 'application/json',
Accept: 'application/json',
},
method: 'DELETE',
},
);
return jsonResponse.status;
}
}
35 changes: 35 additions & 0 deletions plugins/rbac/src/components/DeleteRole.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';

import { IconButton, Tooltip } from '@material-ui/core';
import Delete from '@mui/icons-material/Delete';

type DeleteRoleProps = {
openDialog: (name: string) => void;
roleName: string;
disable: any;
tooltip?: string | undefined;
dataTestId: string;
};

const DeleteRole = ({
openDialog,
roleName,
tooltip,
disable,
dataTestId,
}: DeleteRoleProps) => (
<Tooltip title={tooltip || ''}>
<span data-testid={dataTestId}>
<IconButton
onClick={() => openDialog(roleName)}
aria-label="Delete"
disabled={disable}
title={tooltip || 'Delete Role'}
>
<Delete />
</IconButton>
</span>
</Tooltip>
);

export default DeleteRole;
Loading

0 comments on commit 724abc6

Please sign in to comment.