2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-07-03 20:20:58 +00:00

[PUI] Add 2FA login ()

* Add `2fa_urls`

* Add new fields to serializer

* Add new interface to PUI interfaces

* fix url resolving

* add frontend redirect for MFA login

* redirect login if mfa is required

* Merege upstream/master into branch

* reset default login

* remove mfa states

* fix auth args

* add handler for MFA redirect auth

* Revert "Merege upstream/master into branch"

This reverts commit 717001d8f1.

* revert api version bump

* revert frontend error handling change

* reduce complexity

* reset schema text

* Add e2e test for MFA login url

* accept either POST or body data for login pre-check

* remove CUI test

* style fixes
This commit is contained in:
Matthias Mair
2024-06-20 00:38:43 +02:00
committed by GitHub
parent 73c10e219c
commit 39f3b900de
3 changed files with 126 additions and 8 deletions
src
backend
InvenTree
frontend
src
functions

@ -1,15 +1,45 @@
import { t } from '@lingui/macro';
import { notifications } from '@mantine/notifications';
import axios from 'axios';
import { NavigateFunction } from 'react-router-dom';
import { api, setApiDefaults } from '../App';
import { ApiEndpoints } from '../enums/ApiEndpoints';
import { apiUrl } from '../states/ApiState';
import { apiUrl, useServerApiState } from '../states/ApiState';
import { useLocalState } from '../states/LocalState';
import { useUserState } from '../states/UserState';
import { fetchGlobalStates } from '../states/states';
import { showLoginNotification } from './notifications';
/**
* sends a request to the specified url from a form. this will change the window location.
* @param {string} path the path to send the post request to
* @param {object} params the parameters to add to the url
* @param {string} [method=post] the method to use on the form
*
* Source https://stackoverflow.com/questions/133925/javascript-post-request-like-a-form-submit/133997#133997
*/
function post(path: string, params: any, method = 'post') {
const form = document.createElement('form');
form.method = method;
form.action = path;
for (const key in params) {
if (params.hasOwnProperty(key)) {
const hiddenField = document.createElement('input');
hiddenField.type = 'hidden';
hiddenField.name = key;
hiddenField.value = params[key];
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
}
/**
* Attempt to login using username:password combination.
* If login is successful, an API token will be returned.
@ -50,7 +80,19 @@ export const doBasicLogin = async (username: string, password: string) => {
}
}
})
.catch(() => {});
.catch((err) => {
if (
err?.response.status == 403 &&
err?.response.data.detail == 'MFA required for this user'
) {
post(apiUrl(ApiEndpoints.user_login), {
username: username,
password: password,
csrfmiddlewaretoken: getCsrfCookie(),
mfa: true
});
}
});
if (result) {
await fetchUserState();
@ -65,7 +107,7 @@ export const doBasicLogin = async (username: string, password: string) => {
*
* @arg deleteToken: If true, delete the token from the server
*/
export const doLogout = async (navigate: any) => {
export const doLogout = async (navigate: NavigateFunction) => {
const { clearUserState, isLoggedIn } = useUserState.getState();
// Logout from the server session