- Fix UV index strategy: mark PyTorch CPU index as explicit with name - Add --index-strategy unsafe-best-match to Dockerfile uv pip install - Fix redis version constraint (>=5.0,<6) for ARQ compatibility - Fix Anthropic model name (claude-sonnet-4-5-20250929) - Fix IMAGE_PROVIDER enum value (gemini_flash, not google) - Resolve middlewares.py vs middlewares/ package conflict - Fix worker import paths (models.sql.presentation, models.sql.slide, utils split) - Fix seed script FK resolution by importing all related models - Fix test suite: async fixture scoping, greenlet dep, regex patterns, fixture params - Fix frontend TypeScript error (Boolean cast for layout.react_code) - Regenerate package-lock.json with i18n packages - Add initial Alembic migration (autogenerated from all models) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
78 lines
2.6 KiB
Python
78 lines
2.6 KiB
Python
"""Tests for auth_service: JWT creation/validation, dev login, user creation."""
|
|
import uuid
|
|
|
|
import pytest
|
|
|
|
from services.auth_service import AuthService
|
|
|
|
|
|
@pytest.fixture
|
|
def auth_service():
|
|
return AuthService()
|
|
|
|
|
|
class TestJWT:
|
|
def test_create_and_validate_token(self, auth_service):
|
|
"""Token round-trip: create → validate → same payload."""
|
|
from models.sql.user import UserModel
|
|
|
|
user = UserModel(
|
|
id=uuid.uuid4(),
|
|
email="jwt@test.com",
|
|
display_name="JWT User",
|
|
role="user",
|
|
is_active=True,
|
|
)
|
|
token = auth_service.create_session_jwt(user)
|
|
payload = auth_service.validate_token(token)
|
|
|
|
assert payload is not None
|
|
assert payload["sub"] == str(user.id)
|
|
assert payload["email"] == "jwt@test.com"
|
|
assert payload["role"] == "user"
|
|
|
|
def test_validate_invalid_token(self, auth_service):
|
|
assert auth_service.validate_token("garbage.token.here") is None
|
|
|
|
def test_validate_tampered_token(self, auth_service):
|
|
from models.sql.user import UserModel
|
|
|
|
user = UserModel(
|
|
id=uuid.uuid4(),
|
|
email="tamper@test.com",
|
|
display_name="Tamper",
|
|
role="user",
|
|
is_active=True,
|
|
)
|
|
token = auth_service.create_session_jwt(user)
|
|
# Tamper with the token
|
|
tampered = token[:-5] + "XXXXX"
|
|
assert auth_service.validate_token(tampered) is None
|
|
|
|
|
|
class TestDevLogin:
|
|
async def test_dev_login_success(self, auth_service, session):
|
|
"""Dev mode: correct password creates user."""
|
|
user = await auth_service.dev_login("dev@test.com", "testpass", session)
|
|
assert user is not None
|
|
assert user.email == "dev@test.com"
|
|
|
|
async def test_dev_login_wrong_password(self, auth_service, session):
|
|
user = await auth_service.dev_login("dev@test.com", "wrongpass", session)
|
|
assert user is None
|
|
|
|
async def test_dev_login_idempotent(self, auth_service, session):
|
|
"""Logging in twice with same email returns same user."""
|
|
user1 = await auth_service.dev_login("dev@test.com", "testpass", session)
|
|
user2 = await auth_service.dev_login("dev@test.com", "testpass", session)
|
|
assert user1.id == user2.id
|
|
|
|
|
|
class TestDevMode:
|
|
def test_is_dev_mode_when_no_azure(self, auth_service):
|
|
"""Without AZURE_AD_TENANT_ID, service is in dev mode."""
|
|
assert auth_service.is_dev_mode is True
|
|
|
|
def test_get_authorization_url_raises_in_dev_mode(self, auth_service):
|
|
with pytest.raises(ValueError, match="dev login"):
|
|
auth_service.get_authorization_url()
|