mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
178 lines
5.1 KiB
TypeScript
178 lines
5.1 KiB
TypeScript
import { css, cx } from '@emotion/css';
|
|
import { pickBy } from 'lodash';
|
|
import React from 'react';
|
|
|
|
import { GrafanaTheme2, DEFAULT_SAML_NAME } from '@grafana/data';
|
|
import { Icon, IconName, LinkButton, Stack, useStyles2, useTheme2 } from '@grafana/ui';
|
|
import config from 'app/core/config';
|
|
import { Trans } from 'app/core/internationalization';
|
|
|
|
export interface LoginService {
|
|
bgColor: string;
|
|
enabled: boolean;
|
|
name: string;
|
|
hrefName?: string;
|
|
icon: IconName;
|
|
}
|
|
|
|
export interface LoginServices {
|
|
[key: string]: LoginService;
|
|
}
|
|
|
|
const loginServices: () => LoginServices = () => {
|
|
const oauthEnabled = !!config.oauth;
|
|
|
|
return {
|
|
saml: {
|
|
bgColor: '#464646',
|
|
enabled: config.samlEnabled,
|
|
name: config.samlName || DEFAULT_SAML_NAME,
|
|
icon: 'key-skeleton-alt',
|
|
},
|
|
google: {
|
|
bgColor: '#e84d3c',
|
|
enabled: oauthEnabled && Boolean(config.oauth.google),
|
|
name: config.oauth?.google?.name || 'Google',
|
|
icon: config.oauth?.google?.icon || ('google' as const),
|
|
},
|
|
azuread: {
|
|
bgColor: '#2f2f2f',
|
|
enabled: oauthEnabled && Boolean(config.oauth.azuread),
|
|
name: config.oauth?.azuread?.name || 'Microsoft',
|
|
icon: config.oauth?.azuread?.icon || ('microsoft' as const),
|
|
},
|
|
github: {
|
|
bgColor: '#464646',
|
|
enabled: oauthEnabled && Boolean(config.oauth.github),
|
|
name: config.oauth?.github?.name || 'GitHub',
|
|
icon: config.oauth?.github?.icon || ('github' as const),
|
|
},
|
|
gitlab: {
|
|
bgColor: '#fc6d26',
|
|
enabled: oauthEnabled && Boolean(config.oauth.gitlab),
|
|
name: config.oauth?.gitlab?.name || 'GitLab',
|
|
icon: config.oauth?.gitlab?.icon || ('gitlab' as const),
|
|
},
|
|
grafanacom: {
|
|
bgColor: '#262628',
|
|
enabled: oauthEnabled && Boolean(config.oauth.grafana_com),
|
|
name: config.oauth?.grafana_com?.name || 'Grafana.com',
|
|
icon: config.oauth?.grafana_com?.icon || ('grafana' as const),
|
|
hrefName: 'grafana_com',
|
|
},
|
|
okta: {
|
|
bgColor: '#2f2f2f',
|
|
enabled: oauthEnabled && Boolean(config.oauth.okta),
|
|
name: config.oauth?.okta?.name || 'Okta',
|
|
icon: config.oauth?.okta?.icon || ('okta' as const),
|
|
},
|
|
oauth: {
|
|
bgColor: '#262628',
|
|
enabled: oauthEnabled && Boolean(config.oauth.generic_oauth),
|
|
name: config.oauth?.generic_oauth?.name || 'OAuth',
|
|
icon: config.oauth?.generic_oauth?.icon || ('signin' as const),
|
|
hrefName: 'generic_oauth',
|
|
},
|
|
};
|
|
};
|
|
|
|
const getServiceStyles = (theme: GrafanaTheme2) => {
|
|
return {
|
|
button: css({
|
|
color: '#d8d9da',
|
|
position: 'relative',
|
|
}),
|
|
buttonIcon: css({
|
|
position: 'absolute',
|
|
left: theme.spacing(1),
|
|
top: '50%',
|
|
transform: 'translateY(-50%)',
|
|
}),
|
|
divider: {
|
|
base: css({
|
|
color: theme.colors.text.primary,
|
|
display: 'flex',
|
|
marginBottom: theme.spacing(1),
|
|
justifyContent: 'space-between',
|
|
textAlign: 'center',
|
|
width: '100%',
|
|
}),
|
|
line: css({
|
|
width: 100,
|
|
height: 10,
|
|
borderBottom: `1px solid ${theme.colors.text}`,
|
|
}),
|
|
},
|
|
};
|
|
};
|
|
|
|
const LoginDivider = () => {
|
|
const styles = useStyles2(getServiceStyles);
|
|
return (
|
|
<>
|
|
<div className={styles.divider.base}>
|
|
<div>
|
|
<div className={styles.divider.line} />
|
|
</div>
|
|
<div>
|
|
<span>{!config.disableLoginForm && <span>or</span>}</span>
|
|
</div>
|
|
<div>
|
|
<div className={styles.divider.line} />
|
|
</div>
|
|
</div>
|
|
<div className="clearfix" />
|
|
</>
|
|
);
|
|
};
|
|
|
|
function getButtonStyleFor(service: LoginService, styles: ReturnType<typeof getServiceStyles>, theme: GrafanaTheme2) {
|
|
return cx(
|
|
styles.button,
|
|
css({
|
|
backgroundColor: service.bgColor,
|
|
color: theme.colors.getContrastText(service.bgColor),
|
|
|
|
['&:hover']: {
|
|
backgroundColor: theme.colors.emphasize(service.bgColor, 0.15),
|
|
boxShadow: theme.shadows.z1,
|
|
},
|
|
})
|
|
);
|
|
}
|
|
|
|
export const LoginServiceButtons = () => {
|
|
const enabledServices = pickBy(loginServices(), (service) => service.enabled);
|
|
const hasServices = Object.keys(enabledServices).length > 0;
|
|
const theme = useTheme2();
|
|
const styles = useStyles2(getServiceStyles);
|
|
|
|
if (hasServices) {
|
|
return (
|
|
// TODO: Remove extra div when Stack supports width
|
|
<div style={{ width: '100%' }}>
|
|
<Stack direction={'column'}>
|
|
<LoginDivider />
|
|
{Object.entries(enabledServices).map(([key, service]) => {
|
|
const serviceName = service.name;
|
|
return (
|
|
<LinkButton
|
|
key={key}
|
|
className={getButtonStyleFor(service, styles, theme)}
|
|
href={`login/${service.hrefName ? service.hrefName : key}`}
|
|
target="_self"
|
|
fullWidth
|
|
>
|
|
<Icon className={styles.buttonIcon} name={service.icon} />
|
|
<Trans i18nKey="login.services.sing-in-with-prefix">Sign in with {{ serviceName }}</Trans>
|
|
</LinkButton>
|
|
);
|
|
})}
|
|
</Stack>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return null;
|
|
};
|