diff --git a/public/app/features/auth-config/AuthDrawer.test.tsx b/public/app/features/auth-config/AuthDrawer.test.tsx new file mode 100644 index 00000000000..2af62926c09 --- /dev/null +++ b/public/app/features/auth-config/AuthDrawer.test.tsx @@ -0,0 +1,22 @@ +import { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { AuthDrawer, Props } from './AuthDrawer'; + +const defaultProps: Props = { + onClose: jest.fn(), +}; + +async function getTestContext(overrides: Partial = {}) { + jest.clearAllMocks(); + + const props = { ...defaultProps, ...overrides }; + const { rerender } = render(); + + return { rerender, props }; +} + +it('should render with default props', async () => { + await getTestContext({}); + expect(screen.getByText(/Enable insecure email lookup/i)).toBeInTheDocument(); +}); diff --git a/public/app/features/auth-config/AuthDrawer.tsx b/public/app/features/auth-config/AuthDrawer.tsx new file mode 100644 index 00000000000..b2fbbf5f9f6 --- /dev/null +++ b/public/app/features/auth-config/AuthDrawer.tsx @@ -0,0 +1,104 @@ +import { css } from '@emotion/css'; +import React, { useState } from 'react'; + +import { GrafanaTheme2 } from '@grafana/data'; +import { getBackendSrv } from '@grafana/runtime'; +import { Button, Drawer, Text, TextLink, Switch, useStyles2 } from '@grafana/ui'; + +export interface Props { + onClose: () => void; +} + +const SETTINGS_URL = '/api/admin/settings'; + +export const AuthDrawer = ({ onClose }: Props) => { + const [isOauthAllowInsecureEmailLookup, setOauthAllowInsecureEmailLookup] = useState(false); + + const getSettings = async () => { + try { + const response = await getBackendSrv().get(SETTINGS_URL); + setOauthAllowInsecureEmailLookup(response.auth.oauth_allow_insecure_email_lookup?.toLowerCase?.() === 'true'); + } catch (error) {} + }; + const updateSettings = async (property: boolean) => { + try { + const body = { + updates: { + auth: { + oauth_allow_insecure_email_lookup: '' + property, + }, + }, + }; + await getBackendSrv().put(SETTINGS_URL, body); + } catch (error) {} + }; + + const resetButtonOnClick = async () => { + try { + const body = { + removals: { + auth: ['oauth_allow_insecure_email_lookup'], + }, + }; + await getBackendSrv().put(SETTINGS_URL, body); + getSettings(); + } catch (error) {} + }; + + const oauthAllowInsecureEmailLookupOnChange = async () => { + updateSettings(!isOauthAllowInsecureEmailLookup); + setOauthAllowInsecureEmailLookup(!isOauthAllowInsecureEmailLookup); + }; + + const subtitle = ( + <> + Configure auth settings. Find out more in our{' '} + + documentation + + . + + ); + + const styles = useStyles2(getStyles); + + getSettings(); + + return ( + +
+ Advanced Auth + Enable insecure email lookup + + Allow users to use the same email address to log into Grafana with different identity providers. + + +
+ +
+ ); +}; + +const getStyles = (theme: GrafanaTheme2) => { + return { + advancedAuth: css({ + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(1), + }), + button: css({ + marginTop: theme.spacing(2), + }), + }; +}; diff --git a/public/app/features/auth-config/AuthProvidersListPage.tsx b/public/app/features/auth-config/AuthProvidersListPage.tsx index b3a8a344fc7..7a1330bcf59 100644 --- a/public/app/features/auth-config/AuthProvidersListPage.tsx +++ b/public/app/features/auth-config/AuthProvidersListPage.tsx @@ -1,11 +1,14 @@ -import React, { JSX, useEffect } from 'react'; +import React, { JSX, useEffect, useState } from 'react'; import { connect, ConnectedProps } from 'react-redux'; +import { GrafanaEdition } from '@grafana/data/src/types/config'; import { reportInteraction } from '@grafana/runtime'; -import { Grid, TextLink } from '@grafana/ui'; +import { Grid, TextLink, ToolbarButton } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; +import { config } from 'app/core/config'; import { StoreState } from 'app/types'; +import { AuthDrawer } from './AuthDrawer'; import ConfigureAuthCTA from './components/ConfigureAuthCTA'; import { ProviderCard } from './components/ProviderCard'; import { loadSettings } from './state/actions'; @@ -41,6 +44,8 @@ export const AuthConfigPageUnconnected = ({ loadSettings(); }, [loadSettings]); + const [showDrawer, setShowDrawer] = useState(false); + const authProviders = getRegisteredAuthProviders(); const availableProviders = authProviders.filter((p) => !providerStatuses[p.id]?.hide); const onProviderCardClick = (providerType: string, enabled: boolean) => { @@ -71,6 +76,13 @@ export const AuthConfigPageUnconnected = ({ . } + actions={ + config.buildInfo.edition !== GrafanaEdition.OpenSource && ( + setShowDrawer(true)}> + Auth settings + + ) + } > {!providerList.length ? ( @@ -91,6 +103,7 @@ export const AuthConfigPageUnconnected = ({ configPath={settings.configPath} /> ))} + {showDrawer && setShowDrawer(false)}>} )}