From 5a984d1e6b8168c85c5bcf374786220647a1464d Mon Sep 17 00:00:00 2001 From: Daniel Bedeleanu Date: Sat, 18 Apr 2026 16:57:18 +0000 Subject: [PATCH] test: add user authentication and CRUD tests --- backend/tests/test_users.py | 152 ++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 backend/tests/test_users.py diff --git a/backend/tests/test_users.py b/backend/tests/test_users.py new file mode 100644 index 00000000..7f90d4e4 --- /dev/null +++ b/backend/tests/test_users.py @@ -0,0 +1,152 @@ +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/auth/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/auth/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.auth import hash_password + + # Create local user + user = User( + username="localuser", + email="local@test.com", + hashed_password=hash_password("password123"), + role="user", + origin="local" + ) + test_db.add(user) + test_db.commit() + + response = test_client.post( + "/api/auth/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", + "email": "new@test.com", + "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["email"] == "new@test.com" + + 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", + "email": "new@test.com", + "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", + email="test@test.com", + 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", email="user1@test.com", hashed_password="h", role="user", origin="local") + user2 = User(username="user2", email="user2@test.com", 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", email="old@test.com", hashed_password="h", role="user", origin="local") + test_db.add(user) + test_db.commit() + + response = test_client.put( + f"/api/users/{user.id}", + json={"email": "new@test.com", "role": "admin"}, + headers={"Authorization": f"Bearer {admin_token}"} + ) + assert response.status_code == status.HTTP_200_OK + data = response.json() + assert data["email"] == "new@test.com" + + 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", email="test@test.com", 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