Skip to content
Merged
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
88 changes: 88 additions & 0 deletions tests/unit/test_jwt_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from datetime import datetime, timedelta, timezone

import jwt
import pytest
from fastapi import HTTPException, status

from app.middleware.jw_auth import jw_admin_middleware, settings


class DummyRequest:
def __init__(self, token=None):
self.headers = {}
if token is not None:
self.headers["Authorization"] = token


@pytest.fixture(autouse=True)
def set_admin_secret(monkeypatch):
# Ensure the admin_secret is consistent for tests
monkeypatch.setattr(settings, "admin_secret", "adminsecret")
yield


# Helper to generate admin tokens
def make_admin_token(payload):
return jwt.encode(payload, settings.admin_secret, algorithm="HS256")


def test_no_authorization_header():
req = DummyRequest()
with pytest.raises(HTTPException) as exc:
jw_admin_middleware(req)
assert exc.value.status_code == status.HTTP_401_UNAUTHORIZED
assert "not provided" in exc.value.detail.lower()


def test_malformed_authorization_header():
req = DummyRequest(token="Invalid header")
with pytest.raises(HTTPException) as exc:
jw_admin_middleware(req)
assert exc.value.status_code == status.HTTP_401_UNAUTHORIZED
assert "must start with 'Bearer '" in exc.value.detail


def test_expired_token():
exp = datetime.now(timezone.utc) - timedelta(seconds=1)
token = make_admin_token({"isAdmin": True, "exp": exp})
req = DummyRequest(token=f"Bearer {token}")
with pytest.raises(HTTPException) as exc:
jw_admin_middleware(req)
assert exc.value.status_code == status.HTTP_401_UNAUTHORIZED
assert "expired" in exc.value.detail.lower()


def test_invalid_token_decoding():
req = DummyRequest(token="Bearer not.a.jwt")
with pytest.raises(HTTPException) as exc:
jw_admin_middleware(req)
assert exc.value.status_code == status.HTTP_401_UNAUTHORIZED
assert "validate credentials" in exc.value.detail.lower()


def test_missing_isadmin_claim():
exp = datetime.now(timezone.utc) + timedelta(minutes=5)
token = make_admin_token({"exp": exp})
req = DummyRequest(token=f"Bearer {token}")
with pytest.raises(HTTPException) as exc:
jw_admin_middleware(req)
assert exc.value.status_code == status.HTTP_403_FORBIDDEN
assert "permission" in exc.value.detail.lower()


def test_isadmin_false():
exp = datetime.now(timezone.utc) + timedelta(minutes=5)
token = make_admin_token({"isAdmin": False, "exp": exp})
req = DummyRequest(token=f"Bearer {token}")
with pytest.raises(HTTPException) as exc:
jw_admin_middleware(req)
assert exc.value.status_code == status.HTTP_403_FORBIDDEN
assert "permission" in exc.value.detail.lower()


def test_valid_admin_token():
exp = datetime.now(timezone.utc) + timedelta(minutes=5)
token = make_admin_token({"isAdmin": True, "exp": exp})
req = DummyRequest(token=f"Bearer {token}")
result = jw_admin_middleware(req)
assert result is True
86 changes: 86 additions & 0 deletions tests/unit/test_jwt_auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import uuid
from datetime import datetime, timedelta, timezone

import jwt
import pytest
from fastapi import HTTPException

from app.middleware.jw_auth import jw_auth_middleware, settings


class DummyRequest:
def __init__(self, token=None):
self.headers = {}
if token is not None:
self.headers["Authorization"] = token


@pytest.fixture(autouse=True)
def set_jwt_secret(monkeypatch):
# Ensure the jwt_secret is consistent
monkeypatch.setattr(settings, "jwt_secret", "mysecret")
yield


# Helper to generate tokens
def make_token(payload):
return jwt.encode(payload, settings.jwt_secret, algorithm="HS256")


def test_no_authorization_header():
req = DummyRequest()
with pytest.raises(HTTPException) as exc:
jw_auth_middleware(req)
assert exc.value.status_code == 401
assert "not provided" in exc.value.detail.lower()


def test_malformed_authorization_header():
req = DummyRequest(token="Invalid header")
with pytest.raises(HTTPException) as exc:
jw_auth_middleware(req)
assert exc.value.status_code == 401
assert "must start with 'Bearer '" in exc.value.detail


def test_expired_token():
exp = datetime.now(timezone.utc) - timedelta(seconds=1)
token = make_token({"userID": str(uuid.uuid4()), "exp": exp})
req = DummyRequest(token=f"Bearer {token}")
with pytest.raises(HTTPException) as exc:
jw_auth_middleware(req)
assert exc.value.status_code == 401
assert "expired" in exc.value.detail.lower()


def test_invalid_token_decoding():
# Wrong token string
req = DummyRequest(token="Bearer not.a.jwt")
with pytest.raises(HTTPException) as exc:
jw_auth_middleware(req)
assert exc.value.status_code == 401
assert "validate credentials" in exc.value.detail.lower()


def test_invalid_userid_format():
# userID not a valid UUID
exp = datetime.now(timezone.utc) + timedelta(minutes=5)
token = make_token({"userID": "not-uuid", "exp": exp})
req = DummyRequest(token=f"Bearer {token}")
with pytest.raises(HTTPException) as exc:
jw_auth_middleware(req)
assert exc.value.status_code == 401
assert "invalid userid" in exc.value.detail.lower()


def test_valid_token_returns_uuid():
user_id = uuid.uuid4()
exp = datetime.now(timezone.utc) + timedelta(minutes=5)
token = make_token({"userID": str(user_id), "exp": exp})
req = DummyRequest(token=f"Bearer {token}")
result = jw_auth_middleware(req)
assert isinstance(result, uuid.UUID)
assert result == user_id


# End of jw_auth_middleware tests