diff --git a/cognee/tests/unit/api/test_conditional_authentication_endpoints.py b/cognee/tests/unit/api/test_conditional_authentication_endpoints.py index bc9260cd3..8f86f082b 100644 --- a/cognee/tests/unit/api/test_conditional_authentication_endpoints.py +++ b/cognee/tests/unit/api/test_conditional_authentication_endpoints.py @@ -3,6 +3,7 @@ from unittest.mock import patch, AsyncMock, MagicMock from uuid import uuid4 from fastapi.testclient import TestClient from types import SimpleNamespace +import importlib from cognee.api.client import app @@ -30,6 +31,10 @@ def mock_authenticated_user(): tenant_id=uuid4(), ) +gau_mod = importlib.import_module( + "cognee.modules.users.methods.get_authenticated_user" +) + class TestConditionalAuthenticationEndpoints: """Test that API endpoints work correctly with conditional authentication.""" @@ -51,7 +56,7 @@ class TestConditionalAuthenticationEndpoints: assert response.json() == {"message": "Hello, World, I am alive!"} @patch( - "cognee.modules.users.methods.get_authenticated_user.REQUIRE_AUTHENTICATION", + "cognee.api.client.REQUIRE_AUTHENTICATION", False, ) def test_openapi_schema_no_global_security(self, client): @@ -71,9 +76,9 @@ class TestConditionalAuthenticationEndpoints: assert "CookieAuth" in security_schemes @patch("cognee.api.v1.add.add") - @patch("cognee.modules.users.methods.get_default_user.get_default_user", new_callable=AsyncMock) + @patch.object(gau_mod, 'get_default_user', new_callable=AsyncMock) @patch( - "cognee.modules.users.methods.get_authenticated_user.REQUIRE_AUTHENTICATION", + "cognee.api.client.REQUIRE_AUTHENTICATION", False, ) def test_add_endpoint_with_conditional_auth( @@ -91,12 +96,14 @@ class TestConditionalAuthenticationEndpoints: response = client.post("/api/v1/add", files=files, data=form_data) + assert mock_get_default_user.call_count == 1 + # Core test: authentication is not required (should not get 401) assert response.status_code != 401 - @patch("cognee.modules.users.methods.get_default_user.get_default_user", new_callable=AsyncMock) + @patch.object(gau_mod, 'get_default_user', new_callable=AsyncMock) @patch( - "cognee.modules.users.methods.get_authenticated_user.REQUIRE_AUTHENTICATION", + "cognee.api.client.REQUIRE_AUTHENTICATION", False, ) def test_conditional_authentication_works_with_current_environment( @@ -115,6 +122,8 @@ class TestConditionalAuthenticationEndpoints: response = client.post("/api/v1/add", files=files, data=form_data) + assert mock_get_default_user.call_count == 1 + # Core test: authentication is not required (should not get 401) assert response.status_code != 401 # Note: This test verifies conditional authentication works in the current environment @@ -134,7 +143,7 @@ class TestConditionalAuthenticationBehavior: ("/api/v1/datasets", "GET"), ], ) - @patch("cognee.modules.users.methods.get_default_user.get_default_user", new_callable=AsyncMock) + @patch.object(gau_mod, 'get_default_user', new_callable=AsyncMock) def test_get_endpoints_work_without_auth( self, mock_get_default, client, endpoint, method, mock_default_user ): @@ -146,6 +155,8 @@ class TestConditionalAuthenticationBehavior: elif method == "POST": response = client.post(endpoint, json={}) + assert mock_get_default.call_count == 1 + # Should not return 401 Unauthorized (authentication is optional by default) assert response.status_code != 401 @@ -159,9 +170,14 @@ class TestConditionalAuthenticationBehavior: except Exception: pass # If response is not JSON, that's fine - @patch("cognee.modules.settings.get_settings.get_vectordb_config") - @patch("cognee.modules.settings.get_settings.get_llm_config") - @patch("cognee.modules.users.methods.get_default_user.get_default_user", new_callable=AsyncMock) + + gsm_mod = importlib.import_module( + "cognee.modules.settings.get_settings" + ) + + @patch.object(gsm_mod, 'get_vectordb_config') + @patch.object(gsm_mod, 'get_llm_config') + @patch.object(gau_mod, 'get_default_user', new_callable=AsyncMock) def test_settings_endpoint_integration( self, mock_get_default, mock_llm_config, mock_vector_config, client, mock_default_user ): @@ -185,6 +201,8 @@ class TestConditionalAuthenticationBehavior: response = client.get("/api/v1/settings") + assert mock_get_default.call_count == 1 + # Core test: authentication is not required (should not get 401) assert response.status_code != 401 # Note: This test verifies conditional authentication works for settings endpoint @@ -197,7 +215,7 @@ class TestConditionalAuthenticationErrorHandling: def client(self): return TestClient(app) - @patch("cognee.modules.users.methods.get_default_user.get_default_user", new_callable=AsyncMock) + @patch.object(gau_mod, 'get_default_user', new_callable=AsyncMock) def test_get_default_user_fails(self, mock_get_default, client): """Test behavior when get_default_user fails (with current environment).""" mock_get_default.side_effect = Exception("Database connection failed") diff --git a/cognee/tests/unit/modules/users/test_conditional_authentication.py b/cognee/tests/unit/modules/users/test_conditional_authentication.py index 13e4a304d..99c971321 100644 --- a/cognee/tests/unit/modules/users/test_conditional_authentication.py +++ b/cognee/tests/unit/modules/users/test_conditional_authentication.py @@ -4,22 +4,22 @@ import pytest from unittest.mock import AsyncMock, patch from uuid import uuid4 from types import SimpleNamespace +import importlib + from cognee.modules.users.models import User +gau_mod = importlib.import_module( + "cognee.modules.users.methods.get_authenticated_user" +) + + class TestConditionalAuthentication: """Test cases for conditional authentication functionality.""" @pytest.mark.asyncio - @patch( - "cognee.modules.users.methods.get_authenticated_user.get_default_user", - new_callable=AsyncMock, - ) - @patch( - "cognee.modules.users.methods.get_authenticated_user.REQUIRE_AUTHENTICATION", - False, - ) + @patch.object(gau_mod, 'get_default_user', new_callable=AsyncMock) async def test_require_authentication_false_no_token_returns_default_user( self, mock_get_default ): @@ -28,25 +28,16 @@ class TestConditionalAuthentication: mock_default_user = SimpleNamespace(id=uuid4(), email="default@example.com", is_active=True) mock_get_default.return_value = mock_default_user - from cognee.modules.users.methods.get_authenticated_user import ( - get_authenticated_user, - ) + # Use gau_mod.get_authenticated_user instead # Test with None user (no authentication) - result = await get_authenticated_user(user=None) + result = await gau_mod.get_authenticated_user(user=None) assert result == mock_default_user mock_get_default.assert_called_once() @pytest.mark.asyncio - @patch( - "cognee.modules.users.methods.get_authenticated_user.get_default_user", - new_callable=AsyncMock, - ) - @patch( - "cognee.modules.users.methods.get_authenticated_user.REQUIRE_AUTHENTICATION", - False, - ) + @patch.object(gau_mod, 'get_default_user', new_callable=AsyncMock) async def test_require_authentication_false_with_valid_user_returns_user( self, mock_get_default ): @@ -59,22 +50,17 @@ class TestConditionalAuthentication: is_verified=True, ) - from cognee.modules.users.methods.get_authenticated_user import ( - get_authenticated_user, - ) + # Use gau_mod.get_authenticated_user instead # Test with authenticated user - result = await get_authenticated_user(user=mock_authenticated_user) + result = await gau_mod.get_authenticated_user(user=mock_authenticated_user) assert result == mock_authenticated_user mock_get_default.assert_not_called() @pytest.mark.asyncio - @patch( - "cognee.modules.users.methods.get_authenticated_user.REQUIRE_AUTHENTICATION", - True, - ) - async def test_require_authentication_true_with_user_returns_user(self): + @patch.object(gau_mod, 'get_default_user', new_callable=AsyncMock) + async def test_require_authentication_true_with_user_returns_user(self, mock_get_default): """Test that when REQUIRE_AUTHENTICATION=true and user present, returns user.""" mock_authenticated_user = User( id=uuid4(), @@ -84,11 +70,9 @@ class TestConditionalAuthentication: is_verified=True, ) - from cognee.modules.users.methods.get_authenticated_user import ( - get_authenticated_user, - ) + # Use gau_mod.get_authenticated_user instead - result = await get_authenticated_user(user=mock_authenticated_user) + result = await gau_mod.get_authenticated_user(user=mock_authenticated_user) assert result == mock_authenticated_user @@ -144,7 +128,7 @@ class TestConditionalAuthenticationEnvironmentVariables: from cognee.modules.users.methods.get_authenticated_user import ( REQUIRE_AUTHENTICATION, ) - + importlib.invalidate_caches() assert not REQUIRE_AUTHENTICATION def test_require_authentication_true(self): @@ -211,38 +195,19 @@ class TestConditionalAuthenticationEdgeCases: """Test edge cases and error scenarios.""" @pytest.mark.asyncio - @patch( - "cognee.modules.users.methods.get_authenticated_user.get_default_user", - new_callable=AsyncMock, - ) - @patch.dict(os.environ, {"REQUIRE_AUTHENTICATION": "false"}) + @patch.object(gau_mod, 'get_default_user', new_callable=AsyncMock) async def test_get_default_user_raises_exception(self, mock_get_default): """Test behavior when get_default_user raises an exception.""" - from cognee.modules.users.methods.get_authenticated_user import ( - get_authenticated_user, - ) - mock_get_default.side_effect = Exception("Database error") # This should propagate the exception with pytest.raises(Exception, match="Database error"): - await get_authenticated_user(user=None) + await gau_mod.get_authenticated_user(user=None) @pytest.mark.asyncio - @patch( - "cognee.modules.users.methods.get_authenticated_user.get_default_user", - new_callable=AsyncMock, - ) - @patch( - "cognee.modules.users.methods.get_authenticated_user.REQUIRE_AUTHENTICATION", - False, - ) + @patch.object(gau_mod, 'get_default_user', new_callable=AsyncMock) async def test_user_type_consistency(self, mock_get_default): """Test that the function always returns the same type.""" - from cognee.modules.users.methods.get_authenticated_user import ( - get_authenticated_user, - ) - mock_user = User( id=uuid4(), email="test@example.com", @@ -255,11 +220,11 @@ class TestConditionalAuthenticationEdgeCases: mock_get_default.return_value = mock_default_user # Test with user - result1 = await get_authenticated_user(user=mock_user) + result1 = await gau_mod.get_authenticated_user(user=mock_user) assert result1 == mock_user # Test with None - result2 = await get_authenticated_user(user=None) + result2 = await gau_mod.get_authenticated_user(user=None) assert result2 == mock_default_user # Both should have user-like interface @@ -277,14 +242,7 @@ class TestConditionalAuthenticationEdgeCases: class TestAuthenticationScenarios: """Test specific authentication scenarios that could occur in FastAPI Users.""" - @patch( - "cognee.modules.users.methods.get_authenticated_user.get_default_user", - new_callable=AsyncMock, - ) - @patch( - "cognee.modules.users.methods.get_authenticated_user.REQUIRE_AUTHENTICATION", - False, - ) + @patch.object(gau_mod, 'get_default_user', new_callable=AsyncMock) async def test_fallback_to_default_user_scenarios(self, mock_get_default): """ Test fallback to default user for all scenarios where FastAPI Users returns None: @@ -299,19 +257,11 @@ class TestAuthenticationScenarios: mock_default_user = SimpleNamespace(id=uuid4(), email="default@example.com") mock_get_default.return_value = mock_default_user - from cognee.modules.users.methods.get_authenticated_user import ( - get_authenticated_user, - ) - # All the above scenarios result in user=None being passed to our function - result = await get_authenticated_user(user=None) + result = await gau_mod.get_authenticated_user(user=None) assert result == mock_default_user mock_get_default.assert_called_once() - @patch( - "cognee.modules.users.methods.get_authenticated_user.REQUIRE_AUTHENTICATION", - False, - ) async def test_scenario_valid_active_user(self): """Scenario: Valid JWT and user exists and is active → returns the user.""" mock_user = User( @@ -322,9 +272,7 @@ class TestAuthenticationScenarios: is_verified=True, ) - from cognee.modules.users.methods.get_authenticated_user import ( - get_authenticated_user, - ) + # Use gau_mod.get_authenticated_user instead - result = await get_authenticated_user(user=mock_user) + result = await gau_mod.get_authenticated_user(user=mock_user) assert result == mock_user