Skip to content

Commit

Permalink
feat(orchestrator): disable buttons based on permissions
Browse files Browse the repository at this point in the history
Signed-off-by: Roy Golan <[email protected]>
Signed-off-by: gabriel-farache <[email protected]>
  • Loading branch information
rgolangh authored and gabriel-farache committed Jun 17, 2024
1 parent 2a2eccb commit 57a8ad0
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 20 deletions.
6 changes: 4 additions & 2 deletions plugins/orchestrator-backend/src/service/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,10 @@ const authorize = async (
return decision;
};

declare class UnauthorizedError extends NotAllowedError {
message: 'Unauthorized';
export class UnauthorizedError extends NotAllowedError {
constructor() {
super('Unauthorized');
}
}

export async function createBackendRouter(
Expand Down
14 changes: 14 additions & 0 deletions plugins/orchestrator/docs/Permissions.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,17 @@ g, user:default/guest, role:default/workflowViewer
g, user:default/myOrgUser, role:default/workflowAdmin
g, group:default/platformAdmins, role:default/worflowAdmin
```

See https://casbin.org/docs/rbac for more information about casbin rules

## Enable permissions

To enable permissions, you need to add the following in the [app-config file](../../../app-config.yaml):

```
permission:
enabled: true
rbac:
policies-csv-file: <absolute path to the policy file>
policyFileReload: true
```
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ import {
useRouteRef,
useRouteRefParams,
} from '@backstage/core-plugin-api';
import { usePermission } from '@backstage/plugin-permission-react';

import Button from '@mui/material/Button';
import Grid from '@mui/material/Grid';
import Skeleton from '@mui/material/Skeleton';

import { orchestratorWorkflowExecutePermission } from '@janus-idp/backstage-plugin-orchestrator-common';

import { orchestratorApiRef } from '../../api';
import {
executeWorkflowRouteRef,
Expand All @@ -25,6 +28,9 @@ import WorkflowDefinitionDetailsCard from './WorkflowDefinitionDetailsCard';
export const WorkflowDefinitionViewerPage = () => {
const { workflowId, format } = useRouteRefParams(workflowDefinitionsRouteRef);
const orchestratorApi = useApi(orchestratorApiRef);
const { loading: loadingPermission, allowed: canRun } = usePermission({
permission: orchestratorWorkflowExecutePermission,
});
const {
value: workflowOverview,
loading,
Expand Down Expand Up @@ -61,13 +67,16 @@ export const WorkflowDefinitionViewerPage = () => {
{loading ? (
<Skeleton variant="text" width="5rem" />
) : (
<Button
variant="contained"
color="primary"
onClick={handleExecute}
>
Run
</Button>
!loadingPermission && (
<Button
variant="contained"
color="primary"
onClick={handleExecute}
disabled={!canRun}
>
Run
</Button>
)
)}
</Grid>
</Grid>
Expand Down
11 changes: 8 additions & 3 deletions plugins/orchestrator/src/components/WorkflowInstancePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ import {
useRouteRef,
useRouteRefParams,
} from '@backstage/core-plugin-api';
import { usePermission } from '@backstage/plugin-permission-react';

import Button from '@mui/material/Button';
import Grid from '@mui/material/Grid';

import {
AssessedProcessInstance,
orchestratorWorkflowExecutePermission,
QUERY_PARAM_ASSESSMENT_INSTANCE_ID,
QUERY_PARAM_INSTANCE_ID,
QUERY_PARAM_INSTANCE_STATE,
Expand Down Expand Up @@ -88,6 +90,9 @@ export const WorkflowInstancePage = ({
const [isAbortAlertDialogOpen, setIsAbortAlertDialogOpen] = useState(false);
const [abortWorkflowInstanceErrorMsg, setAbortWorkflowInstanceErrorMsg] =
useState('');
const permittedToExecute = usePermission({
permission: orchestratorWorkflowExecutePermission,
});

const fetchInstance = React.useCallback(async () => {
if (!instanceId && !queryInstanceId) {
Expand Down Expand Up @@ -204,7 +209,7 @@ export const WorkflowInstancePage = ({
<Button
variant="contained"
color="primary"
disabled={!canAbort}
disabled={!permittedToExecute.allowed || !canAbort}
onClick={canAbort ? handleRerun : undefined}
>
Retrigger
Expand All @@ -214,7 +219,7 @@ export const WorkflowInstancePage = ({
<Button
variant="contained"
color="secondary"
disabled={!canAbort}
disabled={!permittedToExecute.allowed || !canAbort}
onClick={
canAbort ? toggleAbortConfirmationDialog : undefined
}
Expand All @@ -229,7 +234,7 @@ export const WorkflowInstancePage = ({
<Button
variant="contained"
color="primary"
disabled={!canRerun}
disabled={!permittedToExecute.allowed || !canRerun}
onClick={canRerun ? handleRerun : undefined}
>
Rerun
Expand Down
27 changes: 19 additions & 8 deletions plugins/orchestrator/src/components/WorkflowsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import { useNavigate } from 'react-router-dom';

import { Link, TableColumn, TableProps } from '@backstage/core-components';
import { useRouteRef } from '@backstage/core-plugin-api';
import { usePermission } from '@backstage/plugin-permission-react';

import Pageview from '@mui/icons-material/Pageview';
import PlayArrow from '@mui/icons-material/PlayArrow';

import {
capitalize,
orchestratorWorkflowExecutePermission,
orchestratorWorkflowInstancesReadPermission,
ProcessInstanceStateValues,
WorkflowOverview,
} from '@janus-idp/backstage-plugin-orchestrator-common';
Expand All @@ -33,7 +36,12 @@ export const WorkflowsTable = ({ items }: WorkflowsTableProps) => {
const definitionLink = useRouteRef(workflowDefinitionsRouteRef);
const executeWorkflowLink = useRouteRef(executeWorkflowRouteRef);
const [data, setData] = useState<FormattedWorkflowOverview[]>([]);

const permittedToExecute = usePermission({
permission: orchestratorWorkflowExecutePermission,
});
const permittedToReadWorkflows = usePermission({
permission: orchestratorWorkflowInstancesReadPermission,
});
const initialState = useMemo(
() => items.map(WorkflowOverviewFormatter.format),
[items],
Expand Down Expand Up @@ -64,6 +72,7 @@ export const WorkflowsTable = ({ items }: WorkflowsTableProps) => {
{
icon: () => <PlayArrow />,
tooltip: 'Execute',
disabled: !permittedToExecute.allowed,
onClick: (_, rowData) =>
handleExecute(rowData as FormattedWorkflowOverview),
},
Expand Down Expand Up @@ -130,12 +139,14 @@ export const WorkflowsTable = ({ items }: WorkflowsTableProps) => {
);

return (
<OverrideBackstageTable<FormattedWorkflowOverview>
title="Workflows"
options={options}
columns={columns}
data={data}
actions={actions}
/>
permittedToReadWorkflows && (
<OverrideBackstageTable<FormattedWorkflowOverview>
title="Workflows"
options={options}
columns={columns}
data={data}
actions={actions}
/>
)
);
};

0 comments on commit 57a8ad0

Please sign in to comment.