diff --git a/package.json b/package.json index 681b71e9..b7efd7a3 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@grafana/aws-sdk": "0.0.37", "@grafana/data": "9.0.2", "@grafana/e2e-selectors": "9.0.2", + "@grafana/experimental": "^1.7.0", "@grafana/runtime": "9.0.2", "@grafana/ui": "9.0.2", "lodash": "4.17.21", diff --git a/src/components/QueryEditor/QueryTypeEditor/index.tsx b/src/components/QueryEditor/QueryTypeEditor/index.tsx index be69719e..802601f5 100644 --- a/src/components/QueryEditor/QueryTypeEditor/index.tsx +++ b/src/components/QueryEditor/QueryTypeEditor/index.tsx @@ -7,6 +7,9 @@ import { queryTypeConfig, getQueryTypeOptions } from './utils'; import { segmentStyles } from '../styles'; import { QueryType } from '../../../types'; +const isValidQueryType = (t: string): t is QueryType => { + return Object.values(QueryType).includes(t as QueryType); +}; const toOption = (queryType: QueryType) => { return { label: queryTypeConfig[queryType].label, @@ -26,7 +29,9 @@ export const QueryTypeEditor = ({ value }: Props) => { dispatch(changeQueryType(e.value!))} + onChange={e => { + isValidQueryType(e.value) && dispatch(changeQueryType(e.value!)); + }} value={toOption(value)} /> ); diff --git a/src/configuration/ConfigEditor.tsx b/src/configuration/ConfigEditor.tsx index 16220090..91c630ad 100644 --- a/src/configuration/ConfigEditor.tsx +++ b/src/configuration/ConfigEditor.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { DataSourceHttpSettings } from '@grafana/ui'; -import { DataSourcePluginOptionsEditorProps } from '@grafana/data'; +import { DataSourcePluginOptionsEditorProps, SelectableValue } from '@grafana/data'; import { OpenSearchOptions } from '../types'; import { OpenSearchDetails } from './OpenSearchDetails'; import { LogsConfig } from './LogsConfig'; @@ -9,21 +8,54 @@ import { config, getBackendSrv, getDataSourceSrv } from '@grafana/runtime'; import { coerceOptions, isValidOptions } from './utils'; import { SIGV4ConnectionConfig } from '@grafana/aws-sdk'; import { OpenSearchDatasource } from 'datasource'; +import { AdvancedHttpSettings, Auth, AuthMethod, ConfigSection, convertLegacyAuthProps } from '@grafana/experimental'; +import { InlineField, Input, Select } from '@grafana/ui'; +import { css } from '@emotion/css'; +import { useEffectOnce } from 'react-use'; + +const Sigv4MethodId: CustomMethodId = 'custom-sigv4' +type CustomMethodId = `custom-${string}`; + +const ACCESS_OPTIONS: Array> = [ + { + label: 'Server (default)', + value: 'proxy', + }, + { + label: 'Browser', + value: 'direct', + }, +]; export type Props = DataSourcePluginOptionsEditorProps; export const ConfigEditor = (props: Props) => { const { options: originalOptions, onOptionsChange } = props; + const [visibleMethods, setVisibleMethods] = useState([AuthMethod.BasicAuth, AuthMethod.OAuthForward, ...(config.sigV4AuthEnabled? [Sigv4MethodId]: [])]) const options = coerceOptions(originalOptions); - + const convertedAuthProps = { + ...convertLegacyAuthProps({ + config: props.options, + onChange: props.onOptionsChange, + }), + }; // Apply some defaults on initial render - useEffect(() => { + useEffectOnce(() => { if (!isValidOptions(originalOptions)) { onOptionsChange(coerceOptions(originalOptions)); } + }); - // We can't enforce the eslint rule here because we only want to run this once. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + useEffect(function setAllowedAuthMethods() { + // if direct access, only basic auth and credentials + if (props.options.access === 'direct') { + setVisibleMethods([AuthMethod.BasicAuth, AuthMethod.CrossSiteCredentials]) + if(!props.options.basicAuth) { + convertedAuthProps.onAuthMethodSelect(AuthMethod.BasicAuth); + } + } else { + setVisibleMethods([AuthMethod.BasicAuth, AuthMethod.OAuthForward, AuthMethod.CrossSiteCredentials, ...(config.sigV4AuthEnabled? [Sigv4MethodId]: [])]) + } + }, [props.options.access]) const [saved, setSaved] = useState(!!options.version && options.version > 1); const datasource = useDatasource(props); @@ -50,18 +82,84 @@ export const ConfigEditor = (props: Props) => { setSaved(true); }; + + const onSelectAuth = (auth: AuthMethod | CustomMethodId) => { + // convertedAuthProps.onAuthMethodSelect(auth); + // hanve to overwrite props.onAuthMethodSelect cause it looks like there's a race condition when + // calling both that and onChange below + if (auth === 'custom-sigv4') { + onOptionsChange({ ...props.options, basicAuth: false, withCredentials: false, jsonData: { ...props.options.jsonData, sigV4Auth: true } }); + } else if (auth === AuthMethod.BasicAuth) { + onOptionsChange({ ...props.options, basicAuth: true, withCredentials: false, jsonData: { ...props.options.jsonData, sigV4Auth: false } }) + + } else if(auth === AuthMethod.CrossSiteCredentials){ + onOptionsChange({ ...props.options, basicAuth: false, withCredentials: true, jsonData: { ...props.options.jsonData, sigV4Auth: false } }) + } + else{ + onOptionsChange({ ...props.options, basicAuth: false, withCredentials: false, jsonData: { ...props.options.jsonData, sigV4Auth: false } }) + + } + }; + return ( <> - } + {/* css */} + + + onOptionsChange({...props.options, url: e.currentTarget.value})} + required + width={40} + /> + + +