Files
omnara-agent-monitor/backend/tests/test_auth.py
Kartik Sarangmath d12fe4a101 Initial commit
2025-07-08 19:17:44 -07:00

238 lines
8.4 KiB
Python

"""Tests for authentication endpoints."""
from datetime import datetime, timezone
from uuid import uuid4
from unittest.mock import patch, Mock
from shared.database.models import User, APIKey
class TestAuthEndpoints:
"""Test authentication endpoints."""
def test_get_session_unauthenticated(self, client):
"""Test getting session when not authenticated."""
response = client.get("/api/v1/auth/session")
assert response.status_code == 401
assert response.json()["detail"] == "Not authenticated"
def test_get_session_authenticated(self, authenticated_client, test_user):
"""Test getting session when authenticated."""
response = authenticated_client.get("/api/v1/auth/session")
assert response.status_code == 200
data = response.json()
assert data["id"] == str(test_user.id)
assert data["email"] == test_user.email
assert data["display_name"] == test_user.display_name
def test_get_current_user_profile(self, authenticated_client, test_user):
"""Test getting current user profile."""
response = authenticated_client.get("/api/v1/auth/me")
assert response.status_code == 200
data = response.json()
assert data["id"] == str(test_user.id)
assert data["email"] == test_user.email
assert data["display_name"] == test_user.display_name
@patch("backend.auth.utils.get_supabase_client")
def test_update_user_profile(
self, mock_supabase, authenticated_client, test_user, test_db
):
"""Test updating user profile."""
# Mock Supabase client
mock_client = Mock()
mock_client.auth.admin.update_user_by_id = Mock()
mock_supabase.return_value = mock_client
new_display_name = "Updated Test User"
response = authenticated_client.patch(
"/api/v1/auth/me", json={"display_name": new_display_name}
)
assert response.status_code == 200
data = response.json()
assert data["display_name"] == new_display_name
# Verify in database
test_db.refresh(test_user)
assert test_user.display_name == new_display_name
# Verify Supabase was called
mock_client.auth.admin.update_user_by_id.assert_called_once()
def test_sync_user(self, authenticated_client, test_user, test_db):
"""Test syncing user from Supabase."""
response = authenticated_client.post(
"/api/v1/auth/sync-user",
json={
"id": str(test_user.id),
"email": test_user.email,
"display_name": "Synced Name",
},
)
assert response.status_code == 200
assert response.json()["message"] == "User synced successfully"
# Verify display name was updated
test_db.refresh(test_user)
assert test_user.display_name == "Synced Name"
def test_sync_user_forbidden(self, authenticated_client, test_user):
"""Test syncing a different user is forbidden."""
different_user_id = str(uuid4())
response = authenticated_client.post(
"/api/v1/auth/sync-user",
json={
"id": different_user_id,
"email": "other@example.com",
"display_name": "Other User",
},
)
assert response.status_code == 403
assert response.json()["detail"] == "Cannot sync different user"
class TestAPIKeyEndpoints:
"""Test API key management endpoints."""
@patch("backend.auth.routes.create_api_key_jwt")
def test_create_api_key(
self, mock_create_jwt, authenticated_client, test_user, test_db
):
"""Test creating an API key."""
mock_jwt_token = "test.jwt.token"
mock_create_jwt.return_value = mock_jwt_token
response = authenticated_client.post(
"/api/v1/auth/api-keys",
json={"name": "Test API Key", "expires_in_days": 30},
)
assert response.status_code == 200
data = response.json()
assert data["name"] == "Test API Key"
assert data["api_key"] == mock_jwt_token
assert "expires_at" in data
# Verify in database
api_key = test_db.query(APIKey).filter(APIKey.user_id == test_user.id).first()
assert api_key is not None
assert api_key.name == "Test API Key"
assert api_key.is_active is True
@patch("backend.auth.routes.create_api_key_jwt")
def test_create_api_key_max_limit(
self, mock_create_jwt, authenticated_client, test_user, test_db
):
"""Test creating API key when at max limit."""
mock_create_jwt.return_value = "test.jwt.token"
# Create 50 existing API keys
for i in range(50):
api_key = APIKey(
id=uuid4(),
user_id=test_user.id,
name=f"Key {i}",
api_key_hash="hash",
api_key=f"token{i}",
is_active=True,
created_at=datetime.now(timezone.utc),
)
test_db.add(api_key)
test_db.commit()
response = authenticated_client.post(
"/api/v1/auth/api-keys",
json={"name": "One Too Many", "expires_in_days": 30},
)
assert response.status_code == 400
assert "Maximum of 50 active API keys allowed" in response.json()["detail"]
def test_list_api_keys(self, authenticated_client, test_user, test_db):
"""Test listing API keys."""
# Create test API keys
api_keys = []
for i in range(3):
api_key = APIKey(
id=uuid4(),
user_id=test_user.id,
name=f"Key {i}",
api_key_hash=f"hash{i}",
api_key=f"token{i}",
is_active=i != 2, # Last one is inactive
created_at=datetime.now(timezone.utc),
)
api_keys.append(api_key)
test_db.add(api_key)
test_db.commit()
response = authenticated_client.get("/api/v1/auth/api-keys")
assert response.status_code == 200
data = response.json()
assert len(data) == 3
# Should be ordered by created_at desc
assert data[0]["name"] == "Key 2"
assert data[0]["is_active"] is False
assert data[1]["name"] == "Key 1"
assert data[1]["is_active"] is True
def test_revoke_api_key(self, authenticated_client, test_user, test_db):
"""Test revoking an API key."""
# Create test API key
api_key = APIKey(
id=uuid4(),
user_id=test_user.id,
name="Test Key",
api_key_hash="hash",
api_key="token",
is_active=True,
created_at=datetime.now(timezone.utc),
)
test_db.add(api_key)
test_db.commit()
response = authenticated_client.delete(f"/api/v1/auth/api-keys/{api_key.id}")
assert response.status_code == 200
assert response.json()["message"] == "API key revoked successfully"
# Verify in database
test_db.refresh(api_key)
assert api_key.is_active is False
def test_revoke_api_key_not_found(self, authenticated_client):
"""Test revoking a non-existent API key."""
fake_id = str(uuid4())
response = authenticated_client.delete(f"/api/v1/auth/api-keys/{fake_id}")
assert response.status_code == 404
assert response.json()["detail"] == "API key not found"
def test_revoke_api_key_wrong_user(self, authenticated_client, test_db):
"""Test revoking another user's API key."""
# Create another user
other_user = User(
id=uuid4(),
email="other@example.com",
display_name="Other User",
created_at=datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc),
)
test_db.add(other_user)
# Create API key for other user
api_key = APIKey(
id=uuid4(),
user_id=other_user.id,
name="Other's Key",
api_key_hash="hash",
api_key="token",
is_active=True,
created_at=datetime.now(timezone.utc),
)
test_db.add(api_key)
test_db.commit()
response = authenticated_client.delete(f"/api/v1/auth/api-keys/{api_key.id}")
assert response.status_code == 404
assert response.json()["detail"] == "API key not found"