Skip to content

Commit

Permalink
Disable manage permissions when no rolebinding present for the defaul…
Browse files Browse the repository at this point in the history
…t group
  • Loading branch information
ppadti committed Oct 4, 2024
1 parent 33ea696 commit 81a2f8d
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ import {
asProjectAdminUser,
} from '~/__tests__/cypress/cypress/utils/mockUsers';
import { mockModelRegistry } from '~/__mocks__/mockModelRegistry';
import type { RoleBindingSubject } from '~/k8sTypes';
import { mockRoleBindingK8sResource } from '~/__mocks__/mockRoleBindingK8sResource';

const groupSubjects: RoleBindingSubject[] = [
{
kind: 'Group',
apiGroup: 'rbac.authorization.k8s.io',
name: 'example-mr-users',
},
];

const setupMocksForMRSettingAccess = ({
hasModelRegistries = true,
Expand Down Expand Up @@ -71,6 +81,19 @@ const setupMocksForMRSettingAccess = ({
req.reply(500); // Something went wrong on the backend when decoding the secret
},
);

cy.interceptOdh(
'GET /api/modelRegistryRoleBindings',
mockK8sResourceList([
mockRoleBindingK8sResource({
namespace: 'odh-model-registries',
name: 'example-mr-user',
subjects: groupSubjects,
roleRefName: 'registry-user-example-mr',
modelRegistryName: 'example-mr',
}),
]),
);
};

it('Model registry settings should not be available for non product admins', () => {
Expand Down
12 changes: 10 additions & 2 deletions frontend/src/pages/modelRegistrySettings/ModelRegistriesTable.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import React from 'react';
import { Button, Toolbar, ToolbarContent, ToolbarItem } from '@patternfly/react-core';
import { Table } from '~/components/table';
import { ModelRegistryKind } from '~/k8sTypes';
import { ModelRegistryKind, RoleBindingKind } from '~/k8sTypes';
import { ContextResourceData } from '~/types';
import { modelRegistryColumns } from './columns';
import ModelRegistriesTableRow from './ModelRegistriesTableRow';

type ModelRegistriesTableProps = {
modelRegistries: ModelRegistryKind[];
refresh: () => Promise<unknown>;
roleBindings: ContextResourceData<RoleBindingKind>;
onCreateModelRegistryClick: () => void;
};

const ModelRegistriesTable: React.FC<ModelRegistriesTableProps> = ({
modelRegistries,
roleBindings,
refresh,
onCreateModelRegistryClick,
}) => (
Expand All @@ -36,7 +39,12 @@ const ModelRegistriesTable: React.FC<ModelRegistriesTableProps> = ({
</Toolbar>
}
rowRenderer={(mr) => (
<ModelRegistriesTableRow key={mr.metadata.name} modelRegistry={mr} refresh={refresh} />
<ModelRegistriesTableRow
key={mr.metadata.name}
modelRegistry={mr}
roleBindings={roleBindings}
refresh={refresh}
/>
)}
variant="compact"
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
import React from 'react';
import { ActionsColumn, Td, Tr } from '@patternfly/react-table';
import { Link } from 'react-router-dom';
import { ModelRegistryKind } from '~/k8sTypes';
import { Tooltip } from '@patternfly/react-core';
import { ModelRegistryKind, RoleBindingKind } from '~/k8sTypes';
import ResourceNameTooltip from '~/components/ResourceNameTooltip';
import { ContextResourceData } from '~/types';
import ViewDatabaseConfigModal from './ViewDatabaseConfigModal';
import DeleteModelRegistryModal from './DeleteModelRegistryModal';
import { ModelRegistryTableRowStatus } from './ModelRegistryTableRowStatus';

type ModelRegistriesTableRowProps = {
modelRegistry: ModelRegistryKind;
roleBindings: ContextResourceData<RoleBindingKind>;
refresh: () => Promise<unknown>;
};

const ModelRegistriesTableRow: React.FC<ModelRegistriesTableRowProps> = ({
modelRegistry: mr,
roleBindings,
refresh,
}) => {
const [isDatabaseConfigModalOpen, setIsDatabaseConfigModalOpen] = React.useState(false);
const [isDeleteModalOpen, setIsDeleteModalOpen] = React.useState(false);
const filteredRoleBindings = roleBindings.data.filter(
(rb) =>
rb.metadata.labels?.['app.kubernetes.io/name'] ===
mr.metadata.annotations?.['openshift.io/display-name'] || mr.metadata.name,
);

return (
<>
<Tr>
Expand All @@ -35,12 +45,18 @@ const ModelRegistriesTableRow: React.FC<ModelRegistriesTableRowProps> = ({
<ModelRegistryTableRowStatus conditions={mr.status?.conditions} />
</Td>
<Td modifier="fitContent">
<Link
aria-label={`Manage permissions for model registry ${mr.metadata.name}`}
to={`/modelRegistrySettings/permissions/${mr.metadata.name}`}
>
Manage permissions
</Link>
{filteredRoleBindings.length === 0 ? (
<Tooltip content="You can manage permissions when the model registry becomes available.">
<span>Manage permissions</span>
</Tooltip>
) : (
<Link
aria-label={`Manage permissions for model registry ${mr.metadata.name}`}
to={`/modelRegistrySettings/permissions/${mr.metadata.name}`}
>
Manage permissions
</Link>
)}
</Td>
<Td isActionCell>
<ActionsColumn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@ import useModelRegistriesBackend from '~/concepts/modelRegistrySettings/useModel
import TitleWithIcon from '~/concepts/design/TitleWithIcon';
import { ProjectObjectType } from '~/concepts/design/utils';
import { ModelRegistrySelectorContext } from '~/concepts/modelRegistry/context/ModelRegistrySelectorContext';
import { useContextResourceData } from '~/utilities/useContextResourceData';
import { RoleBindingKind } from '~/k8sTypes';
import ModelRegistriesTable from './ModelRegistriesTable';
import CreateModal from './CreateModal';
import useModelRegistryRoleBindings from './useModelRegistryRoleBindings';

const ModelRegistrySettings: React.FC = () => {
const [createModalOpen, setCreateModalOpen] = React.useState(false);
const [modelRegistries, loaded, loadError, refreshModelRegistries] = useModelRegistriesBackend();
const [modelRegistries, mrloaded, loadError, refreshModelRegistries] =
useModelRegistriesBackend();
const roleBindings = useContextResourceData<RoleBindingKind>(useModelRegistryRoleBindings());
const { refreshRulesReview } = React.useContext(ModelRegistrySelectorContext);
const loaded = mrloaded && roleBindings.loaded;

const refreshAll = React.useCallback(
() => Promise.all([refreshModelRegistries(), refreshRulesReview()]),
Expand Down Expand Up @@ -65,6 +71,7 @@ const ModelRegistrySettings: React.FC = () => {
>
<ModelRegistriesTable
modelRegistries={modelRegistries}
roleBindings={roleBindings}
refresh={refreshAll}
onCreateModelRegistryClick={() => {
setCreateModalOpen(true);
Expand Down

0 comments on commit 81a2f8d

Please sign in to comment.