Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 5 additions & 5 deletions isic/zip_download/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import json
import logging
from pathlib import PurePosixPath
from typing import TYPE_CHECKING, Literal
from typing import TYPE_CHECKING, Any, Literal

from botocore.signers import CloudFrontSigner
from django.conf import settings
Expand Down Expand Up @@ -63,20 +63,20 @@ def authenticate(self, request: HttpRequest, username: str, password: str) -> Li
class ZipDownloadTokenAuth(APIKeyQuery):
param_name = "token"

def authenticate(self, request: HttpRequest, key: str | None) -> dict:
def authenticate(self, request: HttpRequest, key: str | None) -> dict | None:
if not key:
raise AuthenticationError
return None

try:
token_dict = TimestampSigner().unsign_object(key, max_age=timedelta(days=1))
except BadSignature:
raise AuthenticationError from None
return None

token_dict["token"] = key
return token_dict


def zip_api_auth(request: HttpRequest):
def zip_api_auth(request: HttpRequest) -> Any:
"""
Protects the zip listing endpoint with basic auth.

Expand Down
26 changes: 26 additions & 0 deletions isic/zip_download/tests/test_zip_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from urllib.parse import ParseResult, parse_qs, urlparse

from django.conf import settings
from django.core.signing import TimestampSigner
from ninja.errors import AuthenticationError
import pytest

from isic.core.models import Image
Expand Down Expand Up @@ -48,6 +50,30 @@ def zip_basic_auth():
}


@pytest.mark.django_db
def test_zip_api_auth(mocker, authenticated_client, zip_basic_auth):
from isic.zip_download.api import zip_api_auth

token = TimestampSigner().sign_object({"token": "foo"})

request = mocker.MagicMock(
headers={"Authorization": "Basic " + b64encode(b":badcredentials").decode()}
)
with pytest.raises(AuthenticationError):
zip_api_auth(request)

request = mocker.MagicMock(
headers={"Authorization": zip_basic_auth["HTTP_AUTHORIZATION"]},
GET={"token": token},
)
assert zip_api_auth(request)

request = mocker.MagicMock(
headers={"Authorization": zip_basic_auth["HTTP_AUTHORIZATION"]}, GET={"token": "badtoken"}
)
assert not zip_api_auth(request)


@pytest.mark.django_db(transaction=True)
@pytest.mark.usefixtures("_random_images_with_licenses")
def test_zip_download_licenses(authenticated_client, zip_basic_auth):
Expand Down