mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Login: Show oauth error messages inline (#72255)
Squashed commit of the following: commit b82ed875b88d12348cd4043e2add493e8fb6edc6 Author: Roxana Turc <anamaria-roxana.turc@grafana.com> Date: Tue Jul 25 10:42:31 2023 +0100 user essentials mob! 🔱 lastFile:public/app/core/components/Login/LoginPage.test.tsx commit 923cbcf190d2def57b59f8b231f14322efdf9718 Author: joshhunt <josh@trtr.co> Date: Tue Jul 25 10:17:51 2023 +0100 user essentials mob! 🔱 Co-authored-by: joshhunt <josh@trtr.co> Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com> Co-authored-by: L-M-K-B <48948963+L-M-K-B@users.noreply.github.com>
This commit is contained in:
parent
e9ba6922c0
commit
edb7d0e0d8
@ -79,7 +79,7 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
|||||||
disableUserSignUp = false;
|
disableUserSignUp = false;
|
||||||
loginHint = '';
|
loginHint = '';
|
||||||
passwordHint = '';
|
passwordHint = '';
|
||||||
loginError = undefined;
|
loginError: string | undefined = undefined;
|
||||||
viewersCanEdit = false;
|
viewersCanEdit = false;
|
||||||
editorsCanAdmin = false;
|
editorsCanAdmin = false;
|
||||||
disableSanitizeHtml = false;
|
disableSanitizeHtml = false;
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
import { AppEvents } from '@grafana/data';
|
|
||||||
import { FetchError, getBackendSrv, isFetchError } from '@grafana/runtime';
|
import { FetchError, getBackendSrv, isFetchError } from '@grafana/runtime';
|
||||||
import appEvents from 'app/core/app_events';
|
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
import { t } from 'app/core/internationalization';
|
import { t } from 'app/core/internationalization';
|
||||||
|
|
||||||
@ -53,11 +51,8 @@ export class LoginCtrl extends PureComponent<Props, State> {
|
|||||||
isLoggingIn: false,
|
isLoggingIn: false,
|
||||||
isChangingPassword: false,
|
isChangingPassword: false,
|
||||||
showDefaultPasswordWarning: false,
|
showDefaultPasswordWarning: false,
|
||||||
|
loginErrorMessage: config.loginError,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (config.loginError) {
|
|
||||||
appEvents.emit(AppEvents.alertWarning, ['Login Failed', config.loginError]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
changePassword = (password: string) => {
|
changePassword = (password: string) => {
|
||||||
|
@ -105,6 +105,16 @@ describe('Login Page', () => {
|
|||||||
expect(screen.getByRole('link', { name: 'Sign in with Okta Test' })).toBeInTheDocument();
|
expect(screen.getByRole('link', { name: 'Sign in with Okta Test' })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('shows oauth errors', async () => {
|
||||||
|
runtimeMock.config.loginError = 'Oh no there was an error :(';
|
||||||
|
|
||||||
|
render(<LoginPage />);
|
||||||
|
|
||||||
|
const alert = await screen.findByRole('alert', { name: 'Login failed' });
|
||||||
|
expect(alert).toBeInTheDocument();
|
||||||
|
expect(alert).toHaveTextContent('Oh no there was an error :(');
|
||||||
|
});
|
||||||
|
|
||||||
it('shows an error with incorrect password', async () => {
|
it('shows an error with incorrect password', async () => {
|
||||||
postMock.mockRejectedValueOnce({
|
postMock.mockRejectedValueOnce({
|
||||||
data: {
|
data: {
|
||||||
@ -122,7 +132,9 @@ describe('Login Page', () => {
|
|||||||
await userEvent.type(screen.getByLabelText('Password input field'), 'test');
|
await userEvent.type(screen.getByLabelText('Password input field'), 'test');
|
||||||
await userEvent.click(screen.getByRole('button', { name: 'Login button' }));
|
await userEvent.click(screen.getByRole('button', { name: 'Login button' }));
|
||||||
|
|
||||||
expect(await screen.findByRole('alert', { name: 'Invalid username or password' })).toBeInTheDocument();
|
const alert = await screen.findByRole('alert', { name: 'Login failed' });
|
||||||
|
expect(alert).toBeInTheDocument();
|
||||||
|
expect(alert).toHaveTextContent('Invalid username or password');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows a different error with failed login attempts', async () => {
|
it('shows a different error with failed login attempts', async () => {
|
||||||
@ -142,10 +154,10 @@ describe('Login Page', () => {
|
|||||||
await userEvent.type(screen.getByLabelText('Password input field'), 'test');
|
await userEvent.type(screen.getByLabelText('Password input field'), 'test');
|
||||||
await userEvent.click(screen.getByRole('button', { name: 'Login button' }));
|
await userEvent.click(screen.getByRole('button', { name: 'Login button' }));
|
||||||
|
|
||||||
expect(
|
const alert = await screen.findByRole('alert', { name: 'Login failed' });
|
||||||
await screen.findByRole('alert', {
|
expect(alert).toBeInTheDocument();
|
||||||
name: 'You have exceeded the number of login attempts for this user. Please try again later.',
|
expect(alert).toHaveTextContent(
|
||||||
})
|
'You have exceeded the number of login attempts for this user. Please try again later.'
|
||||||
).toBeInTheDocument();
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -6,6 +6,7 @@ import React from 'react';
|
|||||||
import { Alert, HorizontalGroup, LinkButton } from '@grafana/ui';
|
import { Alert, HorizontalGroup, LinkButton } from '@grafana/ui';
|
||||||
import { Branding } from 'app/core/components/Branding/Branding';
|
import { Branding } from 'app/core/components/Branding/Branding';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
import { t } from 'app/core/internationalization';
|
||||||
|
|
||||||
import { ChangePassword } from '../ForgottenPassword/ChangePassword';
|
import { ChangePassword } from '../ForgottenPassword/ChangePassword';
|
||||||
|
|
||||||
@ -44,7 +45,11 @@ export const LoginPage = () => {
|
|||||||
<LoginLayout isChangingPassword={isChangingPassword}>
|
<LoginLayout isChangingPassword={isChangingPassword}>
|
||||||
{!isChangingPassword && (
|
{!isChangingPassword && (
|
||||||
<InnerBox>
|
<InnerBox>
|
||||||
{loginErrorMessage && <Alert className={alertStyles} severity="error" title={loginErrorMessage} />}
|
{loginErrorMessage && (
|
||||||
|
<Alert className={alertStyles} severity="error" title={t('login.error.title', 'Login failed')}>
|
||||||
|
{loginErrorMessage}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
{!disableLoginForm && (
|
{!disableLoginForm && (
|
||||||
<LoginForm onSubmit={login} loginHint={loginHint} passwordHint={passwordHint} isLoggingIn={isLoggingIn}>
|
<LoginForm onSubmit={login} loginHint={loginHint} passwordHint={passwordHint} isLoggingIn={isLoggingIn}>
|
||||||
|
@ -254,6 +254,7 @@
|
|||||||
"error": {
|
"error": {
|
||||||
"blocked": "",
|
"blocked": "",
|
||||||
"invalid-user-or-password": "",
|
"invalid-user-or-password": "",
|
||||||
|
"title": "",
|
||||||
"unknown": ""
|
"unknown": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -254,6 +254,7 @@
|
|||||||
"error": {
|
"error": {
|
||||||
"blocked": "You have exceeded the number of login attempts for this user. Please try again later.",
|
"blocked": "You have exceeded the number of login attempts for this user. Please try again later.",
|
||||||
"invalid-user-or-password": "Invalid username or password",
|
"invalid-user-or-password": "Invalid username or password",
|
||||||
|
"title": "Login failed",
|
||||||
"unknown": "Unknown error occurred"
|
"unknown": "Unknown error occurred"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -259,6 +259,7 @@
|
|||||||
"error": {
|
"error": {
|
||||||
"blocked": "",
|
"blocked": "",
|
||||||
"invalid-user-or-password": "",
|
"invalid-user-or-password": "",
|
||||||
|
"title": "",
|
||||||
"unknown": ""
|
"unknown": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -259,6 +259,7 @@
|
|||||||
"error": {
|
"error": {
|
||||||
"blocked": "",
|
"blocked": "",
|
||||||
"invalid-user-or-password": "",
|
"invalid-user-or-password": "",
|
||||||
|
"title": "",
|
||||||
"unknown": ""
|
"unknown": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -254,6 +254,7 @@
|
|||||||
"error": {
|
"error": {
|
||||||
"blocked": "Ÿőū ĥävę ęχčęęđęđ ŧĥę ʼnūmþęř őƒ ľőģįʼn äŧŧęmpŧş ƒőř ŧĥįş ūşęř. Pľęäşę ŧřy äģäįʼn ľäŧęř.",
|
"blocked": "Ÿőū ĥävę ęχčęęđęđ ŧĥę ʼnūmþęř őƒ ľőģįʼn äŧŧęmpŧş ƒőř ŧĥįş ūşęř. Pľęäşę ŧřy äģäįʼn ľäŧęř.",
|
||||||
"invalid-user-or-password": "Ĩʼnväľįđ ūşęřʼnämę őř päşşŵőřđ",
|
"invalid-user-or-password": "Ĩʼnväľįđ ūşęřʼnämę őř päşşŵőřđ",
|
||||||
|
"title": "Ŀőģįʼn ƒäįľęđ",
|
||||||
"unknown": "Ůʼnĸʼnőŵʼn ęřřőř őččūřřęđ"
|
"unknown": "Ůʼnĸʼnőŵʼn ęřřőř őččūřřęđ"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -249,6 +249,7 @@
|
|||||||
"error": {
|
"error": {
|
||||||
"blocked": "",
|
"blocked": "",
|
||||||
"invalid-user-or-password": "",
|
"invalid-user-or-password": "",
|
||||||
|
"title": "",
|
||||||
"unknown": ""
|
"unknown": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user