[bug] fix auth split for calendar views (#13081)

This commit is contained in:
Oliver authored and GitHub committed 2026-10-24 12:20:09 +11:00
1 parent e57ee86c35
commit ae1f822f26
2 files changed
+48 -5

No files matched your search

+15 -5
View File
@@ -2520,6 +2520,7 @@ class OrderCalendarExport(ICalFeed):
https://www.djangosnippets.org/snippets/243/
"""
import base64
import binascii
if request.user.is_authenticated:
# Authenticated on first try - maybe normal browser call?
@@ -2534,11 +2535,20 @@ class OrderCalendarExport(ICalFeed):
# NOTE: We are only support basic authentication for now.
#
if auth[0].lower() == 'basic':
uname, passwd = base64.b64decode(auth[1]).decode('ascii').split(':')
user = authenticate(username=uname, password=passwd)
if user is not None and user.is_active:
login(request, user)
request.user = user
try:
# Split on the first colon only - passwords may contain ':'
uname, passwd = (
base64.b64decode(auth[1]).decode('utf-8').split(':', 1)
)
except (binascii.Error, UnicodeDecodeError, ValueError):
# Malformed header - fall through to the 401 response
uname = passwd = None
if uname is not None:
user = authenticate(username=uname, password=passwd)
if user is not None and user.is_active:
login(request, user)
request.user = user
# Check again
if request.user.is_authenticated:
+33
View File
@@ -1005,6 +1005,39 @@ class PurchaseOrderTest(OrderTest):
)
self.assertEqual(response.status_code, 200)
def test_po_calendar_auth_password_colon(self):
"""Test header authorization with a password containing a colon."""
password = 'pass:word:123'
self.user.set_password(password)
self.user.save()
self.client.logout()
base64_token = base64.b64encode(f'{self.username}:{password}'.encode()).decode(
'ascii'
)
response = self.client.get(
reverse('api-po-so-calendar', kwargs={'ordertype': 'purchase-order'}),
format='json',
headers={'authorization': f'basic {base64_token}'},
)
self.assertEqual(response.status_code, 200)
def test_po_calendar_auth_malformed(self):
"""Test that malformed basic authorization headers return 401, not 500."""
self.client.logout()
url = reverse('api-po-so-calendar', kwargs={'ordertype': 'purchase-order'})
for token in [
'not-base64!!', # invalid base64
base64.b64encode(b'\xff\xfe\xfd').decode('ascii'), # invalid utf-8
base64.b64encode(b'no-colon-here').decode('ascii'), # no separator
]:
response = self.client.get(
url, format='json', headers={'authorization': f'basic {token}'}
)
self.assertEqual(response.status_code, 401)
self.assertEqual(response['WWW-Authenticate'], 'Basic realm="api"')
def test_po_calendar_no_permission(self):
"""Test that an authenticated user without purchase_order view permission is denied."""
self.clearRoles()