decorator: Extract get_basic_credentials.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
This commit is contained in:
Zixuan James Li 2022-08-01 16:50:38 -04:00 committed by Tim Abbott
parent d3468e3f78
commit ac2185a2e8
1 changed files with 42 additions and 18 deletions

View File

@ -4,7 +4,18 @@ import logging
import urllib
from functools import wraps
from io import BytesIO
from typing import TYPE_CHECKING, Callable, Dict, Optional, Sequence, TypeVar, Union, cast, overload
from typing import (
TYPE_CHECKING,
Callable,
Dict,
Optional,
Sequence,
Tuple,
TypeVar,
Union,
cast,
overload,
)
import django_otp
from django.conf import settings
@ -711,6 +722,33 @@ def authenticated_uploads_api_view(
return _wrapped_view_func
def get_basic_credentials(
request: HttpRequest, beanstalk_email_decode: bool = False
) -> Tuple[str, str]:
"""
Extracts the role and API key as a tuple from the Authorization header
for HTTP basic authentication.
"""
try:
# Grab the base64-encoded authentication string, decode it, and split it into
# the email and API key
auth_type, credentials = request.headers["Authorization"].split()
# case insensitive per RFC 1945
if auth_type.lower() != "basic":
raise JsonableError(_("This endpoint requires HTTP basic authentication."))
role, api_key = base64.b64decode(credentials).decode().split(":")
if beanstalk_email_decode:
# Beanstalk's web hook UI rejects URL with a @ in the username section
# So we ask the user to replace them with %40
role = role.replace("%40", "@")
except ValueError:
raise UnauthorizedError(_("Invalid authorization header for basic auth"))
except KeyError:
raise UnauthorizedError(_("Missing authorization header for basic auth"))
return role, api_key
# A more REST-y authentication decorator, using, in particular, HTTP basic
# authentication.
#
@ -737,23 +775,9 @@ def authenticated_rest_api_view(
def _wrapped_func_arguments(
request: HttpRequest, /, *args: ParamT.args, **kwargs: ParamT.kwargs
) -> HttpResponse:
# First try block attempts to get the credentials we need to do authentication
try:
# Grab the base64-encoded authentication string, decode it, and split it into
# the email and API key
auth_type, credentials = request.headers["Authorization"].split()
# case insensitive per RFC 1945
if auth_type.lower() != "basic":
raise JsonableError(_("This endpoint requires HTTP basic authentication."))
role, api_key = base64.b64decode(credentials).decode().split(":")
if beanstalk_email_decode:
# Beanstalk's web hook UI rejects URL with a @ in the username section
# So we ask the user to replace them with %40
role = role.replace("%40", "@")
except ValueError:
raise UnauthorizedError(_("Invalid authorization header for basic auth"))
except KeyError:
raise UnauthorizedError(_("Missing authorization header for basic auth"))
role, api_key = get_basic_credentials(
request, beanstalk_email_decode=beanstalk_email_decode
)
# Now we try to do authentication or die
try: