项目文件夹

文件
wehub-resource-sync c889a57b6b
Test Suites / Build CI Environment (push) Has been cancelled
Test Suites / Basic Tests (push) Has been cancelled
Test Suites / End-to-End Tests (push) Has been cancelled
Test Suites / CLI Tests (push) Has been cancelled
Test Suites / Slow End-to-End Tests (push) Has been cancelled
Test Suites / Graph Database Tests (push) Has been cancelled
Test Suites / Vector DB Tests (push) Has been cancelled
Test Suites / Temporal Graph Test (push) Has been cancelled
Test Suites / Search Test on Different DBs (push) Has been cancelled
Test Suites / Example Tests (push) Has been cancelled
Test Suites / Notebook Tests (push) Has been cancelled
Test Suites / OS and Python Tests Ubuntu (push) Has been cancelled
Test Suites / OS and Python Tests Extended (push) Has been cancelled
Test Suites / LLM Test Suite (push) Has been cancelled
Test Suites / S3 File Storage Test (push) Has been cancelled
Test Suites / Run Integration Tests (push) Has been cancelled
Test Suites / MCP Tests (push) Has been cancelled
Test Suites / Docker Compose Test (push) Has been cancelled
Test Suites / Docker CI test (push) Has been cancelled
Test Suites / Relational DB Migration Tests (push) Has been cancelled
Test Suites / Distributed Cognee Test (push) Has been cancelled
Test Suites / DB Examples Tests (push) Has been cancelled
Test Suites / Test Completion Status (push) Has been cancelled
Test Suites / Claude Code Review (push) Has been cancelled
Test Suites / basic checks (push) Has been cancelled
build | Build and Push Cognee MCP Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
build | Build and Push Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.11) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.12) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (kuzu, kuzu) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (neo4j, neo4j) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Examples (push) Has been cancelled
Weighted Edges Tests / Code Quality for Weighted Edges (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:02:24 +08:00

291 行
11 KiB
Python

import os
import sys
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.object(gau_mod, "get_default_user", new_callable=AsyncMock)
async def test_require_authentication_false_no_token_returns_default_user(
self, mock_get_default
):
"""Test that when REQUIRE_AUTHENTICATION=false and no token, returns default user."""
# Mock the default user
mock_default_user = SimpleNamespace(id=uuid4(), email="default@example.com", is_active=True)
mock_get_default.return_value = mock_default_user
# Use gau_mod.get_authenticated_user instead
# Test with None user (no authentication)
result = await gau_mod.get_authenticated_user(user=None)
assert result == mock_default_user
mock_get_default.assert_called_once()
@pytest.mark.asyncio
@patch.object(gau_mod, "get_user", new_callable=AsyncMock)
@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, mock_get_user
):
"""Test that when REQUIRE_AUTHENTICATION=false and valid user, returns that user."""
mock_authenticated_user = User(
id=uuid4(),
email="user@example.com",
hashed_password="hashed",
is_active=True,
is_verified=True,
)
mock_get_user.return_value = mock_authenticated_user
# Test with 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.object(gau_mod, "get_user", new_callable=AsyncMock)
@patch.object(gau_mod, "get_default_user", new_callable=AsyncMock)
async def test_require_authentication_true_with_user_returns_user(
self, mock_get_default, mock_get_user
):
"""Test that when REQUIRE_AUTHENTICATION=true and user present, returns user."""
mock_authenticated_user = User(
id=uuid4(),
email="user@example.com",
hashed_password="hashed",
is_active=True,
is_verified=True,
)
mock_get_user.return_value = mock_authenticated_user
result = await gau_mod.get_authenticated_user(user=mock_authenticated_user)
assert result == mock_authenticated_user
class TestConditionalAuthenticationIntegration:
"""Integration tests that test the full authentication flow."""
@pytest.mark.asyncio
async def test_fastapi_users_dependency_creation(self):
"""Test that FastAPI Users dependency can be created correctly."""
from cognee.modules.users.get_fastapi_users import get_fastapi_users
fastapi_users = get_fastapi_users()
# Test that we can create optional dependency
optional_dependency = fastapi_users.current_user(optional=True, active=True)
assert callable(optional_dependency)
# Test that we can create required dependency
required_dependency = fastapi_users.current_user(active=True) # optional=False by default
assert callable(required_dependency)
@pytest.mark.asyncio
async def test_conditional_authentication_function_exists(self):
"""Test that the conditional authentication function can be imported and used."""
from cognee.modules.users.methods.get_authenticated_user import (
get_authenticated_user,
REQUIRE_AUTHENTICATION,
)
# Should be callable
assert callable(get_authenticated_user)
# REQUIRE_AUTHENTICATION should be a boolean
assert isinstance(REQUIRE_AUTHENTICATION, bool)
class TestConditionalAuthenticationEnvironmentVariables:
"""Test environment variable handling."""
def _reimport(self):
module_name = "cognee.modules.users.methods.get_authenticated_user"
if module_name in sys.modules:
del sys.modules[module_name]
import importlib
return importlib.import_module(module_name)
def _reimport_flag(self):
return self._reimport().REQUIRE_AUTHENTICATION
def test_require_authentication_true(self):
"""Test that REQUIRE_AUTHENTICATION=true is parsed correctly when imported."""
with patch.dict(os.environ, {"REQUIRE_AUTHENTICATION": "true"}, clear=False):
assert self._reimport_flag() is True
def test_access_control_false_disables_auth_when_require_auth_unset(self):
"""ENABLE_BACKEND_ACCESS_CONTROL=false alone should disable auth (issue #2808)."""
env = {k: v for k, v in os.environ.items() if k != "REQUIRE_AUTHENTICATION"}
env["ENABLE_BACKEND_ACCESS_CONTROL"] = "false"
with patch.dict(os.environ, env, clear=True):
assert self._reimport_flag() is False
def test_explicit_require_auth_overrides_access_control(self):
"""REQUIRE_AUTHENTICATION=true wins even if ENABLE_BACKEND_ACCESS_CONTROL=false."""
with patch.dict(
os.environ,
{
"REQUIRE_AUTHENTICATION": "true",
"ENABLE_BACKEND_ACCESS_CONTROL": "false",
},
clear=False,
):
assert self._reimport_flag() is True
def test_explicit_require_auth_false_with_no_access_control_disables_auth(self):
"""REQUIRE_AUTHENTICATION=false + ENABLE_BACKEND_ACCESS_CONTROL=false: auth off."""
with patch.dict(
os.environ,
{
"REQUIRE_AUTHENTICATION": "false",
"ENABLE_BACKEND_ACCESS_CONTROL": "false",
},
clear=False,
):
assert self._reimport_flag() is False
def test_both_unset_defaults_to_require_auth(self):
"""With neither var set, default is to require authentication."""
env = {
k: v
for k, v in os.environ.items()
if k not in ("REQUIRE_AUTHENTICATION", "ENABLE_BACKEND_ACCESS_CONTROL")
}
with patch.dict(os.environ, env, clear=True):
mod = self._reimport()
assert mod.REQUIRE_AUTHENTICATION is True
assert mod.ENABLE_BACKEND_ACCESS_CONTROL is True
def test_multi_tenant_with_no_auth_is_coerced_to_require_auth(self):
"""REQUIRE_AUTHENTICATION=false + ENABLE_BACKEND_ACCESS_CONTROL=true is unsafe
and should be coerced to auth-on with a warning."""
with patch.dict(
os.environ,
{
"REQUIRE_AUTHENTICATION": "false",
"ENABLE_BACKEND_ACCESS_CONTROL": "true",
},
clear=False,
):
mod = self._reimport()
assert mod.REQUIRE_AUTHENTICATION is True
assert mod.ENABLE_BACKEND_ACCESS_CONTROL is True
def test_empty_string_treated_as_unset(self):
"""REQUIRE_AUTHENTICATION='' (e.g. `docker -e REQUIRE_AUTHENTICATION`) should
be treated as unset so it inherits from access control."""
with patch.dict(
os.environ,
{
"REQUIRE_AUTHENTICATION": "",
"ENABLE_BACKEND_ACCESS_CONTROL": "false",
},
clear=False,
):
assert self._reimport_flag() is False
class TestConditionalAuthenticationEdgeCases:
"""Test edge cases and error scenarios."""
@pytest.mark.asyncio
@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."""
mock_get_default.side_effect = Exception("Database error")
# This should propagate the exception
with pytest.raises(Exception, match="Database error"):
await gau_mod.get_authenticated_user(user=None)
@pytest.mark.asyncio
@patch.object(gau_mod, "get_user", new_callable=AsyncMock)
@patch.object(gau_mod, "get_default_user", new_callable=AsyncMock)
async def test_user_type_consistency(self, mock_get_default, mock_get_user):
"""Test that the function always returns the same type."""
mock_user = User(
id=uuid4(),
email="test@example.com",
hashed_password="hashed",
is_active=True,
is_verified=True,
)
mock_get_user.return_value = mock_user
mock_default_user = SimpleNamespace(id=uuid4(), email="default@example.com", is_active=True)
mock_get_default.return_value = mock_default_user
# Test with user
result1 = await gau_mod.get_authenticated_user(user=mock_user)
assert result1 == mock_user
# Test with None
result2 = await gau_mod.get_authenticated_user(user=None)
assert result2 == mock_default_user
# Both should have user-like interface
assert hasattr(result1, "id")
assert hasattr(result1, "email")
assert result1.id == mock_user.id
assert result1.email == mock_user.email
assert hasattr(result2, "id")
assert hasattr(result2, "email")
assert result2.id == mock_default_user.id
assert result2.email == mock_default_user.email
@pytest.mark.asyncio
class TestAuthenticationScenarios:
"""Test specific authentication scenarios that could occur in FastAPI Users."""
@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:
- No JWT/Cookie present
- Invalid JWT/Cookie
- Valid JWT but user doesn't exist in database
- Valid JWT but user is inactive (active=True requirement)
All these scenarios result in FastAPI Users returning None when optional=True,
which should trigger fallback to default user.
"""
mock_default_user = SimpleNamespace(id=uuid4(), email="default@example.com")
mock_get_default.return_value = mock_default_user
# All the above scenarios result in user=None being passed to our function
result = await gau_mod.get_authenticated_user(user=None)
assert result == mock_default_user
mock_get_default.assert_called_once()
@patch.object(gau_mod, "get_user", new_callable=AsyncMock)
async def test_scenario_valid_active_user(self, mock_get_user):
"""Scenario: Valid JWT and user exists and is active → returns the user."""
mock_user = User(
id=uuid4(),
email="active@example.com",
hashed_password="hashed",
is_active=True,
is_verified=True,
)
mock_get_user.return_value = mock_user
result = await gau_mod.get_authenticated_user(user=mock_user)
assert result == mock_user