import pytest from fastapi import status from unittest.mock import patch class TestUserAuthentication: """Test user login (LDAP + local password).""" def test_login_ldap_success(self, test_client, mock_ldap): """Test successful LDAP login.""" response = test_client.post( "/api/users/login", json={"username": "testuser", "password": "password123"} ) assert response.status_code == status.HTTP_200_OK assert "access_token" in response.json() assert response.json()["token_type"] == "bearer" def test_login_ldap_failure(self, test_client, mock_ldap): """Test failed LDAP login.""" mock_ldap.bind.side_effect = Exception("Invalid credentials") response = test_client.post( "/api/users/login", json={"username": "testuser", "password": "wrongpassword"} ) assert response.status_code == status.HTTP_401_UNAUTHORIZED def test_login_local_password(self, test_client, test_db): """Test local password authentication (fallback).""" from backend.models import User from backend.routers.users import get_password_hash # Create local user user = User( username="localuser", hashed_password=get_password_hash("password123"), role="user", origin="local" ) test_db.add(user) test_db.commit() response = test_client.post( "/api/users/login", json={"username": "localuser", "password": "password123"} ) assert response.status_code == status.HTTP_200_OK assert "access_token" in response.json() class TestUserCRUD: """Test user creation, read, update, delete.""" def test_create_user_admin_only(self, test_client, test_db, admin_token): """Test creating a user (admin only).""" response = test_client.post( "/api/users", json={ "username": "newuser", "password": "NewPass123!", "role": "user" }, headers={"Authorization": f"Bearer {admin_token}"} ) assert response.status_code == status.HTTP_201_CREATED data = response.json() assert data["username"] == "newuser" assert data["role"] == "user" def test_create_user_non_admin_denied(self, test_client, user_token): """Test that non-admin users cannot create users.""" response = test_client.post( "/api/users", json={ "username": "newuser", "password": "Pass123!", "role": "user" }, headers={"Authorization": f"Bearer {user_token}"} ) assert response.status_code == status.HTTP_403_FORBIDDEN def test_get_user_by_id(self, test_client, test_db): """Test retrieving a user by ID.""" from backend.models import User user = User( username="testuser", hashed_password="hashed", role="user", origin="local" ) test_db.add(user) test_db.commit() response = test_client.get(f"/api/users/{user.id}") assert response.status_code == status.HTTP_200_OK data = response.json() assert data["username"] == "testuser" def test_list_users(self, test_client, test_db): """Test listing all users.""" from backend.models import User user1 = User(username="user1", hashed_password="h", role="user", origin="local") user2 = User(username="user2", hashed_password="h", role="user", origin="local") test_db.add_all([user1, user2]) test_db.commit() response = test_client.get("/api/users") assert response.status_code == status.HTTP_200_OK data = response.json() assert len(data) >= 2 def test_update_user_admin_only(self, test_client, test_db, admin_token): """Test updating user (admin only).""" from backend.models import User user = User(username="testuser", hashed_password="h", role="user", origin="local") test_db.add(user) test_db.commit() response = test_client.put( f"/api/users/{user.id}", json={"username": "updateduser", "role": "admin"}, headers={"Authorization": f"Bearer {admin_token}"} ) assert response.status_code == status.HTTP_200_OK data = response.json() assert data["role"] == "admin" def test_delete_user_admin_only(self, test_client, test_db, admin_token): """Test deleting user (admin only).""" from backend.models import User user = User(username="testuser", hashed_password="h", role="user", origin="local") test_db.add(user) test_db.commit() user_id = user.id response = test_client.delete( f"/api/users/{user_id}", headers={"Authorization": f"Bearer {admin_token}"} ) assert response.status_code == status.HTTP_204_NO_CONTENT # Verify deletion response = test_client.get(f"/api/users/{user_id}") assert response.status_code == status.HTTP_404_NOT_FOUND