diff --git a/docs/docs/settings/error_codes.md b/docs/docs/settings/error_codes.md index 8fbaec0ded..092b05de96 100644 --- a/docs/docs/settings/error_codes.md +++ b/docs/docs/settings/error_codes.md @@ -131,6 +131,16 @@ Collective exception for errors that occur during mail delivery. This might be c These issues are raised directly from the mail backend so it is unlikely that the error is caused by django or InvenTree itself. Check the logs for more information. +#### INVE-W11 +**Registration cannot be enabled because of email settings - Backend** + +Registration was enabled but the email settings are not configured correctly. This might lead to issues with user registration, password reset and other authentication features that require email. + +Therefore the registration user interface elements will not be shown. + + +To enable registration, the email settings must be configured correctly. See [email configuration](../start/config.md#email-settings). + ### INVE-I (InvenTree Information) Information — These are not errors but information messages. They might point out potential issues or just provide information. diff --git a/src/backend/InvenTree/InvenTree/auth_overrides.py b/src/backend/InvenTree/InvenTree/auth_overrides.py index 6aea015775..3e5599f8f1 100644 --- a/src/backend/InvenTree/InvenTree/auth_overrides.py +++ b/src/backend/InvenTree/InvenTree/auth_overrides.py @@ -20,6 +20,8 @@ from common.settings import get_global_setting from InvenTree.exceptions import log_error from users.models import ApiToken +from .helpers_email import is_email_configured + logger = structlog.get_logger('inventree') @@ -91,11 +93,11 @@ def registration_enabled(): get_global_setting('LOGIN_ENABLE_REG') or InvenTree.sso.sso_registration_enabled() ): - if settings.EMAIL_HOST: + if is_email_configured(): return True else: logger.warning( - 'Registration cannot be enabled, because EMAIL_HOST is not configured.' + 'INVE-W11: Registration cannot be enabled, because EMAIL_HOST is not configured.' ) return False diff --git a/src/backend/InvenTree/InvenTree/helpers_email.py b/src/backend/InvenTree/InvenTree/helpers_email.py index dbd598a27c..57518ee5e9 100644 --- a/src/backend/InvenTree/InvenTree/helpers_email.py +++ b/src/backend/InvenTree/InvenTree/helpers_email.py @@ -14,16 +14,18 @@ from common.models import Priority, issue_mail logger = structlog.get_logger('inventree') -def is_email_configured(): +def is_email_configured() -> bool: """Check if email backend is configured. + Fails on tests nominally, if no bypassed via settings.TESTING_BYPASS_MAILCHECK. + NOTE: This does not check if the configuration is valid! """ configured = True testing = settings.TESTING if InvenTree.ready.isInTestMode(): - return False + return settings.TESTING_BYPASS_MAILCHECK if InvenTree.ready.isImportingData(): return False diff --git a/src/backend/InvenTree/InvenTree/settings.py b/src/backend/InvenTree/InvenTree/settings.py index d47053ca2f..fd3feceffb 100644 --- a/src/backend/InvenTree/InvenTree/settings.py +++ b/src/backend/InvenTree/InvenTree/settings.py @@ -62,6 +62,8 @@ if TESTING: # Are environment variables manipulated by tests? Needs to be set by testing code TESTING_ENV = False +# Are we bypassing exceptions? +TESTING_BYPASS_MAILCHECK = False # Bypass email disablement for tests # New requirement for django 3.2+ DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' diff --git a/src/backend/InvenTree/InvenTree/test_auth.py b/src/backend/InvenTree/InvenTree/test_auth.py index f8f52bfca4..dfcfc98445 100644 --- a/src/backend/InvenTree/InvenTree/test_auth.py +++ b/src/backend/InvenTree/InvenTree/test_auth.py @@ -182,7 +182,10 @@ class TestAuth(InvenTreeAPITestCase): self.post(self.reg_url, self.email_args(), expected_code=403) # Enable registration - now it should work - with self.settings(EMAIL_HOST='localhost') as _, EmailSettingsContext() as _: + with ( + self.settings(EMAIL_HOST='localhost', TESTING_BYPASS_MAILCHECK=True) as _, + EmailSettingsContext() as _, + ): resp = self.post(self.reg_url, self.email_args(), expected_code=200) self.assertEqual(resp.json()['data']['user']['email'], self.test_email) @@ -213,6 +216,9 @@ class TestAuth(InvenTreeAPITestCase): self.assertIn('The provided email domain is not approved.', str(resp.json())) # Right format should work - with self.settings(EMAIL_HOST='localhost') as _, EmailSettingsContext() as _: + with ( + self.settings(EMAIL_HOST='localhost', TESTING_BYPASS_MAILCHECK=True) as _, + EmailSettingsContext() as _, + ): resp = self.post(self.reg_url, self.email_args(), expected_code=200) self.assertEqual(resp.json()['data']['user']['email'], self.test_email) diff --git a/src/frontend/src/components/forms/AuthenticationForm.tsx b/src/frontend/src/components/forms/AuthenticationForm.tsx index 572a075d08..00700ceee1 100644 --- a/src/frontend/src/components/forms/AuthenticationForm.tsx +++ b/src/frontend/src/components/forms/AuthenticationForm.tsx @@ -3,6 +3,7 @@ import { apiUrl } from '@lib/functions/Api'; import { t } from '@lingui/core/macro'; import { Trans } from '@lingui/react/macro'; import { + Alert, Anchor, Button, Divider, @@ -10,6 +11,7 @@ import { Loader, PasswordInput, Stack, + Text, TextInput, VisuallyHidden } from '@mantine/core'; @@ -30,6 +32,7 @@ import { showLoginNotification } from '../../functions/notifications'; import { useServerApiState } from '../../states/ServerApiState'; import { useUserState } from '../../states/UserState'; import { SsoButton } from '../buttons/SSOButton'; +import { errorCodeLink } from '../nav/Alerts'; export function AuthenticationForm() { const classicForm = useForm({ @@ -341,6 +344,12 @@ export function RegistrationForm() { ))} )} + {!registration_enabled() && !sso_registration() && ( + + {t`This might be related to missing mail settings or could be a deliberate decision.`} + {errorCodeLink('INVE-W11')} + + )} ); }