Skip to content

Commit

Permalink
Updates roles and related pages
Browse files Browse the repository at this point in the history
Signed-off-by: Darshit Chanpura <[email protected]>
  • Loading branch information
DarshitChanpura committed Aug 7, 2024
1 parent 451e957 commit d4e5da3
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 63 deletions.
63 changes: 50 additions & 13 deletions public/apps/configuration/panels/role-edit/role-edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import { generateResourceName } from '../../utils/resource-utils';
import { NameRow } from '../../utils/name-row';
import { DataSourceContext } from '../../app-router';
import { SecurityPluginTopNavMenu } from '../../top-nav-menu';
import { HeaderDescription, HeaderTitle } from '../../header/header-components';

interface RoleEditDeps extends BreadcrumbsPageDependencies {
action: 'create' | 'edit' | 'duplicate';
Expand Down Expand Up @@ -233,6 +234,23 @@ export function RoleEdit(props: RoleEditDeps) {

const tenantOptions = tenantNames.map(stringToComboBoxOption);

const updatedUX = props.coreStart.uiSettings.get('home:useNewHomePage');

const descriptionData = [
{
renderComponent: (
<EuiText size="xs" color="subdued">
Roles are the core way of controlling access to your cluster. Roles contain any
combination of cluster-wide permission, index-
<br />
specific permissions, document- and field-level security, and tenants. Then you map users
to these roles so that users <br />
gain those permissions. <ExternalLink href={DocLinks.UsersAndRolesDoc} />
</EuiText>
),
},
];

return (
<>
<SecurityPluginTopNavMenu
Expand All @@ -241,19 +259,38 @@ export function RoleEdit(props: RoleEditDeps) {
setDataSource={setDataSource}
selectedDataSource={dataSource}
/>
{props.buildBreadcrumbs(TITLE_TEXT_DICT[props.action])}
<EuiPageHeader>
<EuiText size="xs" color="subdued" className="panel-header-subtext">
<EuiTitle size="m">
<h1>{TITLE_TEXT_DICT[props.action]}</h1>
</EuiTitle>
Roles are the core way of controlling access to your cluster. Roles contain any
combination of cluster-wide permission, index-specific permissions, document- and
field-level security, and tenants. Once you&apos;ve created the role, you can map users to
the roles so that users gain those permissions.{' '}
<ExternalLink href={DocLinks.UsersAndRolesDoc} />
</EuiText>
</EuiPageHeader>
{updatedUX ? (
<>
<HeaderTitle
navigation={props.depsStart.navigation}
pageHeader={TITLE_TEXT_DICT[props.action]}
application={props.coreStart.application}
/>
<HeaderDescription
navigation={props.depsStart.navigation}
description=""
application={props.coreStart.application}
controls={descriptionData}
/>
</>
) : (
<>
{' '}
{props.buildBreadcrumbs(TITLE_TEXT_DICT[props.action])}
<EuiPageHeader>
<EuiText size="xs" color="subdued" className="panel-header-subtext">
<EuiTitle size="m">
<h1>{TITLE_TEXT_DICT[props.action]}</h1>
</EuiTitle>
Roles are the core way of controlling access to your cluster. Roles contain any
combination of cluster-wide permission, index-specific permissions, document- and
field-level security, and tenants. Once you&apos;ve created the role, you can map
users to the roles so that users gain those permissions.{' '}
<ExternalLink href={DocLinks.UsersAndRolesDoc} />
</EuiText>
</EuiPageHeader>
</>
)}
<PanelWithHeader headerText="Name">
<EuiForm>
<NameRow
Expand Down
141 changes: 102 additions & 39 deletions public/apps/configuration/panels/role-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import { DocLinks } from '../constants';
import { DataSourceContext } from '../app-router';
import { SecurityPluginTopNavMenu } from '../top-nav-menu';
import { AccessErrorComponent } from '../access-error-component';
import { HeaderTitle, HeaderDescription, HeaderButtonOrLink } from '../header/header-components';

const columns: Array<EuiBasicTableColumn<RoleListing>> = [
{
Expand Down Expand Up @@ -198,6 +199,9 @@ export function RoleList(props: AppDependencies) {

const [searchOptions, setSearchOptions] = useState<EuiSearchBarProps>({});
const [query, setQuery] = useState<Query | null>(null);

const updatedUX = props.coreStart.uiSettings.get('home:useNewHomePage');

useEffect(() => {
setSearchOptions({
onChange: (arg) => {
Expand Down Expand Up @@ -260,6 +264,37 @@ export function RoleList(props: AppDependencies) {
});
}, [roleData]);

const buttonData = [
{
label: 'Create role',
isLoading: false,
href: buildHashUrl(ResourceType.roles, Action.create),
fill: true,
iconType: 'plus',
iconSide: 'left',
type: 'button',
testId: 'create-role',
// target: "_blank"
},
];
const descriptionData = [
{
isLoading: loading,
renderComponent: (
<EuiText size="xs" color="subdued">
Roles are the core way of controlling access to your cluster. Roles contain any
combination of cluster-wide permission, index-
<br />
specific permissions, document- and field-level security, and tenants. Then you map users
to these roles so that users <br />
gain those permissions. <ExternalLink href={DocLinks.UsersAndRolesDoc} />
</EuiText>
),
},
];

const roleLen = Query.execute(query || '', roleData).length;

return (
<>
<SecurityPluginTopNavMenu
Expand All @@ -268,50 +303,75 @@ export function RoleList(props: AppDependencies) {
setDataSource={setDataSource}
selectedDataSource={dataSource}
/>
<EuiPageHeader>
<EuiTitle size="l">
<h1>Roles</h1>
</EuiTitle>
</EuiPageHeader>
{updatedUX ? (
<>
<HeaderTitle
navigation={props.depsStart.navigation}
pageHeader="Roles"
shouldDisplayCount={true}
count={roleLen}
application={props.coreStart.application}
/>
<HeaderDescription
navigation={props.depsStart.navigation}
description=""
application={props.coreStart.application}
controls={descriptionData}
/>
<HeaderButtonOrLink
navigation={props.depsStart.navigation}
controls={buttonData}
application={props.coreStart.application}
/>
</>
) : (
<EuiPageHeader>
<EuiTitle size="l">
<h1>Roles</h1>
</EuiTitle>
</EuiPageHeader>
)}
{loading ? (
<EuiLoadingContent />
) : accessErrorFlag ? (
<AccessErrorComponent loading={loading} dataSourceLabel={dataSource && dataSource.label} />
) : (
<EuiPageContent>
<EuiPageContentHeader id="role-table-container">
<EuiPageContentHeaderSection>
<EuiTitle size="s">
<h3>
Roles
<span className="panel-header-count">
{' '}
({Query.execute(query || '', roleData).length})
</span>
</h3>
</EuiTitle>
<EuiText size="xs" color="subdued">
Roles are the core way of controlling access to your cluster. Roles contain any
combination of cluster-wide permission, index-specific permissions, document- and
field-level security, and tenants. Then you map users to these roles so that users
gain those permissions. <ExternalLink href={DocLinks.UsersAndRolesDoc} />
</EuiText>
</EuiPageContentHeaderSection>
<EuiPageContentHeaderSection>
<EuiFlexGroup>
<EuiFlexItem>{actionsMenu}</EuiFlexItem>
<EuiFlexItem>
<EuiSmallButton
fill
href={buildHashUrl(ResourceType.roles, Action.create)}
data-test-subj="create-role"
>
Create role
</EuiSmallButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageContentHeaderSection>
</EuiPageContentHeader>
{updatedUX ? null : (
<EuiPageContentHeader id="role-table-container">
<EuiPageContentHeaderSection>
<EuiTitle size="s">
<h3>
Roles
<span className="panel-header-count">
{' '}
({Query.execute(query || '', roleData).length})
</span>
</h3>
</EuiTitle>
<EuiText size="xs" color="subdued">
Roles are the core way of controlling access to your cluster. Roles contain any
combination of cluster-wide permission, index-specific permissions, document- and
field-level security, and tenants. Then you map users to these roles so that users
gain those permissions. <ExternalLink href={DocLinks.UsersAndRolesDoc} />
</EuiText>
</EuiPageContentHeaderSection>
<EuiPageContentHeaderSection>
<EuiFlexGroup>
<EuiFlexItem>{actionsMenu}</EuiFlexItem>
<EuiFlexItem>
<EuiSmallButton
fill
href={buildHashUrl(ResourceType.roles, Action.create)}
data-test-subj="create-role"
>
Create role
</EuiSmallButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageContentHeaderSection>
</EuiPageContentHeader>
)}
<EuiPageBody>
<EuiInMemoryTable
data-test-subj="role-list"
Expand All @@ -323,7 +383,10 @@ export function RoleList(props: AppDependencies) {
pagination={true}
selection={{ onSelectionChange: setSelection }}
sorting={true}
search={searchOptions}
search={{
...searchOptions,
toolsRight: updatedUX ? [<EuiFlexItem>{actionsMenu}</EuiFlexItem>] : undefined,
}}
error={errorFlag ? 'Load data failed, please check console log for more detail.' : ''}
message={showTableStatusMessage(loading, roleData)}
/>
Expand Down
90 changes: 80 additions & 10 deletions public/apps/configuration/panels/role-view/role-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import { setCrossPageToast } from '../../utils/storage-utils';
import { DataSourceContext } from '../../app-router';
import { SecurityPluginTopNavMenu } from '../../top-nav-menu';
import { getClusterInfo } from '../../../../utils/datasource-utils';
import { HeaderTitle, HeaderButtonOrLink } from '../../header/header-components';

interface RoleViewProps extends BreadcrumbsPageDependencies {
roleName: string;
Expand Down Expand Up @@ -378,6 +379,7 @@ export function RoleView(props: RoleViewProps) {
</EuiSmallButtonEmpty>,
];
const [actionsMenu] = useContextMenuState('Actions', {}, actionsMenuItems);
const updatedUX = props.coreStart.uiSettings.get('home:useNewHomePage');

if (isReserved) {
pageActions = <EuiSmallButton href={duplicateRoleLink}>Duplicate role</EuiSmallButton>;
Expand All @@ -394,6 +396,58 @@ export function RoleView(props: RoleViewProps) {
);
}

const reservedRoleButtons = [
{
label: 'Duplicate role',
isLoading: false,
href: buildHashUrl(ResourceType.roles, Action.edit, props.roleName),
type: 'button',
fill: true,
// target: "_blank"
},
];
const roleButtons = [
{
isLoading: false,
run: async () => {
try {
await requestDeleteRoles(props.coreStart.http, [props.roleName], dataSource.id);
setCrossPageToast(buildUrl(ResourceType.roles), {
id: 'deleteRole',
color: 'success',
title: `${props.roleName} deleted ${getClusterInfo(dataSourceEnabled, dataSource)}`,
});
window.location.href = buildHashUrl(ResourceType.roles);
} catch (e) {
addToast(createUnknownErrorToast('deleteRole', 'delete role'));
}
},
iconType: 'trash',
color: 'danger',
type: 'button', // this should be icon, but icons current do not support a border currently
testId: 'delete',
ariaLabel: 'delete',
// target: "_blank"
},
{
label: 'Duplicate',
isLoading: false,
href: duplicateRoleLink,
type: 'button',
// target: "_blank"
},
{
label: 'Edit role',
isLoading: false,
href: buildHashUrl(ResourceType.roles, Action.edit, props.roleName),
fill: true,
type: 'button',
// target: "_blank"
},
];

const roleView = isReserved ? reservedRoleButtons : roleButtons;

return (
<>
<SecurityPluginTopNavMenu
Expand All @@ -402,18 +456,34 @@ export function RoleView(props: RoleViewProps) {
setDataSource={setDataSource}
selectedDataSource={dataSource}
/>
{props.buildBreadcrumbs(props.roleName)}

<EuiPageContentHeader>
<EuiPageContentHeaderSection>
<EuiTitle size="l">
<h1>{props.roleName}</h1>
</EuiTitle>
</EuiPageContentHeaderSection>
{updatedUX ? (
<>
<HeaderTitle
navigation={props.depsStart.navigation}
pageHeader={props.roleName}
application={props.coreStart.application}
/>
<HeaderButtonOrLink
navigation={props.depsStart.navigation}
controls={roleView}
application={props.coreStart.application}
/>
</>
) : (
<>
{props.buildBreadcrumbs(props.roleName)}

<EuiPageContentHeaderSection>{pageActions}</EuiPageContentHeaderSection>
</EuiPageContentHeader>
<EuiPageContentHeader>
<EuiPageContentHeaderSection>
<EuiTitle size="l">
<h1>{props.roleName}</h1>
</EuiTitle>
</EuiPageContentHeaderSection>

<EuiPageContentHeaderSection>{pageActions}</EuiPageContentHeaderSection>
</EuiPageContentHeader>
</>
)}
<EuiTabbedContent
tabs={tabs}
initialSelectedTab={
Expand Down
2 changes: 1 addition & 1 deletion public/apps/configuration/utils/context-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function useContextMenuState(
iconType={updatedUX ? 'plus' : 'arrowDown'}
iconSide={updatedUX ? 'left' : 'right'}
onClick={() => {
setContextMenuOpen(true);
setContextMenuOpen(!isContextMenuOpen);
}}
{...buttonProps}
>
Expand Down

0 comments on commit d4e5da3

Please sign in to comment.