2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-07-04 14:10:52 +00:00

Display login errors to user (#12288)

* Improved error message extraction

* Updated playwright test
This commit is contained in:
Oliver
2026-07-01 22:39:49 +10:00
committed by GitHub
parent 609e5ee105
commit 9594ba9a98
3 changed files with 66 additions and 10 deletions
+1 -1
View File
@@ -90,7 +90,7 @@ export default defineConfig({
INVENTREE_FRONTEND_API_HOST: 'http://localhost:8000',
INVENTREE_CORS_ORIGIN_ALLOW_ALL: 'True',
INVENTREE_COOKIE_SAMESITE: 'False',
INVENTREE_LOGIN_ATTEMPTS: '100',
INVENTREE_LOGIN_ATTEMPTS: '3',
INVENTREE_PLUGINS_MANDATORY: 'samplelocate',
INVENTREE_CUSTOM_SPLASH: 'img/playwright_custom_splash.png',
INVENTREE_CUSTOM_LOGO: 'img/playwright_custom_logo.png'
+16 -3
View File
@@ -129,11 +129,24 @@ export async function doBasicLogin(
});
break;
default:
const data = err.response?.data ?? {};
let msg: string = t`Check your input and try again.`;
// Extract error message from response data
if (data?.detail) {
msg = data.detail;
} else if (data?.message) {
msg = data.message;
} else if (data?.error) {
msg = data.error;
} else if (data?.errors && Array.isArray(data.errors)) {
msg = data.errors[0]?.message ?? msg;
}
notifications.show({
title: `${t`Login failed`} (${err.response.status})`,
message:
err.response?.data?.detail ??
t`Check your input and try again.`,
message: msg,
id: 'auth-login-error',
color: 'red'
});
+48 -5
View File
@@ -9,12 +9,24 @@ import { TOTP } from 'otpauth';
* Test various types of login failure
*/
test('Login - Failures', async ({ page }) => {
const loginWithError = async () => {
const loginWithError = async ({
msg,
reload = true
}: {
msg?: string;
reload?: boolean;
}) => {
await page.getByRole('button', { name: 'Log In' }).click();
await page.getByText('Login failed', { exact: true }).waitFor();
await page.getByText('Check your input and try again').first().waitFor();
if (msg) {
await page.getByText(msg).waitFor();
}
if (reload) {
await page.reload();
}
};
// Navigate to the 'login' page
@@ -26,25 +38,56 @@ test('Login - Failures', async ({ page }) => {
await page.getByLabel('login-username').fill('invalid user');
await page.getByLabel('login-password').fill('invalid password');
await loginWithError();
await loginWithError({
msg: 'The username and/or password you specified are not correct'
});
// Attempt login with valid (but disabled) user
await page.getByLabel('login-username').fill('ian');
await page.getByLabel('login-password').fill('inactive');
await loginWithError();
await loginWithError({});
// Attempt login with no username
await page.getByLabel('login-username').fill('');
await page.getByLabel('login-password').fill('hunter2');
await loginWithError();
await loginWithError({});
// Attempt login with no password
await page.getByLabel('login-username').fill('ian');
await page.getByLabel('login-password').fill('');
await loginWithError();
await loginWithError({});
let tooManyAttempts = false;
// Attempt login with incorrect password, multiple attempts
for (let i = 0; i < 10; i++) {
await page.getByLabel('login-username').fill('reader');
await page.getByLabel('login-password').fill('readonlyx');
await loginWithError({ reload: false });
const text = await page.getByText('Too many failed login attempts', {
exact: false
});
if (
await expect(text)
.toBeVisible({ timeout: 100 })
.then(() => true)
.catch(() => false)
) {
tooManyAttempts = true;
break;
}
await page.reload();
}
if (!tooManyAttempts) {
await expect(tooManyAttempts).toEqual(true);
}
});
test('Login - Change Password', async ({ page }) => {