Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/backend/InvenTree/InvenTree/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from InvenTree.config import get_boolean_setting, get_oidc_private_key, get_setting
from InvenTree.ready import isInMainThread, isRunningBackup
from InvenTree.sentry import default_sentry_dsn, init_sentry
from InvenTree.validators import invalid_site_url_hint
from InvenTree.version import checkMinPythonVersion, inventreeCommitHash
from users.oauth2_scopes import oauth2_scopes

Expand Down Expand Up @@ -771,7 +772,7 @@
validator = URLValidator()
validator(SITE_URL)
except Exception:
msg = f"Invalid SITE_URL value: '{SITE_URL}'. InvenTree server cannot start."
msg = f"Invalid SITE_URL value: '{SITE_URL}'. InvenTree server cannot start.{invalid_site_url_hint(SITE_URL)}"
logger.error(msg)
print(msg)
sys.exit(-1)
Expand Down
35 changes: 35 additions & 0 deletions src/backend/InvenTree/InvenTree/validators.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""Custom field validators for InvenTree."""

import ipaddress
import tokenize
from urllib.parse import urlsplit

from django.conf import settings
from django.core import validators
Expand Down Expand Up @@ -88,6 +90,39 @@ def __call__(self, value):
super().__call__(value)


def invalid_site_url_hint(site_url: str) -> str:
"""Return an extra hint for *why* a SITE_URL value failed validation.

Django's URLValidator rejects any hostname that isn't 'localhost', an IP
address, or a fully qualified (dotted) name - so a bare LAN hostname like
'warehouse' fails with no indication of what's actually wrong. Returns an
empty string when nothing more specific than "invalid URL" applies.
"""
hostname = urlsplit(site_url).hostname

if hostname is None and '//' not in site_url:
# No scheme was given at all, e.g. SITE_URL=warehouse
hostname = urlsplit(f'//{site_url}').hostname

if not hostname or hostname == 'localhost':
return ''

try:
ipaddress.ip_address(hostname)
return ''
except ValueError:
pass

if '.' not in hostname:
return (
f" '{hostname}' has no top-level domain. InvenTree requires a fully "
"qualified hostname (e.g. 'warehouse.local'), an IP address, or "
"'localhost' - a bare hostname is rejected by Django's URL validator."
)

return ''


def validate_purchase_order_reference(value):
"""Validate the 'reference' field of a PurchaseOrder."""
from order.models import PurchaseOrder
Expand Down
Loading