mirror of
https://github.com/ansible/awx.git
synced 2026-05-19 23:07:42 -02:30
Adds support for html in custom login text
This commit is contained in:
115
awx/ui_next/package-lock.json
generated
115
awx/ui_next/package-lock.json
generated
@@ -11103,6 +11103,11 @@
|
|||||||
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
|
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"klona": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA=="
|
||||||
|
},
|
||||||
"language-subtag-registry": {
|
"language-subtag-registry": {
|
||||||
"version": "0.3.21",
|
"version": "0.3.21",
|
||||||
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz",
|
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz",
|
||||||
@@ -11827,6 +11832,11 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"nanoid": {
|
||||||
|
"version": "3.1.20",
|
||||||
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
|
||||||
|
"integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw=="
|
||||||
|
},
|
||||||
"nanomatch": {
|
"nanomatch": {
|
||||||
"version": "1.2.13",
|
"version": "1.2.13",
|
||||||
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
|
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
|
||||||
@@ -12560,6 +12570,11 @@
|
|||||||
"json-parse-better-errors": "^1.0.1"
|
"json-parse-better-errors": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"parse-srcset": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE="
|
||||||
|
},
|
||||||
"parse5": {
|
"parse5": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
|
||||||
@@ -15623,6 +15638,106 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sanitize-html": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-p7neuskvC8pSurUjdVmbWPXmc9A4+QpOXIL+4gwFC+av5h+lYCXFT8uEneqsFQg/wEA1IH+cKQA60AaQI6p3cg==",
|
||||||
|
"requires": {
|
||||||
|
"deepmerge": "^4.2.2",
|
||||||
|
"escape-string-regexp": "^4.0.0",
|
||||||
|
"htmlparser2": "^6.0.0",
|
||||||
|
"is-plain-object": "^5.0.0",
|
||||||
|
"klona": "^2.0.3",
|
||||||
|
"parse-srcset": "^1.0.2",
|
||||||
|
"postcss": "^8.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"colorette": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w=="
|
||||||
|
},
|
||||||
|
"deepmerge": {
|
||||||
|
"version": "4.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
|
||||||
|
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
|
||||||
|
},
|
||||||
|
"dom-serializer": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-n6kZFH/KlCrqs/1GHMOd5i2fd/beQHuehKdWvNNffbGHTr/almdhuVvTVFb3V7fglz+nC50fFusu3lY33h12pA==",
|
||||||
|
"requires": {
|
||||||
|
"domelementtype": "^2.0.1",
|
||||||
|
"domhandler": "^4.0.0",
|
||||||
|
"entities": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"domelementtype": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w=="
|
||||||
|
},
|
||||||
|
"domhandler": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA==",
|
||||||
|
"requires": {
|
||||||
|
"domelementtype": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"domutils": {
|
||||||
|
"version": "2.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.4.4.tgz",
|
||||||
|
"integrity": "sha512-jBC0vOsECI4OMdD0GC9mGn7NXPLb+Qt6KW1YDQzeQYRUFKmNG8lh7mO5HiELfr+lLQE7loDVI4QcAxV80HS+RA==",
|
||||||
|
"requires": {
|
||||||
|
"dom-serializer": "^1.0.1",
|
||||||
|
"domelementtype": "^2.0.1",
|
||||||
|
"domhandler": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"entities": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
|
||||||
|
},
|
||||||
|
"escape-string-regexp": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
|
||||||
|
},
|
||||||
|
"htmlparser2": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-numTQtDZMoh78zJpaNdJ9MXb2cv5G3jwUoe3dMQODubZvLoGvTE/Ofp6sHvH8OGKcN/8A47pGLi/k58xHP/Tfw==",
|
||||||
|
"requires": {
|
||||||
|
"domelementtype": "^2.0.1",
|
||||||
|
"domhandler": "^4.0.0",
|
||||||
|
"domutils": "^2.4.4",
|
||||||
|
"entities": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-plain-object": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
|
||||||
|
},
|
||||||
|
"postcss": {
|
||||||
|
"version": "8.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.7.tgz",
|
||||||
|
"integrity": "sha512-DsVLH3xJzut+VT+rYr0mtvOtpTjSyqDwPf5EZWXcb0uAKfitGpTY9Ec+afi2+TgdN8rWS9Cs88UDYehKo/RvOw==",
|
||||||
|
"requires": {
|
||||||
|
"colorette": "^1.2.2",
|
||||||
|
"nanoid": "^3.1.20",
|
||||||
|
"source-map": "^0.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source-map": {
|
||||||
|
"version": "0.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"sanitize.css": {
|
"sanitize.css": {
|
||||||
"version": "10.0.0",
|
"version": "10.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-10.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-10.0.0.tgz",
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
"react-router-dom": "^5.1.2",
|
"react-router-dom": "^5.1.2",
|
||||||
"react-virtualized": "^9.21.1",
|
"react-virtualized": "^9.21.1",
|
||||||
"rrule": "^2.6.4",
|
"rrule": "^2.6.4",
|
||||||
|
"sanitize-html": "^2.3.2",
|
||||||
"styled-components": "^4.2.0"
|
"styled-components": "^4.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -4,12 +4,20 @@ import { withI18n } from '@lingui/react';
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import sanitizeHtml from 'sanitize-html';
|
||||||
import {
|
import {
|
||||||
|
Brand,
|
||||||
LoginMainFooterLinksItem,
|
LoginMainFooterLinksItem,
|
||||||
LoginForm,
|
LoginForm,
|
||||||
LoginPage as PFLoginPage,
|
Login as PFLogin,
|
||||||
|
LoginHeader,
|
||||||
|
LoginFooter,
|
||||||
|
LoginMainHeader,
|
||||||
|
LoginMainBody,
|
||||||
|
LoginMainFooter,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AzureIcon,
|
AzureIcon,
|
||||||
GoogleIcon,
|
GoogleIcon,
|
||||||
@@ -23,7 +31,7 @@ import ErrorDetail from '../../components/ErrorDetail';
|
|||||||
|
|
||||||
const loginLogoSrc = '/static/media/logo-login.svg';
|
const loginLogoSrc = '/static/media/logo-login.svg';
|
||||||
|
|
||||||
const LoginPage = styled(PFLoginPage)`
|
const Login = styled(PFLogin)`
|
||||||
& .pf-c-brand {
|
& .pf-c-brand {
|
||||||
max-height: 285px;
|
max-height: 285px;
|
||||||
}
|
}
|
||||||
@@ -112,171 +120,185 @@ function AWXLogin({ alt, i18n, isAuthenticated }) {
|
|||||||
helperText = i18n._(t`There was a problem signing in. Please try again.`);
|
helperText = i18n._(t`There was a problem signing in. Please try again.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
const HeaderBrand = <Brand src={logo} alt={alt || brandName} />;
|
||||||
<LoginPage
|
const Header = <LoginHeader headerBrand={HeaderBrand} />;
|
||||||
brandImgSrc={logo}
|
const Footer = (
|
||||||
brandImgAlt={alt || brandName}
|
<LoginFooter
|
||||||
loginTitle={
|
dangerouslySetInnerHTML={{
|
||||||
brandName
|
__html: sanitizeHtml(loginInfo),
|
||||||
? i18n._(t`Welcome to Ansible ${brandName}! Please Sign In.`)
|
}}
|
||||||
: ''
|
/>
|
||||||
}
|
);
|
||||||
textContent={loginInfo}
|
|
||||||
socialMediaLoginContent={
|
|
||||||
<>
|
|
||||||
{socialAuthOptions &&
|
|
||||||
Object.keys(socialAuthOptions).map(authKey => {
|
|
||||||
const loginUrl = socialAuthOptions[authKey].login_url;
|
|
||||||
if (authKey === 'azuread-oauth2') {
|
|
||||||
return (
|
|
||||||
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
|
||||||
<Tooltip content={i18n._(t`Sign in with Azure AD`)}>
|
|
||||||
<AzureIcon />
|
|
||||||
</Tooltip>
|
|
||||||
</LoginMainFooterLinksItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (authKey === 'github') {
|
|
||||||
return (
|
|
||||||
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
|
||||||
<Tooltip content={i18n._(t`Sign in with GitHub`)}>
|
|
||||||
<GithubIcon />
|
|
||||||
</Tooltip>
|
|
||||||
</LoginMainFooterLinksItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (authKey === 'github-org') {
|
|
||||||
return (
|
|
||||||
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
|
||||||
<Tooltip
|
|
||||||
content={i18n._(t`Sign in with GitHub Organizations`)}
|
|
||||||
>
|
|
||||||
<GithubIcon />
|
|
||||||
</Tooltip>
|
|
||||||
</LoginMainFooterLinksItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (authKey === 'github-team') {
|
|
||||||
return (
|
|
||||||
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
|
||||||
<Tooltip content={i18n._(t`Sign in with GitHub Teams`)}>
|
|
||||||
<GithubIcon />
|
|
||||||
</Tooltip>
|
|
||||||
</LoginMainFooterLinksItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (authKey === 'github-enterprise') {
|
|
||||||
return (
|
|
||||||
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
|
||||||
<Tooltip
|
|
||||||
content={i18n._(t`Sign in with GitHub Enterprise`)}
|
|
||||||
>
|
|
||||||
<GithubIcon />
|
|
||||||
</Tooltip>
|
|
||||||
</LoginMainFooterLinksItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (authKey === 'github-enterprise-org') {
|
|
||||||
return (
|
|
||||||
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
|
||||||
<Tooltip
|
|
||||||
content={i18n._(
|
|
||||||
t`Sign in with GitHub Enterprise Organizations`
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<GithubIcon />
|
|
||||||
</Tooltip>
|
|
||||||
</LoginMainFooterLinksItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (authKey === 'github-enterprise-team') {
|
|
||||||
return (
|
|
||||||
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
|
||||||
<Tooltip
|
|
||||||
content={i18n._(t`Sign in with GitHub Enterprise Teams`)}
|
|
||||||
>
|
|
||||||
<GithubIcon />
|
|
||||||
</Tooltip>
|
|
||||||
</LoginMainFooterLinksItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (authKey === 'google-oauth2') {
|
|
||||||
return (
|
|
||||||
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
|
||||||
<Tooltip content={i18n._(t`Sign in with Google`)}>
|
|
||||||
<GoogleIcon />
|
|
||||||
</Tooltip>
|
|
||||||
</LoginMainFooterLinksItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (authKey.startsWith('saml')) {
|
|
||||||
const samlIDP = authKey.split(':')[1] || null;
|
|
||||||
return (
|
|
||||||
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
|
||||||
<Tooltip
|
|
||||||
content={
|
|
||||||
samlIDP
|
|
||||||
? i18n._(t`Sign in with SAML ${samlIDP}`)
|
|
||||||
: i18n._(t`Sign in with SAML`)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<UserCircleIcon />
|
|
||||||
</Tooltip>
|
|
||||||
</LoginMainFooterLinksItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return (
|
||||||
})}
|
<Login header={Header} footer={Footer}>
|
||||||
</>
|
<LoginMainHeader
|
||||||
}
|
title={
|
||||||
>
|
brandName
|
||||||
<Formik
|
? i18n._(t`Welcome to Ansible ${brandName}! Please Sign In.`)
|
||||||
initialValues={{
|
: ''
|
||||||
password: '',
|
}
|
||||||
username: '',
|
/>
|
||||||
}}
|
<LoginMainBody>
|
||||||
onSubmit={handleSubmit}
|
<Formik
|
||||||
>
|
initialValues={{
|
||||||
{formik => (
|
password: '',
|
||||||
<LoginForm
|
username: '',
|
||||||
className={authError ? 'pf-m-error' : ''}
|
}}
|
||||||
helperText={helperText}
|
onSubmit={handleSubmit}
|
||||||
isLoginButtonDisabled={isAuthenticating}
|
|
||||||
isValidPassword={!authError}
|
|
||||||
isValidUsername={!authError}
|
|
||||||
loginButtonLabel={i18n._(t`Log In`)}
|
|
||||||
onChangePassword={val => {
|
|
||||||
formik.setFieldValue('password', val);
|
|
||||||
dismissAuthError();
|
|
||||||
}}
|
|
||||||
onChangeUsername={val => {
|
|
||||||
formik.setFieldValue('username', val);
|
|
||||||
dismissAuthError();
|
|
||||||
}}
|
|
||||||
onLoginButtonClick={formik.handleSubmit}
|
|
||||||
passwordLabel={i18n._(t`Password`)}
|
|
||||||
passwordValue={formik.values.password}
|
|
||||||
showHelperText={authError}
|
|
||||||
usernameLabel={i18n._(t`Username`)}
|
|
||||||
usernameValue={formik.values.username}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
{loginInfoError && (
|
|
||||||
<AlertModal
|
|
||||||
isOpen={loginInfoError}
|
|
||||||
variant="error"
|
|
||||||
title={i18n._(t`Error!`)}
|
|
||||||
onClose={dismissLoginInfoError}
|
|
||||||
>
|
>
|
||||||
{i18n._(
|
{formik => (
|
||||||
t`Failed to fetch custom login configuration settings. System defaults will be shown instead.`
|
<LoginForm
|
||||||
|
className={authError ? 'pf-m-error' : ''}
|
||||||
|
helperText={helperText}
|
||||||
|
isLoginButtonDisabled={isAuthenticating}
|
||||||
|
isValidPassword={!authError}
|
||||||
|
isValidUsername={!authError}
|
||||||
|
loginButtonLabel={i18n._(t`Log In`)}
|
||||||
|
onChangePassword={val => {
|
||||||
|
formik.setFieldValue('password', val);
|
||||||
|
dismissAuthError();
|
||||||
|
}}
|
||||||
|
onChangeUsername={val => {
|
||||||
|
formik.setFieldValue('username', val);
|
||||||
|
dismissAuthError();
|
||||||
|
}}
|
||||||
|
onLoginButtonClick={formik.handleSubmit}
|
||||||
|
passwordLabel={i18n._(t`Password`)}
|
||||||
|
passwordValue={formik.values.password}
|
||||||
|
showHelperText={authError}
|
||||||
|
usernameLabel={i18n._(t`Username`)}
|
||||||
|
usernameValue={formik.values.username}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
<ErrorDetail error={loginInfoError} />
|
</Formik>
|
||||||
</AlertModal>
|
{loginInfoError && (
|
||||||
)}
|
<AlertModal
|
||||||
</LoginPage>
|
isOpen={loginInfoError}
|
||||||
|
variant="error"
|
||||||
|
title={i18n._(t`Error!`)}
|
||||||
|
onClose={dismissLoginInfoError}
|
||||||
|
>
|
||||||
|
{i18n._(
|
||||||
|
t`Failed to fetch custom login configuration settings. System defaults will be shown instead.`
|
||||||
|
)}
|
||||||
|
<ErrorDetail error={loginInfoError} />
|
||||||
|
</AlertModal>
|
||||||
|
)}
|
||||||
|
</LoginMainBody>
|
||||||
|
<LoginMainFooter
|
||||||
|
socialMediaLoginContent={
|
||||||
|
<>
|
||||||
|
{socialAuthOptions &&
|
||||||
|
Object.keys(socialAuthOptions).map(authKey => {
|
||||||
|
const loginUrl = socialAuthOptions[authKey].login_url;
|
||||||
|
if (authKey === 'azuread-oauth2') {
|
||||||
|
return (
|
||||||
|
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
||||||
|
<Tooltip content={i18n._(t`Sign in with Azure AD`)}>
|
||||||
|
<AzureIcon />
|
||||||
|
</Tooltip>
|
||||||
|
</LoginMainFooterLinksItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (authKey === 'github') {
|
||||||
|
return (
|
||||||
|
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
||||||
|
<Tooltip content={i18n._(t`Sign in with GitHub`)}>
|
||||||
|
<GithubIcon />
|
||||||
|
</Tooltip>
|
||||||
|
</LoginMainFooterLinksItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (authKey === 'github-org') {
|
||||||
|
return (
|
||||||
|
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
||||||
|
<Tooltip
|
||||||
|
content={i18n._(t`Sign in with GitHub Organizations`)}
|
||||||
|
>
|
||||||
|
<GithubIcon />
|
||||||
|
</Tooltip>
|
||||||
|
</LoginMainFooterLinksItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (authKey === 'github-team') {
|
||||||
|
return (
|
||||||
|
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
||||||
|
<Tooltip content={i18n._(t`Sign in with GitHub Teams`)}>
|
||||||
|
<GithubIcon />
|
||||||
|
</Tooltip>
|
||||||
|
</LoginMainFooterLinksItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (authKey === 'github-enterprise') {
|
||||||
|
return (
|
||||||
|
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
||||||
|
<Tooltip
|
||||||
|
content={i18n._(t`Sign in with GitHub Enterprise`)}
|
||||||
|
>
|
||||||
|
<GithubIcon />
|
||||||
|
</Tooltip>
|
||||||
|
</LoginMainFooterLinksItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (authKey === 'github-enterprise-org') {
|
||||||
|
return (
|
||||||
|
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
||||||
|
<Tooltip
|
||||||
|
content={i18n._(
|
||||||
|
t`Sign in with GitHub Enterprise Organizations`
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<GithubIcon />
|
||||||
|
</Tooltip>
|
||||||
|
</LoginMainFooterLinksItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (authKey === 'github-enterprise-team') {
|
||||||
|
return (
|
||||||
|
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
||||||
|
<Tooltip
|
||||||
|
content={i18n._(
|
||||||
|
t`Sign in with GitHub Enterprise Teams`
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<GithubIcon />
|
||||||
|
</Tooltip>
|
||||||
|
</LoginMainFooterLinksItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (authKey === 'google-oauth2') {
|
||||||
|
return (
|
||||||
|
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
||||||
|
<Tooltip content={i18n._(t`Sign in with Google`)}>
|
||||||
|
<GoogleIcon />
|
||||||
|
</Tooltip>
|
||||||
|
</LoginMainFooterLinksItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (authKey.startsWith('saml')) {
|
||||||
|
const samlIDP = authKey.split(':')[1] || null;
|
||||||
|
return (
|
||||||
|
<LoginMainFooterLinksItem href={loginUrl} key={authKey}>
|
||||||
|
<Tooltip
|
||||||
|
content={
|
||||||
|
samlIDP
|
||||||
|
? i18n._(t`Sign in with SAML ${samlIDP}`)
|
||||||
|
: i18n._(t`Sign in with SAML`)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<UserCircleIcon />
|
||||||
|
</Tooltip>
|
||||||
|
</LoginMainFooterLinksItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Login>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ describe('<Login />', () => {
|
|||||||
async function findChildren(wrapper) {
|
async function findChildren(wrapper) {
|
||||||
const [
|
const [
|
||||||
awxLogin,
|
awxLogin,
|
||||||
loginPage,
|
|
||||||
loginForm,
|
loginForm,
|
||||||
usernameInput,
|
usernameInput,
|
||||||
passwordInput,
|
passwordInput,
|
||||||
@@ -32,7 +31,6 @@ describe('<Login />', () => {
|
|||||||
loginHeaderLogo,
|
loginHeaderLogo,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
waitForElement(wrapper, 'AWXLogin', el => el.length === 1),
|
waitForElement(wrapper, 'AWXLogin', el => el.length === 1),
|
||||||
waitForElement(wrapper, 'LoginPage', el => el.length === 1),
|
|
||||||
waitForElement(wrapper, 'LoginForm', el => el.length === 1),
|
waitForElement(wrapper, 'LoginForm', el => el.length === 1),
|
||||||
waitForElement(
|
waitForElement(
|
||||||
wrapper,
|
wrapper,
|
||||||
@@ -49,7 +47,6 @@ describe('<Login />', () => {
|
|||||||
]);
|
]);
|
||||||
return {
|
return {
|
||||||
awxLogin,
|
awxLogin,
|
||||||
loginPage,
|
|
||||||
loginForm,
|
loginForm,
|
||||||
usernameInput,
|
usernameInput,
|
||||||
passwordInput,
|
passwordInput,
|
||||||
@@ -61,7 +58,8 @@ describe('<Login />', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
RootAPI.read.mockResolvedValue({
|
RootAPI.read.mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
custom_login_info: '',
|
custom_login_info:
|
||||||
|
'<div id="custom-button" onmouseover="alert()">TEST</div>',
|
||||||
custom_logo: 'images/foo.jpg',
|
custom_logo: 'images/foo.jpg',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -114,6 +112,16 @@ describe('<Login />', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('custom login info handled correctly', async done => {
|
||||||
|
let wrapper;
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(<AWXLogin isAuthenticated={() => false} />);
|
||||||
|
});
|
||||||
|
await findChildren(wrapper);
|
||||||
|
expect(wrapper.find('footer').html()).toContain('<div>TEST</div>');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
test('data initialization error is properly handled', async done => {
|
test('data initialization error is properly handled', async done => {
|
||||||
RootAPI.read.mockRejectedValueOnce(
|
RootAPI.read.mockRejectedValueOnce(
|
||||||
new Error({
|
new Error({
|
||||||
|
|||||||
Reference in New Issue
Block a user