diff --git a/src/backend/InvenTree/InvenTree/auth_overrides.py b/src/backend/InvenTree/InvenTree/auth_overrides.py index 95aa26c231..569f5fc74d 100644 --- a/src/backend/InvenTree/InvenTree/auth_overrides.py +++ b/src/backend/InvenTree/InvenTree/auth_overrides.py @@ -3,14 +3,16 @@ from django import forms from django.conf import settings from django.contrib.auth.models import Group -from django.http import HttpResponseRedirect +from django.http import HttpRequest, HttpResponseRedirect from django.urls import reverse from django.utils.translation import gettext_lazy as _ import structlog from allauth.account.adapter import DefaultAccountAdapter from allauth.account.forms import LoginForm, SignupForm, set_form_field_order +from allauth.headless.adapter import DefaultHeadlessAdapter from allauth.headless.tokens.sessions import SessionTokenStrategy +from allauth.mfa.adapter import DefaultMFAAdapter from allauth.socialaccount.adapter import DefaultSocialAccountAdapter import InvenTree.helpers_model @@ -210,6 +212,40 @@ class CustomSocialAccountAdapter(RegistrationMixin, DefaultSocialAccountAdapter) logger.error("SSO error for provider '%s' - check admin error log", provider_id) +class CustomMFAAdapter(DefaultMFAAdapter): + """Override of adapter to use dynamic settings.""" + + def block_email_registering(self, user) -> bool: + """Statically disable email registration blocking.""" + return False + + +class CustomHeadlessAdapter(DefaultHeadlessAdapter): + """Override of adapter to use dynamic settings.""" + + def get_frontend_url(self, request: HttpRequest, urlname, **kwargs): + """Get the frontend URL for the given URL name respecting the request.""" + HEADLESS_FRONTEND_URLS = { + 'account_confirm_email': ['verify-email/', '{key}'], + 'account_reset_password': 'reset-password', + 'account_reset_password_from_key': ['set-password?key=', '{key}'], + 'account_signup': 'register', + 'socialaccount_login_error': 'social-login-error', + } + if urlname not in HEADLESS_FRONTEND_URLS: + raise ValueError( + f'URL name "{urlname}" not found in HEADLESS_FRONTEND_URLS' + ) + + url = HEADLESS_FRONTEND_URLS[urlname] + if isinstance(url, list): + return ( + request.build_absolute_uri(f'/{settings.FRONTEND_URL_BASE}/{url[0]}') + + url[1] + ) + return request.build_absolute_uri(f'/{settings.FRONTEND_URL_BASE}/{url}') + + class DRFTokenStrategy(SessionTokenStrategy): """Strategy that InvenTrees own included Token model.""" diff --git a/src/backend/InvenTree/InvenTree/settings.py b/src/backend/InvenTree/InvenTree/settings.py index b10d3bdff1..9381835148 100644 --- a/src/backend/InvenTree/InvenTree/settings.py +++ b/src/backend/InvenTree/InvenTree/settings.py @@ -1300,6 +1300,8 @@ ACCOUNT_FORMS = { SOCIALACCOUNT_ADAPTER = 'InvenTree.auth_overrides.CustomSocialAccountAdapter' ACCOUNT_ADAPTER = 'InvenTree.auth_overrides.CustomAccountAdapter' +MFA_ADAPTER = 'InvenTree.auth_overrides.CustomMFAAdapter' +HEADLESS_ADAPTER = 'InvenTree.auth_overrides.CustomHeadlessAdapter' ACCOUNT_LOGOUT_ON_PASSWORD_CHANGE = True @@ -1307,7 +1309,7 @@ ACCOUNT_LOGOUT_ON_PASSWORD_CHANGE = True def get_frontend_url(pui_path: str): """Generate frontend url. - #TODO This function should be moved to the adapter once https://codeberg.org/allauth/django-allauth/issues/4226 is resolved. + #TODO remove this https://codeberg.org/allauth/django-allauth/issues/4226 is merged. """ host: str = 'http://localhost:8000' if not host.endswith('/'):