2023-11-29 19:09:36 +02:00
|
|
|
import React, { JSX, useEffect } from 'react';
|
2023-04-13 17:07:43 +03:00
|
|
|
import { connect, ConnectedProps } from 'react-redux';
|
|
|
|
|
|
2023-06-09 15:26:32 +02:00
|
|
|
import { reportInteraction } from '@grafana/runtime';
|
2023-11-29 19:09:36 +02:00
|
|
|
import { Grid, TextLink } from '@grafana/ui';
|
2023-04-13 17:07:43 +03:00
|
|
|
import { Page } from 'app/core/components/Page/Page';
|
|
|
|
|
import { StoreState } from 'app/types';
|
|
|
|
|
|
|
|
|
|
import ConfigureAuthCTA from './components/ConfigureAuthCTA';
|
|
|
|
|
import { ProviderCard } from './components/ProviderCard';
|
|
|
|
|
import { loadSettings } from './state/actions';
|
|
|
|
|
|
2023-11-29 19:09:36 +02:00
|
|
|
import { getRegisteredAuthProviders } from './index';
|
2023-04-13 17:07:43 +03:00
|
|
|
|
|
|
|
|
interface OwnProps {}
|
|
|
|
|
|
|
|
|
|
export type Props = OwnProps & ConnectedProps<typeof connector>;
|
|
|
|
|
|
|
|
|
|
function mapStateToProps(state: StoreState) {
|
2023-11-29 19:09:36 +02:00
|
|
|
const { isLoading, providerStatuses, providers } = state.authConfig;
|
2023-04-13 17:07:43 +03:00
|
|
|
return {
|
|
|
|
|
isLoading,
|
|
|
|
|
providerStatuses,
|
2023-11-29 19:09:36 +02:00
|
|
|
providers,
|
2023-04-13 17:07:43 +03:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const mapDispatchToProps = {
|
|
|
|
|
loadSettings,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const connector = connect(mapStateToProps, mapDispatchToProps);
|
|
|
|
|
|
2023-11-29 19:09:36 +02:00
|
|
|
export const AuthConfigPageUnconnected = ({
|
|
|
|
|
providerStatuses,
|
|
|
|
|
isLoading,
|
|
|
|
|
loadSettings,
|
|
|
|
|
providers,
|
|
|
|
|
}: Props): JSX.Element => {
|
2023-04-13 17:07:43 +03:00
|
|
|
useEffect(() => {
|
|
|
|
|
loadSettings();
|
|
|
|
|
}, [loadSettings]);
|
|
|
|
|
|
|
|
|
|
const authProviders = getRegisteredAuthProviders();
|
2023-11-29 19:09:36 +02:00
|
|
|
const availableProviders = authProviders.filter((p) => !providerStatuses[p.id]?.hide);
|
|
|
|
|
const onProviderCardClick = (providerType: string) => {
|
|
|
|
|
reportInteraction('authentication_ui_provider_clicked', { provider: providerType });
|
2023-06-29 15:42:52 +01:00
|
|
|
};
|
2023-06-09 15:26:32 +02:00
|
|
|
|
2023-11-29 19:09:36 +02:00
|
|
|
const providerList = availableProviders.length
|
|
|
|
|
? [
|
|
|
|
|
...availableProviders.map((p) => ({
|
|
|
|
|
provider: p.id,
|
|
|
|
|
settings: { ...providerStatuses[p.id], configPath: p.configPath, type: p.type },
|
|
|
|
|
})),
|
|
|
|
|
...providers,
|
|
|
|
|
]
|
|
|
|
|
: providers;
|
2023-04-13 17:07:43 +03:00
|
|
|
return (
|
2023-11-29 19:09:36 +02:00
|
|
|
<Page
|
|
|
|
|
navId="authentication"
|
|
|
|
|
subTitle={
|
|
|
|
|
<>
|
|
|
|
|
Manage your auth settings and configure single sign-on. Find out more in our{' '}
|
|
|
|
|
<TextLink href="https://grafana.com/docs/grafana/next/setup-grafana/configure-security/configure-authentication">
|
|
|
|
|
documentation
|
|
|
|
|
</TextLink>
|
|
|
|
|
.
|
|
|
|
|
</>
|
|
|
|
|
}
|
|
|
|
|
>
|
2023-04-13 17:07:43 +03:00
|
|
|
<Page.Contents isLoading={isLoading}>
|
2023-11-29 19:09:36 +02:00
|
|
|
{!providerList.length ? (
|
|
|
|
|
<ConfigureAuthCTA />
|
|
|
|
|
) : (
|
|
|
|
|
<Grid gap={3} minColumnWidth={34}>
|
2023-12-21 15:26:42 +02:00
|
|
|
{providerList
|
|
|
|
|
// Temporarily filter providers that don't have the UI implemented
|
|
|
|
|
.filter(({ provider }) => !['grafana_com', 'generic_oauth'].includes(provider))
|
|
|
|
|
.map(({ provider, settings }) => (
|
|
|
|
|
<ProviderCard
|
|
|
|
|
key={provider}
|
|
|
|
|
authType={settings.type || 'OAuth'}
|
|
|
|
|
providerId={provider}
|
|
|
|
|
enabled={settings.enabled}
|
|
|
|
|
onClick={() => onProviderCardClick(provider)}
|
|
|
|
|
//@ts-expect-error Remove legacy types
|
|
|
|
|
configPath={settings.configPath}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
2023-11-29 19:09:36 +02:00
|
|
|
</Grid>
|
2023-04-13 17:07:43 +03:00
|
|
|
)}
|
|
|
|
|
</Page.Contents>
|
|
|
|
|
</Page>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default connector(AuthConfigPageUnconnected);
|