mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[6.8][Security] Add message to login page. (#64158)
This commit is contained in:
parent
0aea444da8
commit
2baa83bc4b
10 changed files with 163 additions and 12 deletions
|
@ -54,3 +54,6 @@ routing requests through a load balancer or proxy).
|
|||
Sets the session duration (in milliseconds). By default, sessions stay active
|
||||
until the browser is closed. When this is set to an explicit timeout, closing the
|
||||
browser still requires the user to log back in to {kib}.
|
||||
|
||||
`xpack.security.loginAssistanceMessage`::
|
||||
Adds a message to the login screen. Useful for displaying information about maintenance windows, links to corporate sign up pages etc.
|
||||
|
|
|
@ -158,6 +158,7 @@ kibana_vars=(
|
|||
xpack.security.encryptionKey
|
||||
xpack.security.secureCookies
|
||||
xpack.security.sessionTimeout
|
||||
xpack.security.loginAssistanceMessage
|
||||
xpack.xpack_main.telemetry.enabled
|
||||
)
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ export const security = (kibana) => new kibana.Plugin({
|
|||
encryptionKey: Joi.string(),
|
||||
sessionTimeout: Joi.number().allow(null).default(null),
|
||||
secureCookies: Joi.boolean().default(false),
|
||||
loginAssistanceMessage: Joi.string(),
|
||||
public: Joi.object({
|
||||
protocol: Joi.string().valid(['http', 'https']),
|
||||
hostname: Joi.string().hostname(),
|
||||
|
@ -178,6 +179,7 @@ export const security = (kibana) => new kibana.Plugin({
|
|||
const { showLogin, loginMessage, allowLogin, layout = 'form' } = xpackInfo.feature(plugin.id).getLicenseCheckResults() || {};
|
||||
|
||||
return {
|
||||
loginAssistanceMessage: config.get('xpack.security.loginAssistanceMessage') || '',
|
||||
loginState: {
|
||||
showLogin,
|
||||
allowLogin,
|
||||
|
|
|
@ -2,6 +2,18 @@
|
|||
|
||||
exports[`BasicLoginForm renders as expected 1`] = `
|
||||
<Fragment>
|
||||
<EuiText
|
||||
grow={true}
|
||||
size="s"
|
||||
>
|
||||
<ReactMarkdown
|
||||
escapeHtml={true}
|
||||
renderers={Object {}}
|
||||
skipHtml={false}
|
||||
source=""
|
||||
transformLinkUri={[Function]}
|
||||
/>
|
||||
</EuiText>
|
||||
<EuiPanel
|
||||
grow={true}
|
||||
hasShadow={false}
|
||||
|
|
|
@ -50,6 +50,7 @@ describe('BasicLoginForm', () => {
|
|||
loginState={loginState}
|
||||
next={''}
|
||||
intl={null as any}
|
||||
loginAssistanceMessage=""
|
||||
/>
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
|
@ -68,6 +69,7 @@ describe('BasicLoginForm', () => {
|
|||
next={''}
|
||||
infoMessage={'Hey this is an info message'}
|
||||
intl={null as any}
|
||||
loginAssistanceMessage=""
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -86,6 +88,7 @@ describe('BasicLoginForm', () => {
|
|||
loginState={loginState}
|
||||
next={''}
|
||||
intl={null as any}
|
||||
loginAssistanceMessage=""
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
|
@ -4,9 +4,18 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiButton, EuiCallOut, EuiFieldText, EuiFormRow, EuiPanel, EuiSpacer } from '@elastic/eui';
|
||||
import {
|
||||
EuiButton,
|
||||
EuiCallOut,
|
||||
EuiFieldText,
|
||||
EuiFormRow,
|
||||
EuiPanel,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
|
||||
import React, { ChangeEvent, Component, FormEvent, Fragment, MouseEvent } from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import { LoginState } from '../../../../../common/login_state';
|
||||
|
||||
interface Props {
|
||||
|
@ -14,6 +23,7 @@ interface Props {
|
|||
window: any;
|
||||
infoMessage?: string;
|
||||
loginState: LoginState;
|
||||
loginAssistanceMessage: string;
|
||||
next: string;
|
||||
intl: InjectedIntl;
|
||||
}
|
||||
|
@ -38,6 +48,7 @@ class BasicLoginFormUI extends Component<Props, State> {
|
|||
public render() {
|
||||
return (
|
||||
<Fragment>
|
||||
{this.renderLoginAssistanceMessage()}
|
||||
{this.renderMessage()}
|
||||
<EuiPanel>
|
||||
<form onSubmit={this.submit}>
|
||||
|
@ -102,6 +113,16 @@ class BasicLoginFormUI extends Component<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
private renderLoginAssistanceMessage = () => {
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiText size="s">
|
||||
<ReactMarkdown source={this.props.loginAssistanceMessage} />
|
||||
</EuiText>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
private renderMessage = () => {
|
||||
if (this.state.message) {
|
||||
return (
|
||||
|
@ -132,6 +153,7 @@ class BasicLoginFormUI extends Component<Props, State> {
|
|||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
|
|
|
@ -182,6 +182,100 @@ exports[`LoginPage disabled form states renders as expected when an unknown logi
|
|||
</div>
|
||||
`;
|
||||
|
||||
exports[`LoginPage disabled form states renders as expected when loginAssistanceMessage is set 1`] = `
|
||||
<div
|
||||
className="loginWelcome login-form"
|
||||
>
|
||||
<header
|
||||
className="loginWelcome__header"
|
||||
>
|
||||
<div
|
||||
className="loginWelcome__content eui-textCenter"
|
||||
>
|
||||
<EuiSpacer
|
||||
size="xxl"
|
||||
/>
|
||||
<span
|
||||
className="loginWelcome__logo"
|
||||
>
|
||||
<EuiIcon
|
||||
size="xxl"
|
||||
type="logoKibana"
|
||||
/>
|
||||
</span>
|
||||
<EuiTitle
|
||||
className="loginWelcome__title"
|
||||
size="l"
|
||||
textTransform="none"
|
||||
>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
defaultMessage="Welcome to Kibana"
|
||||
id="xpack.security.loginPage.welcomeTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
</h1>
|
||||
</EuiTitle>
|
||||
<EuiText
|
||||
className="loginWelcome__subtitle"
|
||||
color="subdued"
|
||||
grow={true}
|
||||
size="s"
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Your window into the Elastic Stack"
|
||||
id="xpack.security.loginPage.welcomeDescription"
|
||||
values={Object {}}
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
<EuiSpacer
|
||||
size="xl"
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<div
|
||||
className="loginWelcome__content loginWelcome-body"
|
||||
>
|
||||
<EuiFlexGroup
|
||||
alignItems="stretch"
|
||||
component="div"
|
||||
direction="row"
|
||||
gutterSize="l"
|
||||
justifyContent="flexStart"
|
||||
responsive={true}
|
||||
wrap={false}
|
||||
>
|
||||
<EuiFlexItem
|
||||
component="div"
|
||||
grow={true}
|
||||
>
|
||||
<InjectIntl(BasicLoginFormUI)
|
||||
http={
|
||||
Object {
|
||||
"post": [MockFunction],
|
||||
}
|
||||
}
|
||||
isSecureConnection={false}
|
||||
loginAssistanceMessage="This is an *important* message"
|
||||
loginState={
|
||||
Object {
|
||||
"allowLogin": true,
|
||||
"layout": "form",
|
||||
"loginMessage": "",
|
||||
}
|
||||
}
|
||||
next=""
|
||||
requiresSecureConnection={false}
|
||||
window={Object {}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`LoginPage disabled form states renders as expected when secure cookies are required but not present 1`] = `
|
||||
<div
|
||||
className="loginWelcome login-form"
|
||||
|
@ -440,6 +534,7 @@ exports[`LoginPage enabled form state renders as expected 1`] = `
|
|||
}
|
||||
}
|
||||
isSecureConnection={false}
|
||||
loginAssistanceMessage=""
|
||||
loginState={
|
||||
Object {
|
||||
"allowLogin": true,
|
||||
|
|
|
@ -46,6 +46,7 @@ describe('LoginPage', () => {
|
|||
loginState: createLoginState(),
|
||||
isSecureConnection: false,
|
||||
requiresSecureConnection: true,
|
||||
loginAssistanceMessage: '',
|
||||
};
|
||||
|
||||
expect(shallow(<LoginPage {...props} />)).toMatchSnapshot();
|
||||
|
@ -61,6 +62,7 @@ describe('LoginPage', () => {
|
|||
}),
|
||||
isSecureConnection: false,
|
||||
requiresSecureConnection: false,
|
||||
loginAssistanceMessage: '',
|
||||
};
|
||||
|
||||
expect(shallow(<LoginPage {...props} />)).toMatchSnapshot();
|
||||
|
@ -76,6 +78,7 @@ describe('LoginPage', () => {
|
|||
}),
|
||||
isSecureConnection: false,
|
||||
requiresSecureConnection: false,
|
||||
loginAssistanceMessage: '',
|
||||
};
|
||||
|
||||
expect(shallow(<LoginPage {...props} />)).toMatchSnapshot();
|
||||
|
@ -91,6 +94,21 @@ describe('LoginPage', () => {
|
|||
}),
|
||||
isSecureConnection: false,
|
||||
requiresSecureConnection: false,
|
||||
loginAssistanceMessage: '',
|
||||
};
|
||||
|
||||
expect(shallow(<LoginPage {...props} />)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders as expected when loginAssistanceMessage is set', () => {
|
||||
const props = {
|
||||
http: createMockHttp(),
|
||||
window: {},
|
||||
next: '',
|
||||
loginState: createLoginState(),
|
||||
isSecureConnection: false,
|
||||
requiresSecureConnection: false,
|
||||
loginAssistanceMessage: 'This is an *important* message',
|
||||
};
|
||||
|
||||
expect(shallow(<LoginPage {...props} />)).toMatchSnapshot();
|
||||
|
@ -106,6 +124,7 @@ describe('LoginPage', () => {
|
|||
loginState: createLoginState(),
|
||||
isSecureConnection: false,
|
||||
requiresSecureConnection: false,
|
||||
loginAssistanceMessage: '',
|
||||
};
|
||||
|
||||
expect(shallow(<LoginPage {...props} />)).toMatchSnapshot();
|
||||
|
|
|
@ -8,16 +8,7 @@ import React, { Component } from 'react';
|
|||
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
import {
|
||||
// @ts-ignore
|
||||
EuiCard,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiIcon,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui';
|
||||
import classNames from 'classnames';
|
||||
import { LoginState } from '../../../../../common/login_state';
|
||||
import { BasicLoginForm } from '../basic_login_form';
|
||||
|
@ -31,6 +22,7 @@ interface Props {
|
|||
loginState: LoginState;
|
||||
isSecureConnection: boolean;
|
||||
requiresSecureConnection: boolean;
|
||||
loginAssistanceMessage: string;
|
||||
}
|
||||
|
||||
export class LoginPage extends Component<Props, {}> {
|
||||
|
|
|
@ -38,7 +38,8 @@ interface AnyObject {
|
|||
$http: AnyObject,
|
||||
$window: AnyObject,
|
||||
secureCookies: boolean,
|
||||
loginState: LoginState
|
||||
loginState: LoginState,
|
||||
loginAssistanceMessage: string
|
||||
) => {
|
||||
const basePath = chrome.getBasePath();
|
||||
const next = parseNext($window.location.href, basePath);
|
||||
|
@ -58,6 +59,7 @@ interface AnyObject {
|
|||
loginState={loginState}
|
||||
isSecureConnection={isSecure}
|
||||
requiresSecureConnection={secureCookies}
|
||||
loginAssistanceMessage={loginAssistanceMessage}
|
||||
next={next}
|
||||
/>
|
||||
</I18nContext>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue