Initial commit
This commit is contained in:
commit
5cda7bc309
28 changed files with 1173 additions and 0 deletions
85
tests/test_auth.py
Normal file
85
tests/test_auth.py
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from django.test import RequestFactory
|
||||
|
||||
from yksa_kit.auth import (
|
||||
extract_token,
|
||||
request_can_ingest,
|
||||
request_has_valid_token,
|
||||
resolve_token,
|
||||
store_session_token,
|
||||
)
|
||||
from yksa_kit.models import ApiToken, TokenKind
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def rf() -> RequestFactory:
|
||||
return RequestFactory()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_returns_none_when_no_credentials(rf):
|
||||
assert extract_token(rf.get("/api/v1/things/")) is None
|
||||
assert request_has_valid_token(rf.get("/api/v1/things/")) is False
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_authorization_bearer_header(rf):
|
||||
token = ApiToken.objects.create(name="ci-job")
|
||||
resolved = extract_token(rf.get("/", HTTP_AUTHORIZATION=f"Bearer {token.token}"))
|
||||
assert resolved is not None and resolved.pk == token.pk
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_authorization_raw_header_accepted(rf):
|
||||
"""Plain header value without the 'Bearer ' prefix is tolerated."""
|
||||
token = ApiToken.objects.create(name="legacy-client")
|
||||
assert extract_token(rf.get("/", HTTP_AUTHORIZATION=token.token)) is not None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_query_string_token(rf):
|
||||
token = ApiToken.objects.create(name="browser")
|
||||
assert extract_token(rf.get("/", {"api_token": token.token})) is not None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_revoked_token_is_anonymous(rf):
|
||||
token = ApiToken.objects.create(name="revoked", is_active=False)
|
||||
assert extract_token(rf.get("/", HTTP_AUTHORIZATION=f"Bearer {token.token}")) is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_unknown_token_is_anonymous(rf):
|
||||
assert extract_token(rf.get("/", HTTP_AUTHORIZATION="Bearer nope")) is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_extract_token_updates_last_used(rf):
|
||||
token = ApiToken.objects.create(name="track-me")
|
||||
assert token.last_used_at is None
|
||||
extract_token(rf.get("/", HTTP_AUTHORIZATION=f"Bearer {token.token}"))
|
||||
token.refresh_from_db()
|
||||
assert token.last_used_at is not None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_only_ingest_tokens_may_push(rf):
|
||||
read = ApiToken.objects.create(name="reader")
|
||||
ingest = ApiToken.objects.create(name="station", kind=TokenKind.INGEST)
|
||||
assert request_can_ingest(rf.get("/", {"api_token": read.token})) is False
|
||||
assert request_can_ingest(rf.get("/", {"api_token": ingest.token})) is True
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_session_token_is_ignored_by_the_api_path(rf):
|
||||
"""The session carrier is for browser pages only; an API controller asking
|
||||
request_has_valid_token() must not be authenticated by a stale session."""
|
||||
token = ApiToken.objects.create(name="browser")
|
||||
request = rf.get("/")
|
||||
request.session = {}
|
||||
store_session_token(request, token)
|
||||
|
||||
assert request_has_valid_token(request) is False
|
||||
assert resolve_token(request) is not None
|
||||
Loading…
Add table
Add a link
Reference in a new issue