# tests/integration/api/v1/admin/test_auth.py """Integration tests for admin authentication endpoints. Tests the /api/v1/admin/auth/* endpoints. """ from datetime import UTC, datetime, timedelta import pytest from jose import jwt @pytest.mark.integration @pytest.mark.api @pytest.mark.auth class TestAdminAuthAPI: """Test admin authentication endpoints at /api/v1/admin/auth/*.""" def test_login_success(self, client, test_admin): """Test successful admin login.""" response = client.post( "/api/v1/admin/auth/login", json={"email_or_username": test_admin.username, "password": "adminpass123"}, ) assert response.status_code == 200 data = response.json() assert "access_token" in data assert data["token_type"] == "bearer" assert "expires_in" in data assert data["user"]["username"] == test_admin.username assert data["user"]["email"] == test_admin.email def test_login_with_email(self, client, test_admin): """Test admin login with email instead of username.""" response = client.post( "/api/v1/admin/auth/login", json={"email_or_username": test_admin.email, "password": "adminpass123"}, ) assert response.status_code == 200 data = response.json() assert "access_token" in data assert data["user"]["email"] == test_admin.email def test_login_wrong_password(self, client, test_admin): """Test login with wrong password.""" response = client.post( "/api/v1/admin/auth/login", json={ "email_or_username": test_admin.username, "password": "wrongpassword", }, ) assert response.status_code == 401 data = response.json() assert data["error_code"] == "INVALID_CREDENTIALS" def test_login_nonexistent_user(self, client): """Test login with nonexistent user.""" response = client.post( "/api/v1/admin/auth/login", json={"email_or_username": "nonexistent", "password": "password123"}, ) assert response.status_code == 401 data = response.json() assert data["error_code"] == "INVALID_CREDENTIALS" def test_login_inactive_user(self, client, db, test_admin): """Test login with inactive admin account.""" original_status = test_admin.is_active test_admin.is_active = False db.commit() try: response = client.post( "/api/v1/admin/auth/login", json={ "email_or_username": test_admin.username, "password": "adminpass123", }, ) assert response.status_code == 403 data = response.json() assert data["error_code"] == "USER_NOT_ACTIVE" finally: test_admin.is_active = original_status db.commit() def test_login_non_admin_user_rejected(self, client, test_user): """Test that non-admin users cannot use admin login.""" response = client.post( "/api/v1/admin/auth/login", json={"email_or_username": test_user.username, "password": "testpass123"}, ) assert response.status_code == 401 data = response.json() assert data["error_code"] == "INVALID_CREDENTIALS" def test_login_validation_error(self, client): """Test login with invalid request format.""" response = client.post( "/api/v1/admin/auth/login", json={ "email_or_username": "", # Empty }, ) assert response.status_code == 422 data = response.json() assert data["error_code"] == "VALIDATION_ERROR" def test_get_current_admin_info(self, client, admin_headers, test_admin): """Test getting current admin user info.""" response = client.get("/api/v1/admin/auth/me", headers=admin_headers) assert response.status_code == 200 data = response.json() assert data["username"] == test_admin.username assert data["email"] == test_admin.email assert data["role"] == "admin" assert data["is_active"] is True def test_get_current_admin_without_auth(self, client): """Test getting current admin without authentication.""" response = client.get("/api/v1/admin/auth/me") assert response.status_code == 401 data = response.json() assert data["error_code"] == "INVALID_TOKEN" def test_get_current_admin_invalid_token(self, client): """Test getting current admin with invalid token.""" response = client.get( "/api/v1/admin/auth/me", headers={"Authorization": "Bearer invalid_token"} ) assert response.status_code == 401 data = response.json() assert data["error_code"] == "INVALID_TOKEN" def test_get_current_admin_expired_token(self, client, test_admin, auth_manager): """Test getting current admin with expired token.""" expired_payload = { "sub": str(test_admin.id), "username": test_admin.username, "email": test_admin.email, "role": test_admin.role, "exp": datetime.now(UTC) - timedelta(hours=1), "iat": datetime.now(UTC) - timedelta(hours=2), } expired_token = jwt.encode( expired_payload, auth_manager.secret_key, algorithm=auth_manager.algorithm ) response = client.get( "/api/v1/admin/auth/me", headers={"Authorization": f"Bearer {expired_token}"}, ) assert response.status_code == 401 data = response.json() assert data["error_code"] == "TOKEN_EXPIRED" def test_logout(self, client, admin_headers): """Test admin logout.""" response = client.post("/api/v1/admin/auth/logout", headers=admin_headers) assert response.status_code == 200 data = response.json() assert data["message"] == "Logged out successfully"