= ({
+ accessItemKey,
+ accessHeader,
+ roleMappings,
+ addMappingButton,
+ getRoleMappingPath,
+ shouldShowAuthProvider,
+}) => {
+ const [filterValue, updateValue] = useState('');
+
+ // This is needed because App Search has `engines` and Workplace Search has `groups`.
+ const standardizeRoleMapping = (roleMappings as SharedRoleMapping[]).map((rm) => {
+ const _rm = { ...rm } as SharedRoleMapping;
+ _rm.accessItems = rm[accessItemKey];
+ return _rm;
+ });
+
+ const filterResults = (result: SharedRoleMapping) => {
+ const values = Object.values(result);
+ const regexp = new RegExp(filterValue, 'i');
+ return values.filter((x) => regexp.test(x)).length > 0;
+ };
+
+ const filteredResults = standardizeRoleMapping.filter(filterResults);
+ const getFirstAttributeName = (rules: RoleRules): string => Object.entries(rules)[0][0];
+ const getFirstAttributeValue = (rules: RoleRules): string => Object.entries(rules)[0][1];
+
+ return (
+ <>
+
+
+ updateValue(e.target.value)}
+ />
+
+ {addMappingButton}
+
+
+ {filteredResults.length > 0 ? (
+
+
+ {EXTERNAL_ATTRIBUTE_LABEL}
+ {ATTRIBUTE_VALUE_LABEL}
+ {ROLE_LABEL}
+ {accessHeader}
+ {shouldShowAuthProvider && (
+ {AUTH_PROVIDER_LABEL}
+ )}
+
+
+
+ {filteredResults.map(
+ ({ id, authProvider, rules, roleType, accessAllEngines, accessItems, toolTip }) => (
+
+ {getFirstAttributeName(rules)}
+
+ {getFirstAttributeValue(rules)}
+
+ {roleType}
+
+ {accessAllEngines ? (
+ ALL_LABEL
+ ) : (
+ <>
+ {accessItems.length === 0
+ ? noItemsPlaceholder
+ : accessItems.map(({ name }) => (
+
+ {name}
+
+
+ ))}
+ >
+ )}
+
+ {shouldShowAuthProvider && (
+
+ {authProvider.map(getAuthProviderDisplayValue).join(', ')}
+
+ )}
+
+ {id && (
+
+ {MANAGE_ROLE_MAPPING_BUTTON}
+
+ )}
+ {toolTip && }
+
+
+ )
+ )}
+
+
+ ) : (
+
+ {i18n.translate('xpack.enterpriseSearch.roleMapping.moResults.message', {
+ defaultMessage: "No results found for '{filterValue}'",
+ values: { filterValue },
+ })}
+
+ )}
+ >
+ );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_selector.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_selector.test.tsx
new file mode 100644
index 0000000000000..cceac99430bb6
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_selector.test.tsx
@@ -0,0 +1,56 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { shallow } from 'enzyme';
+
+import { EuiRadio, EuiCallOut } from '@elastic/eui';
+
+import { RoleSelector } from './role_selector';
+
+describe('RoleSelector', () => {
+ const onChange = jest.fn();
+
+ const props = {
+ disabled: false,
+ disabledText: 'Disabled',
+ roleType: 'user',
+ roleTypeOption: 'option',
+ description: 'This a thing',
+ onChange,
+ };
+
+ it('renders', () => {
+ const wrapper = shallow();
+
+ expect(wrapper.find(EuiRadio)).toHaveLength(1);
+ });
+
+ it('calls method on change', () => {
+ const wrapper = shallow();
+ const radio = wrapper.find(EuiRadio);
+ radio.simulate('change', { target: { value: 'bar' } });
+
+ expect(onChange).toHaveBeenCalled();
+ });
+
+ it('renders callout when disabled', () => {
+ const wrapper = shallow();
+ const radio = wrapper.find(EuiRadio);
+
+ expect(radio.dive().find(EuiCallOut)).toHaveLength(1);
+ expect(wrapper.find(EuiRadio).prop('checked')).toEqual(false);
+ });
+
+ it('sets checked attribute on radio when option matched type', () => {
+ const wrapper = shallow();
+ const radio = wrapper.find(EuiRadio);
+
+ expect(radio.prop('checked')).toEqual(true);
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_selector.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_selector.tsx
new file mode 100644
index 0000000000000..a0e75a1b6aca2
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_selector.tsx
@@ -0,0 +1,67 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { startCase } from 'lodash';
+
+import {
+ EuiCallOut,
+ EuiFormRow,
+ EuiRadio,
+ EuiSpacer,
+ EuiText,
+ EuiTextColor,
+ EuiTitle,
+} from '@elastic/eui';
+
+interface Props {
+ disabled?: boolean;
+ disabledText?: string;
+ roleType?: string;
+ roleTypeOption: string;
+ description: string;
+ onChange(roleTypeOption: string): void;
+}
+
+export const RoleSelector: React.FC = ({
+ disabled,
+ disabledText,
+ roleType,
+ roleTypeOption,
+ description,
+ onChange,
+}) => (
+
+ {
+ onChange(roleTypeOption);
+ }}
+ label={
+ <>
+
+ {startCase(roleTypeOption)}
+
+ {disabled && disabledText && (
+ {disabledText}}
+ iconType="alert"
+ />
+ )}
+
+
+ {description}
+
+ >
+ }
+ />
+
+);
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/types.ts b/x-pack/plugins/enterprise_search/public/applications/shared/types.ts
index d024c72bcf230..16a9e3b54aea5 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/types.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/types.ts
@@ -43,3 +43,19 @@ export interface IndexJob extends IIndexingStatus {
}
export type TOperation = typeof ADD | typeof UPDATE;
+
+export interface RoleRules {
+ username?: string;
+ role?: string;
+ email?: string;
+ metadata?: string;
+}
+
+export interface RoleMapping {
+ id: string;
+ attributeName: string;
+ attributeValue: string;
+ authProvider: string[];
+ roleType: string;
+ rules: RoleRules;
+}
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts
index 404011b10f456..44e0fd5b6f287 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts
@@ -5,6 +5,8 @@
* 2.0.
*/
+import { RoleMapping } from '../shared/types';
+
export * from '../../../common/types/workplace_search';
export type SpacerSizeTypes = 'xs' | 's' | 'm' | 'l' | 'xl' | 'xxl';
@@ -203,3 +205,13 @@ export interface SearchResultConfig {
color: string;
detailFields: DetailField[];
}
+
+export interface RoleGroup {
+ id: string;
+ name: string;
+}
+
+export interface WSRoleMapping extends RoleMapping {
+ allGroups: boolean;
+ groups: RoleGroup[];
+}