2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-10-03 15:52:51 +00:00

fix(backend): better siteurl testing in middleware (#10335)

* fix(backend): simplify siteurl testing

* add multi-site test

* pass off site_url check if more than one trusted origin is set

* split up testing

* add temporary debug info

* fix test enviorment
This commit is contained in:
Matthias Mair
2025-09-19 10:18:03 +02:00
committed by GitHub
parent 843dd92901
commit 4b0acad518
2 changed files with 93 additions and 27 deletions

View File

@@ -237,11 +237,18 @@ class InvenTreeHostSettingsMiddleware(MiddlewareMixin):
# Ensure that the settings are set correctly with the current request
accessed_scheme = request._current_scheme_host
if accessed_scheme and not accessed_scheme.startswith(settings.SITE_URL):
msg = f'INVE-E7: The used path `{accessed_scheme}` does not match the SITE_URL `{settings.SITE_URL}`'
logger.error(msg)
return render(
request, 'config_error.html', {'error_message': msg}, status=500
)
if (
isinstance(settings.CSRF_TRUSTED_ORIGINS, list)
and len(settings.CSRF_TRUSTED_ORIGINS) > 1
):
# The used url might not be the primary url - next check determines if in a trusted origins
pass
else:
msg = f'INVE-E7: The used path `{accessed_scheme}` does not match the SITE_URL `{settings.SITE_URL}`'
logger.error(msg)
return render(
request, 'config_error.html', {'error_message': msg}, status=500
)
# Check trusted origins
referer = urlsplit(accessed_scheme)

View File

@@ -1,5 +1,6 @@
"""Tests for middleware functions."""
from django.conf import settings
from django.http import Http404
from django.urls import reverse
@@ -87,36 +88,72 @@ class MiddlewareTests(InvenTreeTestCase):
log_error('testpath')
check(1)
def do_positive_test(self, response):
"""Helper function to check for positive test results."""
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'INVE-E7')
self.assertContains(response, 'window.INVENTREE_SETTINGS')
def test_site_url_checks(self):
"""Test that the site URL check is correctly working."""
# correctly set
# simple setup
with self.settings(
SITE_URL='http://testserver', CSRF_TRUSTED_ORIGINS=['http://testserver']
):
response = self.client.get(reverse('web'))
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'INVE-E7')
self.assertContains(response, 'window.INVENTREE_SETTINGS')
self.do_positive_test(response)
# wrongly set site URL
with self.settings(SITE_URL='https://example.com'):
# simple setup with wildcard
with self.settings(
SITE_URL='http://testserver', CSRF_TRUSTED_ORIGINS=['http://*.testserver']
):
response = self.client.get(reverse('web'))
self.assertEqual(response.status_code, 500)
self.assertContains(
response,
'INVE-E7: The used path `http://testserver` does not match',
status_code=500,
)
self.assertNotContains(
response, 'window.INVENTREE_SETTINGS', status_code=500
)
self.do_positive_test(response)
def test_site_url_checks_multi(self):
"""Test that the site URL check is correctly working in a multi-site setup."""
# multi-site setup with trusted origins
with self.settings(
SITE_URL='https://testserver.example.com',
CSRF_TRUSTED_ORIGINS=[
'http://testserver',
'https://testserver.example.com',
],
):
# this will run with testserver as host by default
response = self.client.get(reverse('web'))
self.do_positive_test(response)
# Now test with the "outside" url name
response = self.client.get(
'https://testserver.example.com/web/',
SERVER_NAME='testserver.example.com',
)
self.do_positive_test(response)
# A non-trsuted origin must still fail in multi - origin setup
response = self.client.get(
'https://not-my-testserver.example.com/web/',
SERVER_NAME='not-my-testserver.example.com',
)
self.assertEqual(response.status_code, 500)
# Even if it is a subdomain
response = self.client.get(
'https://not-my.testserver.example.com/web/',
SERVER_NAME='not-my.testserver.example.com',
)
self.assertEqual(response.status_code, 500)
def test_site_url_checks_fails(self):
"""Test that the site URL check is correctly failing.
Important for security.
"""
# wrongly set but in debug -> is ignored
with self.settings(SITE_URL='https://example.com', DEBUG=True):
response = self.client.get(reverse('web'))
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'INVE-E7')
self.assertContains(response, 'window.INVENTREE_SETTINGS')
self.do_positive_test(response)
# wrongly set cors
with self.settings(
@@ -133,10 +170,32 @@ class MiddlewareTests(InvenTreeTestCase):
response, 'window.INVENTREE_SETTINGS', status_code=500
)
# wrongly set site URL
with self.settings(
SITE_URL='http://testserver', CSRF_TRUSTED_ORIGINS=['http://*.testserver']
SITE_URL='https://example.com',
CSRF_TRUSTED_ORIGINS=['http://localhost:8000'],
):
response = self.client.get(reverse('web'))
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'INVE-E7')
self.assertContains(response, 'window.INVENTREE_SETTINGS')
self.assertEqual(response.status_code, 500)
self.assertContains(
response, 'INVE-E7: The used path `http://testserver` ', status_code=500
)
self.assertNotContains(
response, 'window.INVENTREE_SETTINGS', status_code=500
)
# Log stuff # TODO remove
print(
'###DBG-TST###',
'site',
settings.SITE_URL,
'trusted',
settings.CSRF_TRUSTED_ORIGINS,
)
# Check that the correct step triggers the error message
self.assertContains(
response,
'INVE-E7: The used path `http://testserver` does not match',
status_code=500,
)