286a3eb20f
Implement multi-user BasicAuth pass-through mode (ADR-020) where each request includes BasicAuth credentials that are forwarded to Nextcloud APIs without persistent storage. Changes: - Add _get_client_from_basic_auth() in context.py to extract credentials from Authorization header (set by BasicAuthMiddleware) - Add AstrolabeClient for app password provisioning via Astrolabe API - Update oauth_sync.py with dual credential support (app passwords first, then refresh tokens as fallback) - Simplify oauth_tools.py provisioning logic - Add integration tests for app password provisioning and multi-user BasicAuth Features: - Stateless multi-user mode: credentials passed per-request - Optional background sync via app passwords (stored in Astrolabe) - Falls back to refresh tokens if app password not available - Test coverage for provisioning flow and pass-through mode Related: ADR-019 (Multi-user BasicAuth), ADR-020 (Deployment Modes) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
48 lines
1.6 KiB
Python
48 lines
1.6 KiB
Python
"""Integration tests for multi-user BasicAuth pass-through mode.
|
|
|
|
Tests that BasicAuth credentials are extracted from request headers
|
|
and passed through to Nextcloud APIs without storage (stateless).
|
|
"""
|
|
|
|
import pytest
|
|
|
|
|
|
@pytest.mark.integration
|
|
async def test_basic_auth_pass_through_notes_list(nc_mcp_basic_auth_client):
|
|
"""Test BasicAuth pass-through with notes list tool."""
|
|
# Call tool - BasicAuth header is set at connection level by fixture
|
|
response = await nc_mcp_basic_auth_client.call_tool("nc_notes_list", {})
|
|
|
|
# Verify tool executed successfully with pass-through auth
|
|
assert response is not None
|
|
assert "results" in response or "content" in response
|
|
|
|
|
|
@pytest.mark.integration
|
|
async def test_basic_auth_pass_through_notes_create(nc_mcp_basic_auth_client):
|
|
"""Test BasicAuth pass-through with notes create tool."""
|
|
# Create a note using BasicAuth
|
|
response = await nc_mcp_basic_auth_client.call_tool(
|
|
"nc_notes_create",
|
|
{
|
|
"title": "BasicAuth Test Note",
|
|
"content": "This note was created via BasicAuth pass-through",
|
|
"category": "Test",
|
|
},
|
|
)
|
|
|
|
assert response is not None
|
|
assert response.get("success") is True or "note_id" in response
|
|
|
|
|
|
@pytest.mark.integration
|
|
async def test_basic_auth_pass_through_search(nc_mcp_basic_auth_client):
|
|
"""Test BasicAuth pass-through with search tool."""
|
|
# Search notes using BasicAuth
|
|
response = await nc_mcp_basic_auth_client.call_tool(
|
|
"nc_notes_search", {"query": "BasicAuth"}
|
|
)
|
|
|
|
assert response is not None
|
|
assert "results" in response or "content" in response
|