Skip to content

Commit

Permalink
[PLAT-10802][RBAC|UI] UI shows 1/0 Universe when no universes are the…
Browse files Browse the repository at this point in the history
…re in portal - [PLAT-10803][RBAC|UI] Able to select same role multiple times

Summary:
Previously, we used index as 0, but now since other resource types are added, we now find the universeType and consider it's length.
And also ,now we have added a check to prevent the user from selecting duplicate role

Test Plan: Tested manually

Reviewers: asathyan, lsangappa

Reviewed By: lsangappa

Subscribers: yugaware

Differential Revision: https://phorge.dev.yugabyte.com/D29195
  • Loading branch information
haikarthikssk committed Oct 11, 2023
1 parent fe26a51 commit 15fdf98
Show file tree
Hide file tree
Showing 14 changed files with 161 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { FC, useEffect, useState } from 'react';
import { useToggle } from 'react-use';
import { Controller, useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { find } from 'lodash';
import { find, findIndex } from 'lodash';
import { Box, makeStyles } from '@material-ui/core';
import { YBTable } from '../../../../components/backupv2/components/restore/pages/selectTables/YBTable';
import { YBCheckboxField, YBModal } from '../../../components';
Expand Down Expand Up @@ -92,8 +92,6 @@ const useStyle = makeStyles((theme) => ({
}
}));

const ResourceGroupIndex = 0;

