mirror of
https://github.com/grafana/grafana.git
synced 2025-02-13 09:05:45 -06:00
* Add initial authentication config page skeleton * Add initial SAML config page WIP * Add few more pages * Add connect to IdP page * Assertion mappings page stub and url params * Able to save settings * Some tweaks for authentication page * Tweak behaviour * Tweak provider name * Move SAML config pages to enterprise * minor refactor * Able to reset settings * Configure key and cert from UI * Refactor WIP * Tweak styles * Optional save button * Some tweaks for the page * Don't show info popup when save settings * Improve key/cert validation * Fetch provider status and display on auth page * Add settings list to the auth page * Show call to action card if no auth configured * clean up * Show authentication page only if SAML available * Add access control for SSO config page * Add feature toggle for auth config UI * Add code owners for auth config page * Auth config UI disabled by default * Fix feature toggle check * Apply suggestions from review * Refactor: use forms for steps * Clean up * Improve authentication page loading * Fix CTA link * Minor tweaks * Fix page route * Fix formatting * Fix generated code formatting
156 lines
5.3 KiB
TypeScript
156 lines
5.3 KiB
TypeScript
import { css } from '@emotion/css';
|
|
import { isEmpty } from 'lodash';
|
|
import React, { useEffect } from 'react';
|
|
import { connect, ConnectedProps } from 'react-redux';
|
|
|
|
import { GrafanaTheme2 } from '@grafana/data';
|
|
import { useStyles2 } from '@grafana/ui';
|
|
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';
|
|
import { filterAuthSettings, getProviderUrl } from './utils';
|
|
|
|
import { getRegisteredAuthProviders } from '.';
|
|
|
|
interface OwnProps {}
|
|
|
|
export type Props = OwnProps & ConnectedProps<typeof connector>;
|
|
|
|
function mapStateToProps(state: StoreState) {
|
|
const { settings, isLoading, providerStatuses } = state.authConfig;
|
|
return {
|
|
settings,
|
|
isLoading,
|
|
providerStatuses,
|
|
};
|
|
}
|
|
|
|
const mapDispatchToProps = {
|
|
loadSettings,
|
|
};
|
|
|
|
const connector = connect(mapStateToProps, mapDispatchToProps);
|
|
|
|
export const AuthConfigPageUnconnected = ({
|
|
settings,
|
|
providerStatuses,
|
|
isLoading,
|
|
loadSettings,
|
|
}: Props): JSX.Element => {
|
|
const styles = useStyles2(getStyles);
|
|
|
|
useEffect(() => {
|
|
loadSettings();
|
|
}, [loadSettings]);
|
|
|
|
const authProviders = getRegisteredAuthProviders();
|
|
const enabledProviders = authProviders.filter((p) => providerStatuses[p.id]?.enabled);
|
|
const configuresProviders = authProviders.filter(
|
|
(p) => providerStatuses[p.id]?.configured && !providerStatuses[p.id]?.enabled
|
|
);
|
|
const availableProviders = authProviders.filter(
|
|
(p) => !providerStatuses[p.id]?.enabled && !providerStatuses[p.id]?.configured
|
|
);
|
|
const authSettings = filterAuthSettings(settings);
|
|
const firstAvailableProvider = availableProviders?.length ? availableProviders[0] : null;
|
|
|
|
return (
|
|
<Page navId="authentication">
|
|
<Page.Contents isLoading={isLoading}>
|
|
<h3 className={styles.sectionHeader}>Configured authentication</h3>
|
|
{!!enabledProviders?.length && (
|
|
<div className={styles.cardsContainer}>
|
|
{enabledProviders.map((provider) => (
|
|
<ProviderCard
|
|
key={provider.id}
|
|
providerId={provider.id}
|
|
displayName={provider.displayName}
|
|
authType={provider.type}
|
|
enabled={providerStatuses[provider.id]?.enabled}
|
|
configPath={provider.configPath}
|
|
/>
|
|
))}
|
|
</div>
|
|
)}
|
|
{!enabledProviders?.length && firstAvailableProvider && !isEmpty(providerStatuses) && (
|
|
<ConfigureAuthCTA
|
|
title={`You have no ${firstAvailableProvider.type} configuration created at the moment`}
|
|
buttonIcon="plus-circle"
|
|
buttonLink={getProviderUrl(firstAvailableProvider)}
|
|
buttonTitle={`Configure ${firstAvailableProvider.type}`}
|
|
description={`Important: if you have ${firstAvailableProvider.type} configuration enabled via the .ini file Grafana is using it.
|
|
Configuring ${firstAvailableProvider.type} via UI will take precedence over any configuration in the .ini file.
|
|
No changes will be written into .ini file.`}
|
|
/>
|
|
)}
|
|
{!!configuresProviders?.length && (
|
|
<div className={styles.cardsContainer}>
|
|
{configuresProviders.map((provider) => (
|
|
<ProviderCard
|
|
key={provider.id}
|
|
providerId={provider.id}
|
|
displayName={provider.displayName}
|
|
authType={provider.protocol}
|
|
enabled={providerStatuses[provider.id]?.enabled}
|
|
configPath={provider.configPath}
|
|
/>
|
|
))}
|
|
</div>
|
|
)}
|
|
<div className={styles.settingsSection}>
|
|
<h3>Settings</h3>
|
|
{authSettings && (
|
|
<table className="filter-table">
|
|
<tbody>
|
|
{Object.entries(authSettings).map(([sectionName, sectionSettings], i) => (
|
|
<React.Fragment key={`section-${i}`}>
|
|
<tr>
|
|
<td className="admin-settings-section">{sectionName}</td>
|
|
<td />
|
|
</tr>
|
|
{Object.entries(sectionSettings).map(([settingName, settingValue], j) => (
|
|
<tr key={`property-${j}`}>
|
|
<td className={styles.settingName}>{settingName}</td>
|
|
<td className={styles.settingName}>{settingValue}</td>
|
|
</tr>
|
|
))}
|
|
</React.Fragment>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
)}
|
|
</div>
|
|
</Page.Contents>
|
|
</Page>
|
|
);
|
|
};
|
|
|
|
const getStyles = (theme: GrafanaTheme2) => {
|
|
return {
|
|
cardsContainer: css`
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(288px, 1fr));
|
|
gap: ${theme.spacing(3)};
|
|
margin-bottom: ${theme.spacing(3)};
|
|
margin-top: ${theme.spacing(2)};
|
|
`,
|
|
sectionHeader: css`
|
|
margin-bottom: ${theme.spacing(3)};
|
|
`,
|
|
settingsSection: css`
|
|
margin-top: ${theme.spacing(4)};
|
|
`,
|
|
settingName: css`
|
|
padding-left: 25px;
|
|
`,
|
|
settingValue: css`
|
|
white-space: break-spaces;
|
|
`,
|
|
};
|
|
};
|
|
|
|
export default connector(AuthConfigPageUnconnected);
|