From 85619c888617d75f6e26aaf8caa9992be0683af9 Mon Sep 17 00:00:00 2001 From: Derek Ho Date: Tue, 12 Sep 2023 10:34:15 -0400 Subject: [PATCH 1/9] basic rendering for the access control tab Signed-off-by: Derek Ho --- .../components/access_control_callout.tsx | 27 +++ .../components/access_control_tab.tsx | 171 ++++++++++++++++++ .../components/datasource.tsx | 9 +- .../components/datasources_header.tsx | 2 +- 4 files changed, 206 insertions(+), 3 deletions(-) create mode 100644 public/components/data_connections/components/access_control_callout.tsx create mode 100644 public/components/data_connections/components/access_control_tab.tsx diff --git a/public/components/data_connections/components/access_control_callout.tsx b/public/components/data_connections/components/access_control_callout.tsx new file mode 100644 index 0000000000..0ff69317a1 --- /dev/null +++ b/public/components/data_connections/components/access_control_callout.tsx @@ -0,0 +1,27 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiCallOut, + EuiLink, + EuiPageHeader, + EuiPageHeaderSection, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; +import _ from 'lodash'; +import React, { useState } from 'react'; +import { EuiPanel } from '@elastic/eui'; +import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../common/constants/data_connections'; + +export const AccessControlCallout = () => { + return ( + + Access to data can be managed in other systems outside of OpenSearch. Check with your + administrator for additional configurations. + + ); +}; diff --git a/public/components/data_connections/components/access_control_tab.tsx b/public/components/data_connections/components/access_control_tab.tsx new file mode 100644 index 0000000000..fdc8b381ac --- /dev/null +++ b/public/components/data_connections/components/access_control_tab.tsx @@ -0,0 +1,171 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiButton, + EuiFlexGroup, + EuiFlexItem, + EuiLink, + EuiPageHeader, + EuiPageHeaderSection, + EuiSpacer, + EuiText, + EuiTitle, + EuiHorizontalRule, + htmlIdGenerator, + EuiRadioGroup, + EuiComboBox, +} from '@elastic/eui'; +import _ from 'lodash'; +import React, { useEffect, useState } from 'react'; +import { EuiPanel } from '@elastic/eui'; +import { render } from 'mustache'; +import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../common/constants/data_connections'; +import { AccessControlCallout } from './access_control_callout'; +import { coreRefs } from '../../../../public/framework/core_refs'; + +const idPrefix = htmlIdGenerator()(); + +export const AccessControlTab = () => { + const [mode, setMode] = useState<'view' | 'edit'>('edit'); + const [roles, setRoles] = useState>([]); + + useEffect(() => { + coreRefs.http!.get('/api/v1/configuration/roles').then((data) => + setRoles( + Object.keys(data.data).map((key) => { + return { label: key }; + }) + ) + ); + }, []); + + const radios = [ + { + id: `${idPrefix}0`, + label: 'Restricted - accessible by users with specific OpenSearch roles', + }, + { + id: `${idPrefix}1`, + label: 'Everyone - accessible by all users on this cluster', + }, + ]; + + const [radioIdSelected, setRadioIdSelected] = useState(`${idPrefix}1`); + + const onChange = (optionId) => { + setRadioIdSelected(optionId); + }; + + const renderViewAccessControlDetails = () => { + return ( + + + + + Query access + + {'-'} + + + + + + + + Acceleration permissions + + {'-'} + + + + + + ); + }; + + const renderEditAccessControlDetails = () => { + return ( + + + + + Query Permissions + + Control which OpenSearch roles have query permissions on this data source.{' '} + + Learn more + + + + + onChange(id)} + name="radio group" + legend={{ + children: Access level, + }} + /> + {radioIdSelected === `${idPrefix}0` ? ( + {}} + isClearable={true} + data-test-subj="demoComboBox" + autoFocus + /> + ) : ( + <> + )} + + + + + ); + }; + + return ( + <> + + + + + + + +

Access Control

+ Control which OpenSearch users have access to this data source. +
+
+ + + { + setMode('view'); + } + : () => { + setMode('edit'); + } + } + fill={mode === 'edit' ? true : false} + > + {mode === 'edit' ? 'Edit' : 'View'} + + +
+ + {mode === 'edit' ? renderViewAccessControlDetails() : renderEditAccessControlDetails()} +
+ + ); +}; diff --git a/public/components/data_connections/components/datasource.tsx b/public/components/data_connections/components/datasource.tsx index 19c6b9fbec..25b2c0bfa1 100644 --- a/public/components/data_connections/components/datasource.tsx +++ b/public/components/data_connections/components/datasource.tsx @@ -19,9 +19,11 @@ import { EuiCard, EuiTab, EuiTabs, + EuiTabbedContent, } from '@elastic/eui'; -import React, { useEffect, useState } from 'react'; +import React, { Fragment, useEffect, useState } from 'react'; import { DATASOURCES_BASE } from '../../../../common/constants/shared'; +import { AccessControlTab } from './access_control_tab'; interface DatasourceDetails { allowedRoles: string[]; @@ -52,16 +54,19 @@ export function DataSource(props: any) { id: 'data', name: 'Data', disabled: false, + content: <>, }, { id: 'access_control', name: 'Access control', disabled: false, + content: , }, { id: 'connection_configuration', name: 'Connection configuration', disabled: false, + content: <>, }, ]; @@ -169,7 +174,7 @@ export function DataSource(props: any) { - {renderTabs()} + diff --git a/public/components/data_connections/components/datasources_header.tsx b/public/components/data_connections/components/datasources_header.tsx index 8c0ceb7242..cde62fff5f 100644 --- a/public/components/data_connections/components/datasources_header.tsx +++ b/public/components/data_connections/components/datasources_header.tsx @@ -28,7 +28,7 @@ export function DataConnectionsHeader() { Connect and manage compatible OpenSearch Dashboard data sources and compute.{' '} - + Learn more From 4c720e2dca3230e42090fb3c96d52e5d5e015592 Mon Sep 17 00:00:00 2001 From: Derek Ho Date: Tue, 12 Sep 2023 12:10:31 -0400 Subject: [PATCH 2/9] hook up basic radio groups and euicombo boxes for query and acceleration permissions Signed-off-by: Derek Ho --- common/types/data_connections.ts | 15 ++++ .../acceleration_permissions_flex_item.tsx | 71 +++++++++++++++ .../components/access_control_tab.tsx | 88 ++++++++----------- .../query_permissions_flex_item.tsx | 70 +++++++++++++++ 4 files changed, 195 insertions(+), 49 deletions(-) create mode 100644 common/types/data_connections.ts create mode 100644 public/components/data_connections/components/acceleration_permissions_flex_item.tsx create mode 100644 public/components/data_connections/components/query_permissions_flex_item.tsx diff --git a/common/types/data_connections.ts b/common/types/data_connections.ts new file mode 100644 index 0000000000..5201b5b879 --- /dev/null +++ b/common/types/data_connections.ts @@ -0,0 +1,15 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { EuiRadioGroupOption } from '@elastic/eui'; + +export interface PermissionsFlexItem { + roles: Array<{ label: string }>; + selectedRoles: Array<{ label: string }>; + selectedRadio: string; + setSelectedRoles: (selectedRoles: Array<{ label: string }>) => void; + setSelectedRadio: (selectedRadio: string) => void; + radios: EuiRadioGroupOption[]; +} diff --git a/public/components/data_connections/components/acceleration_permissions_flex_item.tsx b/public/components/data_connections/components/acceleration_permissions_flex_item.tsx new file mode 100644 index 0000000000..ab173c4189 --- /dev/null +++ b/public/components/data_connections/components/acceleration_permissions_flex_item.tsx @@ -0,0 +1,71 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiComboBox, + EuiFlexGroup, + EuiFlexItem, + EuiLink, + EuiPageHeader, + EuiPageHeaderSection, + EuiRadioGroup, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; +import _ from 'lodash'; +import React from 'react'; +import { PermissionsFlexItem } from 'common/types/data_connections'; +import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../common/constants/data_connections'; + +export const AccelerationPermissionsFlexItem = (props: PermissionsFlexItem) => { + const { roles, setSelectedRoles, selectedRoles, selectedRadio, radios, setSelectedRadio } = props; + return ( + + + + Acceleration Permissions + + Control which OpenSearch roles have permissions to accelerate external data through + OpenSearch indexing.{' '} + + Learn more + + + + + setSelectedRadio(id)} + name="acceleration-radio-group" + legend={{ + children: Access level, + }} + /> + {selectedRadio === `0` ? ( +
+ + OpenSearch Roles + + Select one or more OpenSearch roles that can query this data connection. + + +
+ ) : ( + <> + )} +
+
+
+ ); +}; diff --git a/public/components/data_connections/components/access_control_tab.tsx b/public/components/data_connections/components/access_control_tab.tsx index fdc8b381ac..5afea06706 100644 --- a/public/components/data_connections/components/access_control_tab.tsx +++ b/public/components/data_connections/components/access_control_tab.tsx @@ -25,12 +25,20 @@ import { render } from 'mustache'; import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../common/constants/data_connections'; import { AccessControlCallout } from './access_control_callout'; import { coreRefs } from '../../../../public/framework/core_refs'; - -const idPrefix = htmlIdGenerator()(); +import { QueryPermissionsFlexItem } from './query_permissions_flex_item'; +import { AccelerationPermissionsFlexItem } from './acceleration_permissions_flex_item'; export const AccessControlTab = () => { const [mode, setMode] = useState<'view' | 'edit'>('edit'); const [roles, setRoles] = useState>([]); + const [selectedQueryPermissionRoles, setSelectedQueryPermissionRoles] = useState< + Array<{ label: string }> + >([]); + const [selectedAccelerationPermissionRoles, setSelectedAccelerationPermissionRoles] = useState< + Array<{ label: string }> + >([]); + const [queryPermissionRadioSelected, setQueryRadioIdSelected] = useState(`1`); + const [accelerationPermissionRadioSelected, setAccelerationRadioIdSelected] = useState(`1`); useEffect(() => { coreRefs.http!.get('/api/v1/configuration/roles').then((data) => @@ -44,20 +52,24 @@ export const AccessControlTab = () => { const radios = [ { - id: `${idPrefix}0`, + id: `0`, label: 'Restricted - accessible by users with specific OpenSearch roles', }, { - id: `${idPrefix}1`, + id: `1`, + label: 'Everyone - accessible by all users on this cluster', + }, + ]; + const radios2 = [ + { + id: `0`, + label: 'Restricted - accessible by users with specific OpenSearch roles', + }, + { + id: `1`, label: 'Everyone - accessible by all users on this cluster', }, ]; - - const [radioIdSelected, setRadioIdSelected] = useState(`${idPrefix}1`); - - const onChange = (optionId) => { - setRadioIdSelected(optionId); - }; const renderViewAccessControlDetails = () => { return ( @@ -88,45 +100,23 @@ export const AccessControlTab = () => { const renderEditAccessControlDetails = () => { return ( - - - - - Query Permissions - - Control which OpenSearch roles have query permissions on this data source.{' '} - - Learn more - - - - - onChange(id)} - name="radio group" - legend={{ - children: Access level, - }} - /> - {radioIdSelected === `${idPrefix}0` ? ( - {}} - isClearable={true} - data-test-subj="demoComboBox" - autoFocus - /> - ) : ( - <> - )} - - - + + + ); }; diff --git a/public/components/data_connections/components/query_permissions_flex_item.tsx b/public/components/data_connections/components/query_permissions_flex_item.tsx new file mode 100644 index 0000000000..bd9d7dfe81 --- /dev/null +++ b/public/components/data_connections/components/query_permissions_flex_item.tsx @@ -0,0 +1,70 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiComboBox, + EuiFlexGroup, + EuiFlexItem, + EuiLink, + EuiPageHeader, + EuiPageHeaderSection, + EuiRadioGroup, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; +import _ from 'lodash'; +import React from 'react'; +import { PermissionsFlexItem } from 'common/types/data_connections'; +import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../common/constants/data_connections'; + +export const QueryPermissionsFlexItem = (props: PermissionsFlexItem) => { + const { roles, setSelectedRoles, selectedRoles, selectedRadio, radios, setSelectedRadio } = props; + return ( + + + + Query Permissions + + Control which OpenSearch roles have query permissions on this data source.{' '} + + Learn more + + + + + setSelectedRadio(id)} + name="query-radio-group" + legend={{ + children: Access level, + }} + /> + {selectedRadio === `0` ? ( +
+ + OpenSearch Roles + + Select one or more OpenSearch roles that can query this data connection. + + +
+ ) : ( + <> + )} +
+
+
+ ); +}; From 5337b7152b93ee2e0ae7ce808a6bfe5b3532ce0c Mon Sep 17 00:00:00 2001 From: Derek Ho Date: Tue, 12 Sep 2023 13:56:03 -0400 Subject: [PATCH 3/9] refactor and clean up unuseed inports Signed-off-by: Derek Ho --- common/constants/data_connections.ts | 5 + .../acceleration_permissions_flex_item.tsx | 13 ++- .../components/access_control_callout.tsx | 15 +-- .../components/access_control_tab.tsx | 102 +++++++++++++----- .../query_permissions_flex_item.tsx | 13 ++- 5 files changed, 92 insertions(+), 56 deletions(-) diff --git a/common/constants/data_connections.ts b/common/constants/data_connections.ts index 354d797de9..4231772996 100644 --- a/common/constants/data_connections.ts +++ b/common/constants/data_connections.ts @@ -8,3 +8,8 @@ export const OPENSEARCH_DOCUMENTATION_URL = export const OPENSEARCH_ACC_DOCUMENTATION_URL = 'https://opensearch.org/docs/latest/data-acceleration/index'; + +export const QUERY_RESTRICT = 'query-restrict'; +export const QUERY_ALL = 'query-all'; +export const ACCELERATION_RESTRICT = 'acceleration-restrict'; +export const ACCELERATION_ALL = 'acceleration-all'; diff --git a/public/components/data_connections/components/acceleration_permissions_flex_item.tsx b/public/components/data_connections/components/acceleration_permissions_flex_item.tsx index ab173c4189..61b00dd15b 100644 --- a/public/components/data_connections/components/acceleration_permissions_flex_item.tsx +++ b/public/components/data_connections/components/acceleration_permissions_flex_item.tsx @@ -8,17 +8,16 @@ import { EuiFlexGroup, EuiFlexItem, EuiLink, - EuiPageHeader, - EuiPageHeaderSection, EuiRadioGroup, EuiSpacer, EuiText, - EuiTitle, } from '@elastic/eui'; -import _ from 'lodash'; import React from 'react'; -import { PermissionsFlexItem } from 'common/types/data_connections'; -import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../common/constants/data_connections'; +import { PermissionsFlexItem } from '../../../../common/types/data_connections'; +import { + OPENSEARCH_DOCUMENTATION_URL, + QUERY_ALL, +} from '../../../../common/constants/data_connections'; export const AccelerationPermissionsFlexItem = (props: PermissionsFlexItem) => { const { roles, setSelectedRoles, selectedRoles, selectedRadio, radios, setSelectedRadio } = props; @@ -45,7 +44,7 @@ export const AccelerationPermissionsFlexItem = (props: PermissionsFlexItem) => { children: Access level, }} /> - {selectedRadio === `0` ? ( + {selectedRadio === QUERY_ALL ? (
OpenSearch Roles diff --git a/public/components/data_connections/components/access_control_callout.tsx b/public/components/data_connections/components/access_control_callout.tsx index 0ff69317a1..f675673ffc 100644 --- a/public/components/data_connections/components/access_control_callout.tsx +++ b/public/components/data_connections/components/access_control_callout.tsx @@ -3,19 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { - EuiCallOut, - EuiLink, - EuiPageHeader, - EuiPageHeaderSection, - EuiSpacer, - EuiText, - EuiTitle, -} from '@elastic/eui'; -import _ from 'lodash'; -import React, { useState } from 'react'; -import { EuiPanel } from '@elastic/eui'; -import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../common/constants/data_connections'; +import { EuiCallOut } from '@elastic/eui'; +import React from 'react'; export const AccessControlCallout = () => { return ( diff --git a/public/components/data_connections/components/access_control_tab.tsx b/public/components/data_connections/components/access_control_tab.tsx index 5afea06706..c46d280f53 100644 --- a/public/components/data_connections/components/access_control_tab.tsx +++ b/public/components/data_connections/components/access_control_tab.tsx @@ -7,29 +7,27 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem, - EuiLink, - EuiPageHeader, - EuiPageHeaderSection, EuiSpacer, EuiText, - EuiTitle, EuiHorizontalRule, - htmlIdGenerator, - EuiRadioGroup, - EuiComboBox, + EuiBottomBar, + EuiButtonEmpty, } from '@elastic/eui'; -import _ from 'lodash'; import React, { useEffect, useState } from 'react'; import { EuiPanel } from '@elastic/eui'; -import { render } from 'mustache'; -import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../common/constants/data_connections'; +import { + ACCELERATION_ALL, + ACCELERATION_RESTRICT, + QUERY_ALL, + QUERY_RESTRICT, +} from 'common/constants/data_connections'; import { AccessControlCallout } from './access_control_callout'; import { coreRefs } from '../../../../public/framework/core_refs'; import { QueryPermissionsFlexItem } from './query_permissions_flex_item'; import { AccelerationPermissionsFlexItem } from './acceleration_permissions_flex_item'; export const AccessControlTab = () => { - const [mode, setMode] = useState<'view' | 'edit'>('edit'); + const [mode, setMode] = useState<'view' | 'edit'>('view'); const [roles, setRoles] = useState>([]); const [selectedQueryPermissionRoles, setSelectedQueryPermissionRoles] = useState< Array<{ label: string }> @@ -37,8 +35,18 @@ export const AccessControlTab = () => { const [selectedAccelerationPermissionRoles, setSelectedAccelerationPermissionRoles] = useState< Array<{ label: string }> >([]); - const [queryPermissionRadioSelected, setQueryRadioIdSelected] = useState(`1`); - const [accelerationPermissionRadioSelected, setAccelerationRadioIdSelected] = useState(`1`); + const [queryPermissionRadioSelected, setQueryRadioIdSelected] = useState(`query-1`); + const [accelerationPermissionRadioSelected, setAccelerationRadioIdSelected] = useState( + `acceleration-1` + ); + + const [finalQueryPermissionsPlaceHolder, setFinalQueryPermissionsPlaceHolder] = useState< + Array<{ label: string }> + >([]); + const [ + finalAccelerationPermissionsPlaceHolder, + setFinalAccelerationPermissionsPlaceHolder, + ] = useState>([]); useEffect(() => { coreRefs.http!.get('/api/v1/configuration/roles').then((data) => @@ -50,23 +58,23 @@ export const AccessControlTab = () => { ); }, []); - const radios = [ + const queryRadios = [ { - id: `0`, + id: QUERY_RESTRICT, label: 'Restricted - accessible by users with specific OpenSearch roles', }, { - id: `1`, + id: QUERY_ALL, label: 'Everyone - accessible by all users on this cluster', }, ]; - const radios2 = [ + const accelerationRadios = [ { - id: `0`, + id: ACCELERATION_RESTRICT, label: 'Restricted - accessible by users with specific OpenSearch roles', }, { - id: `1`, + id: ACCELERATION_ALL, label: 'Everyone - accessible by all users on this cluster', }, ]; @@ -79,7 +87,9 @@ export const AccessControlTab = () => { Query access - {'-'} + {finalQueryPermissionsPlaceHolder.length + ? `Restricted to ${finalQueryPermissionsPlaceHolder.map((role) => role.label)}` + : '-'} @@ -89,7 +99,11 @@ export const AccessControlTab = () => { Acceleration permissions - {'-'} + {finalAccelerationPermissionsPlaceHolder.length + ? `Restricted to ${finalAccelerationPermissionsPlaceHolder.map( + (role) => role.label + )}` + : '-'} @@ -107,7 +121,7 @@ export const AccessControlTab = () => { setSelectedRoles={setSelectedQueryPermissionRoles} selectedRadio={queryPermissionRadioSelected} setSelectedRadio={setQueryRadioIdSelected} - radios={radios} + radios={queryRadios} /> { setSelectedRoles={setSelectedAccelerationPermissionRoles} selectedRadio={accelerationPermissionRadioSelected} setSelectedRadio={setAccelerationRadioIdSelected} - radios={radios2} + radios={accelerationRadios} /> ); }; + const saveChanges = () => { + setFinalAccelerationPermissionsPlaceHolder(selectedAccelerationPermissionRoles); + setFinalQueryPermissionsPlaceHolder(selectedQueryPermissionRoles); + setMode('view'); + }; + return ( <> @@ -139,23 +159,47 @@ export const AccessControlTab = () => { { - setMode('view'); + setMode('edit'); } : () => { - setMode('edit'); + setMode('view'); } } - fill={mode === 'edit' ? true : false} + fill={mode === 'view' ? true : false} > - {mode === 'edit' ? 'Edit' : 'View'} + {mode === 'view' ? 'Edit' : 'Cancel'} - {mode === 'edit' ? renderViewAccessControlDetails() : renderEditAccessControlDetails()} + {mode === 'view' ? renderViewAccessControlDetails() : renderEditAccessControlDetails()} + + {mode === 'edit' ? ( + + + + { + setMode('view'); + }} + color="ghost" + size="s" + iconType="cross" + > + Discard change(s) + + + + + Save + + + + + ) : null} ); }; diff --git a/public/components/data_connections/components/query_permissions_flex_item.tsx b/public/components/data_connections/components/query_permissions_flex_item.tsx index bd9d7dfe81..fb80f449b4 100644 --- a/public/components/data_connections/components/query_permissions_flex_item.tsx +++ b/public/components/data_connections/components/query_permissions_flex_item.tsx @@ -8,17 +8,16 @@ import { EuiFlexGroup, EuiFlexItem, EuiLink, - EuiPageHeader, - EuiPageHeaderSection, EuiRadioGroup, EuiSpacer, EuiText, - EuiTitle, } from '@elastic/eui'; -import _ from 'lodash'; import React from 'react'; -import { PermissionsFlexItem } from 'common/types/data_connections'; -import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../common/constants/data_connections'; +import { PermissionsFlexItem } from '../../../../common/types/data_connections'; +import { + OPENSEARCH_DOCUMENTATION_URL, + QUERY_RESTRICT, +} from '../../../../common/constants/data_connections'; export const QueryPermissionsFlexItem = (props: PermissionsFlexItem) => { const { roles, setSelectedRoles, selectedRoles, selectedRadio, radios, setSelectedRadio } = props; @@ -44,7 +43,7 @@ export const QueryPermissionsFlexItem = (props: PermissionsFlexItem) => { children: Access level, }} /> - {selectedRadio === `0` ? ( + {selectedRadio === QUERY_RESTRICT ? (
OpenSearch Roles From 9feb7dda357d16c70eeb5fdb70444e153d8abdba Mon Sep 17 00:00:00 2001 From: Derek Ho Date: Tue, 12 Sep 2023 13:57:49 -0400 Subject: [PATCH 4/9] remove unused import Signed-off-by: Derek Ho --- public/components/data_connections/components/datasource.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/public/components/data_connections/components/datasource.tsx b/public/components/data_connections/components/datasource.tsx index 2a4441ca64..b4c81c0831 100644 --- a/public/components/data_connections/components/datasource.tsx +++ b/public/components/data_connections/components/datasource.tsx @@ -18,10 +18,9 @@ import { EuiIcon, EuiCard, EuiTab, - EuiTabs, EuiTabbedContent, } from '@elastic/eui'; -import React, { Fragment, useEffect, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { DATASOURCES_BASE } from '../../../../common/constants/shared'; import { AccessControlTab } from './access_control_tab'; From 14f3ff27aa18969cce412e263b51f603e135b38c Mon Sep 17 00:00:00 2001 From: Derek Ho Date: Tue, 12 Sep 2023 14:47:01 -0400 Subject: [PATCH 5/9] fix import and snapshot Signed-off-by: Derek Ho --- .../__snapshots__/manage_datasource_table.test.tsx.snap | 9 +++++++-- .../data_connections/components/access_control_tab.tsx | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/public/components/data_connections/components/__tests__/__snapshots__/manage_datasource_table.test.tsx.snap b/public/components/data_connections/components/__tests__/__snapshots__/manage_datasource_table.test.tsx.snap index 8206d792b7..f22590ecd1 100644 --- a/public/components/data_connections/components/__tests__/__snapshots__/manage_datasource_table.test.tsx.snap +++ b/public/components/data_connections/components/__tests__/__snapshots__/manage_datasource_table.test.tsx.snap @@ -37,8 +37,8 @@ exports[`Manage Datasource Table test Renders manage datasource table with data Learn more + + (opens in a new tab or window) +
diff --git a/public/components/data_connections/components/access_control_tab.tsx b/public/components/data_connections/components/access_control_tab.tsx index c46d280f53..ff40edc43c 100644 --- a/public/components/data_connections/components/access_control_tab.tsx +++ b/public/components/data_connections/components/access_control_tab.tsx @@ -20,7 +20,7 @@ import { ACCELERATION_RESTRICT, QUERY_ALL, QUERY_RESTRICT, -} from 'common/constants/data_connections'; +} from '../../../../common/constants/data_connections'; import { AccessControlCallout } from './access_control_callout'; import { coreRefs } from '../../../../public/framework/core_refs'; import { QueryPermissionsFlexItem } from './query_permissions_flex_item'; From 7c40489d33e72bab3b28dbaa193b73d83ee674e3 Mon Sep 17 00:00:00 2001 From: Derek Ho Date: Tue, 12 Sep 2023 15:28:59 -0400 Subject: [PATCH 6/9] fix test Signed-off-by: Derek Ho --- .../__snapshots__/datasource.test.tsx.snap | 85 +++++++++++-------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/public/components/data_connections/components/__tests__/__snapshots__/datasource.test.tsx.snap b/public/components/data_connections/components/__tests__/__snapshots__/datasource.test.tsx.snap index 793dde1044..d4de273330 100644 --- a/public/components/data_connections/components/__tests__/__snapshots__/datasource.test.tsx.snap +++ b/public/components/data_connections/components/__tests__/__snapshots__/datasource.test.tsx.snap @@ -259,46 +259,59 @@ exports[`Datasource Page test Renders datasource page with data 1`] = ` -
- - + - + + + Connection configuration + + +
+
Date: Mon, 18 Sep 2023 10:42:09 -0400 Subject: [PATCH 7/9] Address PR comments Signed-off-by: Derek Ho --- common/types/data_connections.ts | 6 +- .../components/access_control_tab.tsx | 101 +++++------------- .../components/data_connection.tsx | 23 +++- .../data_connections/components/no_access.tsx | 2 +- ...ns_flex_item.tsx => query_permissions.tsx} | 2 +- server/adaptors/ppl_plugin.ts | 8 ++ .../data_connections_router.ts | 35 ++++++ 7 files changed, 93 insertions(+), 84 deletions(-) rename public/components/data_connections/components/{query_permissions_flex_item.tsx => query_permissions.tsx} (96%) diff --git a/common/types/data_connections.ts b/common/types/data_connections.ts index 5201b5b879..0bb50bc6ff 100644 --- a/common/types/data_connections.ts +++ b/common/types/data_connections.ts @@ -5,11 +5,11 @@ import { EuiRadioGroupOption } from '@elastic/eui'; -export interface PermissionsFlexItem { +export interface PermissionsConfiguration { roles: Array<{ label: string }>; selectedRoles: Array<{ label: string }>; selectedRadio: string; - setSelectedRoles: (selectedRoles: Array<{ label: string }>) => void; - setSelectedRadio: (selectedRadio: string) => void; + setSelectedRoles: React.Dispatch>>; + setSelectedRadio: React.Dispatch>; radios: EuiRadioGroupOption[]; } diff --git a/public/components/data_connections/components/access_control_tab.tsx b/public/components/data_connections/components/access_control_tab.tsx index ff40edc43c..b0b4318707 100644 --- a/public/components/data_connections/components/access_control_tab.tsx +++ b/public/components/data_connections/components/access_control_tab.tsx @@ -15,38 +15,25 @@ import { } from '@elastic/eui'; import React, { useEffect, useState } from 'react'; import { EuiPanel } from '@elastic/eui'; -import { - ACCELERATION_ALL, - ACCELERATION_RESTRICT, - QUERY_ALL, - QUERY_RESTRICT, -} from '../../../../common/constants/data_connections'; +import { QUERY_ALL, QUERY_RESTRICT } from '../../../../common/constants/data_connections'; import { AccessControlCallout } from './access_control_callout'; import { coreRefs } from '../../../../public/framework/core_refs'; -import { QueryPermissionsFlexItem } from './query_permissions_flex_item'; -import { AccelerationPermissionsFlexItem } from './acceleration_permissions_flex_item'; +import { QueryPermissionsConfiguration } from './query_permissions'; +import { DATACONNECTIONS_BASE } from '../../../../common/constants/shared'; + +interface AccessControlTabProps { + dataConnection: string; + connector: string; +} -export const AccessControlTab = () => { +export const AccessControlTab = (props: AccessControlTabProps) => { const [mode, setMode] = useState<'view' | 'edit'>('view'); const [roles, setRoles] = useState>([]); const [selectedQueryPermissionRoles, setSelectedQueryPermissionRoles] = useState< Array<{ label: string }> >([]); - const [selectedAccelerationPermissionRoles, setSelectedAccelerationPermissionRoles] = useState< - Array<{ label: string }> - >([]); const [queryPermissionRadioSelected, setQueryRadioIdSelected] = useState(`query-1`); - const [accelerationPermissionRadioSelected, setAccelerationRadioIdSelected] = useState( - `acceleration-1` - ); - - const [finalQueryPermissionsPlaceHolder, setFinalQueryPermissionsPlaceHolder] = useState< - Array<{ label: string }> - >([]); - const [ - finalAccelerationPermissionsPlaceHolder, - setFinalAccelerationPermissionsPlaceHolder, - ] = useState>([]); + const { http } = coreRefs; useEffect(() => { coreRefs.http!.get('/api/v1/configuration/roles').then((data) => @@ -68,18 +55,8 @@ export const AccessControlTab = () => { label: 'Everyone - accessible by all users on this cluster', }, ]; - const accelerationRadios = [ - { - id: ACCELERATION_RESTRICT, - label: 'Restricted - accessible by users with specific OpenSearch roles', - }, - { - id: ACCELERATION_ALL, - label: 'Everyone - accessible by all users on this cluster', - }, - ]; - const renderViewAccessControlDetails = () => { + const AccessControlDetails = () => { return ( @@ -87,23 +64,7 @@ export const AccessControlTab = () => { Query access - {finalQueryPermissionsPlaceHolder.length - ? `Restricted to ${finalQueryPermissionsPlaceHolder.map((role) => role.label)}` - : '-'} - - - - - - - - Acceleration permissions - - {finalAccelerationPermissionsPlaceHolder.length - ? `Restricted to ${finalAccelerationPermissionsPlaceHolder.map( - (role) => role.label - )}` - : '-'} + {[].length ? `Restricted` : '-'} @@ -112,10 +73,10 @@ export const AccessControlTab = () => { ); }; - const renderEditAccessControlDetails = () => { + const EditAccessControlDetails = () => { return ( - { setSelectedRadio={setQueryRadioIdSelected} radios={queryRadios} /> - ); }; const saveChanges = () => { - setFinalAccelerationPermissionsPlaceHolder(selectedAccelerationPermissionRoles); - setFinalQueryPermissionsPlaceHolder(selectedQueryPermissionRoles); + http!.put(`${DATACONNECTIONS_BASE}`, { + body: JSON.stringify({ + name: props.dataConnection, + allowedRoles: ['test'], + connector: props.connector, + }), + }); setMode('view'); }; @@ -158,15 +116,7 @@ export const AccessControlTab = () => { { - setMode('edit'); - } - : () => { - setMode('view'); - } - } + onClick={() => setMode(mode === 'view' ? 'edit' : 'view')} fill={mode === 'view' ? true : false} > {mode === 'view' ? 'Edit' : 'Cancel'} @@ -174,10 +124,10 @@ export const AccessControlTab = () => { - {mode === 'view' ? renderViewAccessControlDetails() : renderEditAccessControlDetails()} + {mode === 'view' ? : } - {mode === 'edit' ? ( + {mode === 'edit' && ( @@ -199,7 +149,8 @@ export const AccessControlTab = () => { - ) : null} + )} + ); }; diff --git a/public/components/data_connections/components/data_connection.tsx b/public/components/data_connections/components/data_connection.tsx index 0c18b9f0a9..d356dd9231 100644 --- a/public/components/data_connections/components/data_connection.tsx +++ b/public/components/data_connections/components/data_connection.tsx @@ -30,6 +30,7 @@ interface DatasourceDetails { allowedRoles: string[]; name: string; cluster: string; + connector: string; } export const DataConnection = (props: any) => { @@ -38,18 +39,30 @@ export const DataConnection = (props: any) => { allowedRoles: [], name: '', cluster: '', + connector: '', }); const [hasAccess, setHasAccess] = useState(true); - const { http } = coreRefs; + const { http, chrome } = coreRefs; useEffect(() => { - http + chrome!.setBreadcrumbs([ + { + text: 'Data Connections', + href: '#/', + }, + { + text: `${dataSource}`, + href: `#/manage/${dataSource}`, + }, + ]); + http! .get(`${DATACONNECTIONS_BASE}/${dataSource}`) .then((data) => setDatasourceDetails({ allowedRoles: data.allowedRoles, name: data.name, cluster: data.properties['emr.cluster'], + connector: data.connector, }) ) .catch((err) => { @@ -57,7 +70,7 @@ export const DataConnection = (props: any) => { setHasAccess(false); } }); - }, []); + }, [chrome, http]); const tabs = [ { @@ -70,7 +83,9 @@ export const DataConnection = (props: any) => { id: 'access_control', name: 'Access control', disabled: false, - content: , + content: ( + + ), }, { id: 'connection_configuration', diff --git a/public/components/data_connections/components/no_access.tsx b/public/components/data_connections/components/no_access.tsx index 0bb0bae2fa..d1bdc693cc 100644 --- a/public/components/data_connections/components/no_access.tsx +++ b/public/components/data_connections/components/no_access.tsx @@ -13,7 +13,7 @@ export const NoAccess = () => { Data connections not set up} + title={

{"You don't have permissions to access the requested page"}

} body={ { diff --git a/public/components/data_connections/components/query_permissions_flex_item.tsx b/public/components/data_connections/components/query_permissions.tsx similarity index 96% rename from public/components/data_connections/components/query_permissions_flex_item.tsx rename to public/components/data_connections/components/query_permissions.tsx index fb80f449b4..94209e2cd1 100644 --- a/public/components/data_connections/components/query_permissions_flex_item.tsx +++ b/public/components/data_connections/components/query_permissions.tsx @@ -19,7 +19,7 @@ import { QUERY_RESTRICT, } from '../../../../common/constants/data_connections'; -export const QueryPermissionsFlexItem = (props: PermissionsFlexItem) => { +export const QueryPermissionsConfiguration = (props: PermissionsConfiguration) => { const { roles, setSelectedRoles, selectedRoles, selectedRadio, radios, setSelectedRadio } = props; return ( diff --git a/server/adaptors/ppl_plugin.ts b/server/adaptors/ppl_plugin.ts index 71dbcb5696..ddc2a2ccf9 100644 --- a/server/adaptors/ppl_plugin.ts +++ b/server/adaptors/ppl_plugin.ts @@ -55,6 +55,14 @@ export const PPLPlugin = function (Client, config, components) { method: 'GET', }); + ppl.modifyDataConnection = ca({ + url: { + fmt: `${OPENSEARCH_DATACONNECTIONS_API.DATACONNECTION}`, + }, + needBody: true, + method: 'PUT', + }); + ppl.getDataConnections = ca({ url: { fmt: `${OPENSEARCH_DATACONNECTIONS_API.DATACONNECTION}`, diff --git a/server/routes/data_connections/data_connections_router.ts b/server/routes/data_connections/data_connections_router.ts index ff276db80e..6721613726 100644 --- a/server/routes/data_connections/data_connections_router.ts +++ b/server/routes/data_connections/data_connections_router.ts @@ -37,6 +37,41 @@ export function registerDataConnectionsRoute(router: IRouter) { } ); + router.put( + { + path: `${DATACONNECTIONS_BASE}`, + validate: { + body: schema.object({ + name: schema.string(), + connector: schema.string(), + allowedRoles: schema.arrayOf(schema.string()), + }), + }, + }, + async (context, request, response): Promise => { + try { + const dataConnectionsresponse = await context.observability_plugin.observabilityClient + .asScoped(request) + .callAsCurrentUser('ppl.modifyDataConnection', { + body: { + name: request.body.name, + connector: request.body.connector, + allowedRoles: request.body.allowedRoles, + }, + }); + return response.ok({ + body: dataConnectionsresponse, + }); + } catch (error: any) { + console.error('Issue in modifying data connection:', error); + return response.custom({ + statusCode: error.statusCode || 500, + body: error.message, + }); + } + } + ); + router.get( { path: `${DATACONNECTIONS_BASE}`, From f3ff2f9755e6b21f988a59e4e6ff48b26f563eb2 Mon Sep 17 00:00:00 2001 From: Derek Ho Date: Mon, 18 Sep 2023 15:56:27 -0400 Subject: [PATCH 8/9] Address PR comments Signed-off-by: Derek Ho --- common/constants/data_connections.ts | 2 +- common/types/data_connections.ts | 7 +- ...anage_data_connections_table.test.tsx.snap | 9 +- .../__tests__/data_connection.test.tsx | 26 ++-- .../manage_data_connections_table.test.tsx | 14 ++- .../components/__tests__/testing_constants.ts | 84 +++++-------- .../components/access_control_tab.tsx | 113 +++++++++--------- .../components/data_connection.tsx | 28 ++--- .../data_connections/components/no_access.tsx | 41 +++---- .../components/query_permissions.tsx | 66 ++++++---- .../data_connections_router.ts | 2 + 11 files changed, 187 insertions(+), 205 deletions(-) diff --git a/common/constants/data_connections.ts b/common/constants/data_connections.ts index 4231772996..07b2eb0435 100644 --- a/common/constants/data_connections.ts +++ b/common/constants/data_connections.ts @@ -9,7 +9,7 @@ export const OPENSEARCH_DOCUMENTATION_URL = export const OPENSEARCH_ACC_DOCUMENTATION_URL = 'https://opensearch.org/docs/latest/data-acceleration/index'; -export const QUERY_RESTRICT = 'query-restrict'; +export const QUERY_RESTRICTED = 'query-restricted'; export const QUERY_ALL = 'query-all'; export const ACCELERATION_RESTRICT = 'acceleration-restrict'; export const ACCELERATION_ALL = 'acceleration-all'; diff --git a/common/types/data_connections.ts b/common/types/data_connections.ts index 0bb50bc6ff..9fd0527d96 100644 --- a/common/types/data_connections.ts +++ b/common/types/data_connections.ts @@ -3,13 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { EuiRadioGroupOption } from '@elastic/eui'; - -export interface PermissionsConfiguration { +export interface PermissionsConfigurationProps { roles: Array<{ label: string }>; selectedRoles: Array<{ label: string }>; - selectedRadio: string; setSelectedRoles: React.Dispatch>>; - setSelectedRadio: React.Dispatch>; - radios: EuiRadioGroupOption[]; } diff --git a/public/components/data_connections/components/__tests__/__snapshots__/manage_data_connections_table.test.tsx.snap b/public/components/data_connections/components/__tests__/__snapshots__/manage_data_connections_table.test.tsx.snap index c0d7f7b684..e61640befb 100644 --- a/public/components/data_connections/components/__tests__/__snapshots__/manage_data_connections_table.test.tsx.snap +++ b/public/components/data_connections/components/__tests__/__snapshots__/manage_data_connections_table.test.tsx.snap @@ -37,8 +37,8 @@ exports[`Manage Data Connections Table test Renders manage data connections tabl Learn more - - (opens in a new tab or window) -
diff --git a/public/components/data_connections/components/__tests__/data_connection.test.tsx b/public/components/data_connections/components/__tests__/data_connection.test.tsx index 9e16fcda80..3146b747f9 100644 --- a/public/components/data_connections/components/__tests__/data_connection.test.tsx +++ b/public/components/data_connections/components/__tests__/data_connection.test.tsx @@ -11,28 +11,28 @@ import { describeDataConnection } from './testing_constants'; import { DataConnection } from '../data_connection'; import ReactDOM from 'react-dom'; +jest.mock('../../../../../public/framework/core_refs', () => ({ + coreRefs: { + chrome: { + setBreadcrumbs: jest.fn(), + }, + http: { + get: jest.fn().mockResolvedValue(describeDataConnection), + }, + }, +})); + describe('Data Connection Page test', () => { configure({ adapter: new Adapter() }); it('Renders data connection page with data', async () => { - const http = { - get: jest.fn().mockResolvedValue(describeDataConnection), - }; const pplService = { fetch: jest.fn(), }; - const mockChrome = { - setBreadcrumbs: jest.fn(), - }; - const wrapper = mount( - - ); + const wrapper = mount(); const container = document.createElement('div'); await act(() => { - ReactDOM.render( - , - container - ); + ReactDOM.render(, container); }); expect(container).toMatchSnapshot(); }); diff --git a/public/components/data_connections/components/__tests__/manage_data_connections_table.test.tsx b/public/components/data_connections/components/__tests__/manage_data_connections_table.test.tsx index 380fcf3924..fe7369426a 100644 --- a/public/components/data_connections/components/__tests__/manage_data_connections_table.test.tsx +++ b/public/components/data_connections/components/__tests__/manage_data_connections_table.test.tsx @@ -10,6 +10,18 @@ import React from 'react'; import { ManageDataConnectionsTable } from '../manage_data_connections_table'; import { showDataConnectionsData } from './testing_constants'; import ReactDOM from 'react-dom'; +import { coreRefs } from '../../../../../public/framework/core_refs'; + +jest.mock('../../../../../public/framework/core_refs', () => ({ + coreRefs: { + chrome: { + setBreadcrumbs: jest.fn(), + }, + http: { + get: jest.fn().mockResolvedValue(showDataConnectionsData), + }, + }, +})); describe('Manage Data Connections Table test', () => { configure({ adapter: new Adapter() }); @@ -19,7 +31,7 @@ describe('Manage Data Connections Table test', () => { get: jest.fn().mockResolvedValue(showDataConnectionsData), }; const pplService = { - fetch: jest.fn(), + fetch: jest.fn().mockResolvedValue(showDataConnectionsData), }; const mockChrome = { setBreadcrumbs: jest.fn(), diff --git a/public/components/data_connections/components/__tests__/testing_constants.ts b/public/components/data_connections/components/__tests__/testing_constants.ts index 995e149fe8..65258fb27b 100644 --- a/public/components/data_connections/components/__tests__/testing_constants.ts +++ b/public/components/data_connections/components/__tests__/testing_constants.ts @@ -3,61 +3,43 @@ * SPDX-License-Identifier: Apache-2.0 */ -export const showDataConnectionsData = [ - { - name: 'my_spark3', - connector: 'SPARK', - allowedRoles: [], - properties: { - 'spark.connector': 'emr', - 'spark.datasource.flint.host': '0.0.0.0', - 'spark.datasource.flint.integration': - 'https://aws.oss.sonatype.org/content/repositories/snapshots/org/opensearch/opensearch-spark-standalone_2.12/0.1.0-SNAPSHOT/opensearch-spark-standalone_2.12-0.1.0-20230731.182705-3.jar', - 'spark.datasource.flint.port': '9200', - 'spark.datasource.flint.scheme': 'http', - 'emr.cluster': 'j-3UNQLT1MPBGLG', +export const showDataConnectionsData = { + schema: [ + { + name: 'DATASOURCE_NAME', + type: 'string', }, - }, - { - name: 'my_spark4', - connector: 'SPARK', - allowedRoles: [], - properties: { - 'spark.connector': 'emr', - 'spark.datasource.flint.host': '15.248.1.68', - 'spark.datasource.flint.integration': - 'https://aws.oss.sonatype.org/content/repositories/snapshots/org/opensearch/opensearch-spark-standalone_2.12/0.1.0-SNAPSHOT/opensearch-spark-standalone_2.12-0.1.0-20230731.182705-3.jar', - 'spark.datasource.flint.port': '9200', - 'spark.datasource.flint.scheme': 'http', - 'emr.cluster': 'j-3UNQLT1MPBGLG', + { + name: 'CONNECTOR_TYPE', + type: 'string', }, - }, - { - name: 'my_spark', - connector: 'SPARK', - allowedRoles: [], - properties: { - 'spark.connector': 'emr', - 'spark.datasource.flint.host': '0.0.0.0', - 'spark.datasource.flint.port': '9200', - 'spark.datasource.flint.scheme': 'http', - 'spark.datasource.flint.region': 'xxx', - 'emr.cluster': 'xxx', + ], + datarows: [ + ['my_spark_actual', 'SPARK'], + ['@opensearch', 'OPENSEARCH'], + ['my_spark', 'SPARK'], + ], + total: 3, + size: 3, + jsonData: [ + { + DATASOURCE_NAME: 'my_spark3', + CONNECTOR_TYPE: 'SPARK', }, - }, - { - name: 'my_spark2', - connector: 'SPARK', - allowedRoles: [], - properties: { - 'spark.connector': 'emr', - 'spark.datasource.flint.host': '0.0.0.0', - 'spark.datasource.flint.port': '9200', - 'spark.datasource.flint.scheme': 'http', - 'emr.cluster': 'j-3UNQLT1MPBGLG', + { + DATASOURCE_NAME: 'my_spark4', + CONNECTOR_TYPE: 'SPARK', }, - }, -]; + { + DATASOURCE_NAME: 'my_spark', + CONNECTOR_TYPE: 'SPARK', + }, + { + DATASOURCE_NAME: 'my_spark2', + CONNECTOR_TYPE: 'SPARK', + }, + ], +}; export const describeDataConnection = { name: 'my_spark3', diff --git a/public/components/data_connections/components/access_control_tab.tsx b/public/components/data_connections/components/access_control_tab.tsx index b0b4318707..15c8491b90 100644 --- a/public/components/data_connections/components/access_control_tab.tsx +++ b/public/components/data_connections/components/access_control_tab.tsx @@ -24,6 +24,7 @@ import { DATACONNECTIONS_BASE } from '../../../../common/constants/shared'; interface AccessControlTabProps { dataConnection: string; connector: string; + properties: unknown; } export const AccessControlTab = (props: AccessControlTabProps) => { @@ -32,11 +33,10 @@ export const AccessControlTab = (props: AccessControlTabProps) => { const [selectedQueryPermissionRoles, setSelectedQueryPermissionRoles] = useState< Array<{ label: string }> >([]); - const [queryPermissionRadioSelected, setQueryRadioIdSelected] = useState(`query-1`); const { http } = coreRefs; useEffect(() => { - coreRefs.http!.get('/api/v1/configuration/roles').then((data) => + http!.get('/api/v1/configuration/roles').then((data) => setRoles( Object.keys(data.data).map((key) => { return { label: key }; @@ -45,17 +45,6 @@ export const AccessControlTab = (props: AccessControlTabProps) => { ); }, []); - const queryRadios = [ - { - id: QUERY_RESTRICT, - label: 'Restricted - accessible by users with specific OpenSearch roles', - }, - { - id: QUERY_ALL, - label: 'Everyone - accessible by all users on this cluster', - }, - ]; - const AccessControlDetails = () => { return ( @@ -80,9 +69,6 @@ export const AccessControlTab = (props: AccessControlTabProps) => { roles={roles} selectedRoles={selectedQueryPermissionRoles} setSelectedRoles={setSelectedQueryPermissionRoles} - selectedRadio={queryPermissionRadioSelected} - setSelectedRadio={setQueryRadioIdSelected} - radios={queryRadios} /> ); @@ -92,64 +78,75 @@ export const AccessControlTab = (props: AccessControlTabProps) => { http!.put(`${DATACONNECTIONS_BASE}`, { body: JSON.stringify({ name: props.dataConnection, - allowedRoles: ['test'], + allowedRoles: selectedQueryPermissionRoles.map((role) => role.label), connector: props.connector, + properties: props.properties, }), }); setMode('view'); }; - return ( - <> - - - - - - - -

Access Control

- Control which OpenSearch users have access to this data source. -
-
+ const AccessControlHeader = () => { + return ( + + + +

Access Control

+ Control which OpenSearch users have access to this data source. +
+
+ + + setMode(mode === 'view' ? 'edit' : 'view')} + fill={mode === 'view' ? true : false} + > + {mode === 'view' ? 'Edit' : 'Cancel'} + + +
+ ); + }; + const SaveOrCancel = () => { + return ( + + - setMode(mode === 'view' ? 'edit' : 'view')} - fill={mode === 'view' ? true : false} + { + setMode('view'); + }} + color="ghost" + size="s" + iconType="cross" > - {mode === 'view' ? 'Edit' : 'Cancel'} + Discard change(s) + + + + + Save + + ); + }; + + return ( + <> + + + + + {mode === 'view' ? : } - {mode === 'edit' && ( - - - - { - setMode('view'); - }} - color="ghost" - size="s" - iconType="cross" - > - Discard change(s) - - - - - Save - - - - - )} + {mode === 'edit' && } ); diff --git a/public/components/data_connections/components/data_connection.tsx b/public/components/data_connections/components/data_connection.tsx index d356dd9231..0df41e30f9 100644 --- a/public/components/data_connections/components/data_connection.tsx +++ b/public/components/data_connections/components/data_connection.tsx @@ -31,6 +31,7 @@ interface DatasourceDetails { name: string; cluster: string; connector: string; + properties: unknown; } export const DataConnection = (props: any) => { @@ -40,6 +41,7 @@ export const DataConnection = (props: any) => { name: '', cluster: '', connector: '', + properties: {}, }); const [hasAccess, setHasAccess] = useState(true); const { http, chrome } = coreRefs; @@ -63,6 +65,7 @@ export const DataConnection = (props: any) => { name: data.name, cluster: data.properties['emr.cluster'], connector: data.connector, + properties: data.properties, }) ) .catch((err) => { @@ -84,7 +87,11 @@ export const DataConnection = (props: any) => { name: 'Access control', disabled: false, content: ( - + ), }, { @@ -95,25 +102,6 @@ export const DataConnection = (props: any) => { }, ]; - const [selectedTabId, setSelectedTabId] = useState('data'); - - const onSelectedTabChanged = (id) => { - setSelectedTabId(id); - }; - - const renderTabs = () => { - return tabs.map((tab, index) => ( - onSelectedTabChanged(tab.id)} - isSelected={tab.id === selectedTabId} - disabled={tab.disabled} - key={index} - > - {tab.name} - - )); - }; - const renderOverview = () => { return ( diff --git a/public/components/data_connections/components/no_access.tsx b/public/components/data_connections/components/no_access.tsx index d1bdc693cc..5c07b28931 100644 --- a/public/components/data_connections/components/no_access.tsx +++ b/public/components/data_connections/components/no_access.tsx @@ -3,36 +3,29 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { EuiButton, EuiEmptyPrompt, EuiPage, EuiPanel, EuiText } from '@elastic/eui'; +import { EuiButton, EuiEmptyPrompt, EuiPage, EuiText } from '@elastic/eui'; import _ from 'lodash'; import React from 'react'; -import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../common/constants/data_connections'; export const NoAccess = () => { return ( - - {"You don't have permissions to access the requested page"}} - body={ - - { - 'You do not have the permissions to view and edit data connections. Please reach out to your administrator for access.' - } - - } - actions={ - window.open(OPENSEARCH_DOCUMENTATION_URL, '_blank')} - > - Learn more - - } - /> - + {'No permissions to access'}} + body={ + + { + 'Missing permissions to view connection details. Contact your administrator for permissions.' + } + + } + actions={ + (window.location.hash = '')}> + Return to data connections + + } + /> ); }; diff --git a/public/components/data_connections/components/query_permissions.tsx b/public/components/data_connections/components/query_permissions.tsx index 94209e2cd1..d983015fe4 100644 --- a/public/components/data_connections/components/query_permissions.tsx +++ b/public/components/data_connections/components/query_permissions.tsx @@ -12,15 +12,51 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; -import React from 'react'; -import { PermissionsFlexItem } from '../../../../common/types/data_connections'; +import React, { useState } from 'react'; import { OPENSEARCH_DOCUMENTATION_URL, - QUERY_RESTRICT, + QUERY_ALL, + QUERY_RESTRICTED, } from '../../../../common/constants/data_connections'; +import { PermissionsConfigurationProps } from '../../../../common/types/data_connections'; + +export const QueryPermissionsConfiguration = (props: PermissionsConfigurationProps) => { + const { roles, selectedRoles, setSelectedRoles } = props; + + const [selectedRadio, setSelectedRadio] = useState( + selectedRoles.length ? QUERY_RESTRICTED : QUERY_ALL + ); + const radios = [ + { + id: QUERY_RESTRICTED, + label: 'Restricted - accessible by users with specific OpenSearch roles', + }, + { + id: QUERY_ALL, + label: 'Everyone - accessible by all users on this cluster', + }, + ]; + + const ConfigureRoles = () => { + return ( +
+ + OpenSearch Roles + + Select one or more OpenSearch roles that can query this data connection. + + +
+ ); + }; -export const QueryPermissionsConfiguration = (props: PermissionsConfiguration) => { - const { roles, setSelectedRoles, selectedRoles, selectedRadio, radios, setSelectedRadio } = props; return ( @@ -43,25 +79,7 @@ export const QueryPermissionsConfiguration = (props: PermissionsConfiguration) = children: Access level, }} /> - {selectedRadio === QUERY_RESTRICT ? ( -
- - OpenSearch Roles - - Select one or more OpenSearch roles that can query this data connection. - - -
- ) : ( - <> - )} + {selectedRadio === QUERY_RESTRICTED && }
diff --git a/server/routes/data_connections/data_connections_router.ts b/server/routes/data_connections/data_connections_router.ts index 6721613726..b0f2b2bade 100644 --- a/server/routes/data_connections/data_connections_router.ts +++ b/server/routes/data_connections/data_connections_router.ts @@ -45,6 +45,7 @@ export function registerDataConnectionsRoute(router: IRouter) { name: schema.string(), connector: schema.string(), allowedRoles: schema.arrayOf(schema.string()), + properties: schema.any(), }), }, }, @@ -57,6 +58,7 @@ export function registerDataConnectionsRoute(router: IRouter) { name: request.body.name, connector: request.body.connector, allowedRoles: request.body.allowedRoles, + properties: request.body.properties, }, }); return response.ok({ From 8fd721156be93211117e1e85f8d1647783f79668 Mon Sep 17 00:00:00 2001 From: Derek Ho Date: Mon, 18 Sep 2023 15:58:11 -0400 Subject: [PATCH 9/9] Remove unused files and variables Signed-off-by: Derek Ho --- common/constants/data_connections.ts | 2 - .../acceleration_permissions_flex_item.tsx | 70 ------------------- 2 files changed, 72 deletions(-) delete mode 100644 public/components/data_connections/components/acceleration_permissions_flex_item.tsx diff --git a/common/constants/data_connections.ts b/common/constants/data_connections.ts index 07b2eb0435..2c06e935ee 100644 --- a/common/constants/data_connections.ts +++ b/common/constants/data_connections.ts @@ -11,5 +11,3 @@ export const OPENSEARCH_ACC_DOCUMENTATION_URL = export const QUERY_RESTRICTED = 'query-restricted'; export const QUERY_ALL = 'query-all'; -export const ACCELERATION_RESTRICT = 'acceleration-restrict'; -export const ACCELERATION_ALL = 'acceleration-all'; diff --git a/public/components/data_connections/components/acceleration_permissions_flex_item.tsx b/public/components/data_connections/components/acceleration_permissions_flex_item.tsx deleted file mode 100644 index 61b00dd15b..0000000000 --- a/public/components/data_connections/components/acceleration_permissions_flex_item.tsx +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - EuiComboBox, - EuiFlexGroup, - EuiFlexItem, - EuiLink, - EuiRadioGroup, - EuiSpacer, - EuiText, -} from '@elastic/eui'; -import React from 'react'; -import { PermissionsFlexItem } from '../../../../common/types/data_connections'; -import { - OPENSEARCH_DOCUMENTATION_URL, - QUERY_ALL, -} from '../../../../common/constants/data_connections'; - -export const AccelerationPermissionsFlexItem = (props: PermissionsFlexItem) => { - const { roles, setSelectedRoles, selectedRoles, selectedRadio, radios, setSelectedRadio } = props; - return ( - - - - Acceleration Permissions - - Control which OpenSearch roles have permissions to accelerate external data through - OpenSearch indexing.{' '} - - Learn more - - - - - setSelectedRadio(id)} - name="acceleration-radio-group" - legend={{ - children: Access level, - }} - /> - {selectedRadio === QUERY_ALL ? ( -
- - OpenSearch Roles - - Select one or more OpenSearch roles that can query this data connection. - - -
- ) : ( - <> - )} -
-
-
- ); -};