export const SelectUniverseResource: FC<SelectUniverseResourceProps> = ({
fieldIndex,
universeList
Expand All @@ -109,6 +107,11 @@ export const SelectUniverseResource: FC<SelectUniverseResourceProps> = ({
const role = watch(`roleResourceDefinitions.${fieldIndex}.role`);
const roleMappings = watch(`roleResourceDefinitions.${fieldIndex}.resourceGroup`);

const ResourceGroupIndex = Math.max(
findIndex(roleMappings.resourceDefinitionSet, { resourceType: Resource.UNIVERSE }),
0
);

const [selectedResources, setSelectedResources] = useState<UniverseNameAndUUIDMapping[]>(
roleMappings.resourceDefinitionSet[ResourceGroupIndex].resourceUUIDSet
);
Expand Down
16 changes: 9 additions & 7 deletions managed/ui/src/redesign/features/rbac/roles/RoleContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@ import { Role } from './IRoles';
// export const roleMethods
export default createStateContext<Role | null>(null);

export const Pages = ['CREATE_ROLE', 'LIST_ROLE', 'EDIT_ROLE'] as const;
export const Pages = {
CREATE_ROLE: 'CREATE_ROLE',
LIST_ROLE: 'LIST_ROLE',
EDIT_ROLE: 'EDIT_ROLE'
} as const;
export const EditViews = { CONFIGURATIONS: 'CONFIGURATIONS', USERS: 'USERS' } as const;

export const EditViews = ['CONFIGURATIONS', 'USERS'] as const;

export type Page = typeof Pages[number];
export type EditView = typeof EditViews[number];
export type Page = keyof typeof Pages;

export type RoleViewContext = {
formProps: {
currentPage: Page;
editView?: EditView
editView?: keyof typeof EditViews;
};
currentRole: Role | null;
};
Expand All @@ -50,7 +52,7 @@ export const roleMethods = (context: RoleViewContext) => ({
...context,
currentRole
}),
setEditView: (editView: EditView): RoleViewContext => ({
setEditView: (editView: keyof typeof EditViews): RoleViewContext => ({
...context,
formProps: {
...context.formProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { resourceOrderByRelevance } from '../../common/RbacUtils';
import { Role } from '../IRoles';
import { Permission, Resource } from '../../permission';
import { createRole, editRole, getAllAvailablePermissions } from '../../api';
import { RoleContextMethods, RoleViewContext } from '../RoleContext';
import { Pages, RoleContextMethods, RoleViewContext } from '../RoleContext';
import { createErrorMessage } from '../../../universe/universe-form/utils/helpers';
import { isDefinedNotNull, isNonEmptyString } from '../../../../../utils/ObjectUtils';
import { ArrowDropDown, Create } from '@material-ui/icons';
Expand Down Expand Up @@ -121,7 +121,7 @@ export const CreateRole = forwardRef((_, forwardRef) => {
{
onSuccess: (_resp, role) => {
toast.success(t('successMsg', { role_name: role.name }));
setCurrentPage('LIST_ROLE');
setCurrentPage(Pages.LIST_ROLE);
},
onError: (err) => {
toast.error(createErrorMessage(err));
Expand All @@ -136,7 +136,7 @@ export const CreateRole = forwardRef((_, forwardRef) => {
{
onSuccess: (_resp, role) => {
toast.success(t('editSuccessMsg', { role_name: role.name }));
setCurrentPage('LIST_ROLE');
setCurrentPage(Pages.LIST_ROLE);
},
onError: (err) => {
toast.error(createErrorMessage(err));
Expand All @@ -155,7 +155,7 @@ export const CreateRole = forwardRef((_, forwardRef) => {
};

const onCancel = () => {
setCurrentPage('LIST_ROLE');
setCurrentPage(Pages.LIST_ROLE);
};

useImperativeHandle(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { toast } from 'react-toastify';
import { Trans, useTranslation } from 'react-i18next';
import { makeStyles } from '@material-ui/core';
import { YBInputField, YBModal } from '../../../../components';
import { RoleContextMethods, RoleViewContext } from '../RoleContext';
import { Pages, RoleContextMethods, RoleViewContext } from '../RoleContext';
import { deleteRole } from '../../api';
import { createErrorMessage } from '../../../universe/universe-form/utils/helpers';
import { Role } from '../IRoles';
Expand Down Expand Up @@ -59,7 +59,7 @@ export const DeleteRoleModal: FC<DeleteRoleProps> = ({ open, onHide }) => {
onSuccess: () => {
toast.success(t('successMsg', { role_name: currentRole?.name }));
queryClient.invalidateQueries('roles');
setCurrentPage('LIST_ROLE');
setCurrentPage(Pages.LIST_ROLE);
onHide();
},
onError: (err) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { UsersUnderRole } from './UsersUnderRole';
import { DeleteRoleModal } from './DeleteRoleModal';
import { ConfirmEditRoleModal } from './ConfirmEditRoleModal';

import { EditView, RoleContextMethods, RoleViewContext } from '../RoleContext';
import { EditViews, RoleContextMethods, RoleViewContext } from '../RoleContext';
import { RoleType } from '../IRoles';

import { ReactComponent as ArrowLeft } from '../../../../assets/arrow_left.svg';
Expand Down Expand Up @@ -76,26 +76,32 @@ export const EditRole = () => {
keyPrefix: 'rbac.roles.edit'
});

const Menu: { view: EditView, label: string }[] = [
const Menu: { view: keyof typeof EditViews; label: string }[] = [
{
view: "CONFIGURATIONS",
view: EditViews.CONFIGURATIONS,
label: t('menu.configurations')
},
{
view: "USERS",
view: EditViews.USERS,
label: t('menu.users')
}
];

const classes = useStyles();
const [{ currentRole, formProps: { editView } }] = (useContext(RoleViewContext) as unknown) as RoleContextMethods;
const [currentView, setCurrentView] = useState<typeof Menu[number]['view']>(editView ?? "CONFIGURATIONS");
const [
{
currentRole,
formProps: { editView }
}
] = (useContext(RoleViewContext) as unknown) as RoleContextMethods;
const [currentView, setCurrentView] = useState<keyof typeof EditViews>(
editView ?? EditViews.CONFIGURATIONS
);
const createRoleRef = useRef<any>(null);

const [showDeleteModal, toggleDeleteModal] = useToggle(false);
const [showEditRoleConfirmModal, toggleEditRoleConfirmModal] = useToggle(false);


return (
<Container
onCancel={() => {
Expand Down Expand Up @@ -144,7 +150,7 @@ export const EditRole = () => {
))}
</Grid>
<Grid item>
{currentView === "CONFIGURATIONS" ? (
{currentView === EditViews.CONFIGURATIONS ? (
<div>
<CreateRole ref={createRoleRef} />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { YBLoadingCircleIcon } from '../../../../../components/common/indicators
import { YBSearchInput } from '../../../../../components/common/forms/fields/YBSearchInput';
import { RoleTypeComp } from '../../common/RbacUtils';

import { RoleContextMethods, RoleViewContext } from '../RoleContext';
import { EditViews, Pages, RoleContextMethods, RoleViewContext } from '../RoleContext';
import { ForbiddenRoles, Role, RoleType } from '../IRoles';
import { getAllRoles, getRoleBindingsForAllUsers } from '../../api';
import { RbacValidator, hasNecessaryPerm } from '../../common/RbacValidator';
Expand Down Expand Up @@ -115,27 +115,25 @@ const ListRoles = () => {
icon: <User />,
callback: () => {
setCurrentRole(role);
setEditView("USERS");
setCurrentPage('EDIT_ROLE');
setEditView(EditViews.USERS);
setCurrentPage(Pages.EDIT_ROLE);
}
}
];


if (
hasNecessaryPerm({
...UserPermissionMap.editRole,
onResource: role.roleUUID
})
) {

menuOptions.push({
text: t('table.moreActions.editRole'),
icon: <Create />,
callback: () => {
setCurrentRole(role);
setEditView("CONFIGURATIONS");
setCurrentPage('EDIT_ROLE');
setEditView(EditViews.CONFIGURATIONS);
setCurrentPage(Pages.EDIT_ROLE);
}
});

Expand All @@ -149,8 +147,8 @@ const ListRoles = () => {
roleUUID: '',
name: ''
});
setEditView("CONFIGURATIONS");
setCurrentPage('CREATE_ROLE');
setEditView(EditViews.CONFIGURATIONS);
setCurrentPage(Pages.CREATE_ROLE);
}
});

Expand Down Expand Up @@ -213,7 +211,7 @@ const ListRoles = () => {
variant="primary"
onClick={() => {
setCurrentRole(null);
setCurrentPage('CREATE_ROLE');
setCurrentPage(Pages.CREATE_ROLE);
}}
data-testid={`rbac-resource-create-role`}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { flattenDeep, values } from 'lodash';
import { useTranslation } from 'react-i18next';
import { Typography, makeStyles } from '@material-ui/core';
import { getRoleBindingsForAllUsers } from '../../api';
import { RoleContextMethods, RoleViewContext } from '../RoleContext';
import { Pages, RoleContextMethods, RoleViewContext } from '../RoleContext';
import { UsersTab } from '../../common/rbac_constants';

const useStyles = makeStyles((theme) => ({
Expand Down Expand Up @@ -63,7 +63,7 @@ export const UsersUnderRole = forwardRef((_, forwardRef) => {

const onCancel = () => {
setCurrentRole(null);
setCurrentPage('LIST_ROLE');
setCurrentPage(Pages.LIST_ROLE);
};

useImperativeHandle(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import { toast } from 'react-toastify';
import { yupResolver } from '@hookform/resolvers/yup';
import { useTranslation } from 'react-i18next';
import { FormProvider, useForm } from 'react-hook-form';
import { Box, makeStyles } from '@material-ui/core';
import { Box, FormHelperText, makeStyles } from '@material-ui/core';
import Container from '../../common/Container';
import { RolesAndResourceMapping } from '../../policy/RolesAndResourceMapping';
import { YBInputField, YBPasswordField } from '../../../../components';
import { createUser } from '../../api';
import { RbacUserWithResources } from '../interface/Users';
import { Resource } from '../../permission';
import { UserContextMethods, UserViewContext } from './UserContext';
import { UserContextMethods, UserPages, UserViewContext } from './UserContext';
import { createErrorMessage } from '../../../universe/universe-form/utils/helpers';
import { getUserValidationSchema } from './UserValidationSchema';

Expand Down Expand Up @@ -95,7 +95,7 @@ const CreateUsersForm = forwardRef((_, forwardRef) => {
onSuccess: () => {
toast.success(t('form.successMsg', { user_email: methods.getValues().email }));
queryClient.invalidateQueries('users');
setCurrentPage('LIST_USER');
setCurrentPage(UserPages.LIST_USER);
},
onError: (err) => {
toast.error(createErrorMessage(err));
Expand Down Expand Up @@ -148,6 +148,11 @@ const CreateUsersForm = forwardRef((_, forwardRef) => {
fullWidth
/>
<RolesAndResourceMapping />
{errors.roleResourceDefinitions?.message && (
<FormHelperText required error>
{errors.roleResourceDefinitions.message}
</FormHelperText>
)}
</form>
</Box>
</FormProvider>
Expand All @@ -168,7 +173,7 @@ export const CreateUsers = () => {
<Container
onCancel={() => {
setCurrentUser(null);
setCurrentPage('LIST_USER');
setCurrentPage(UserPages.LIST_USER);
}}
onSave={() => {
createUserRef.current?.onSave();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { deleteUser } from '../../api';
import { createErrorMessage } from '../../../universe/universe-form/utils/helpers';
import ErrorIcon from '../../../../assets/error.svg';
import { RbacUser } from '../interface/Users';
import { UserContextMethods, UserViewContext } from './UserContext';
import { UserContextMethods, UserPages, UserViewContext } from './UserContext';

type DeleteUserProps = {
open: boolean;
Expand Down Expand Up @@ -58,7 +58,7 @@ export const DeleteUserModal: FC<DeleteUserProps> = ({ open, onHide }) => {
const doDeleteUser = useMutation(() => deleteUser(currentUser!), {
onSuccess: () => {
toast.success(t('successMsg', { user_email: currentUser?.email }));
setCurrentPage('LIST_USER');
setCurrentPage(UserPages.LIST_USER);
queryClient.invalidateQueries('users');
onHide();
},
Expand Down
Loading

0 comments on commit 15fdf98

Please sign in to comment.