refactor(api): split management.py into domain-focused modules

Split the monolithic management.py (1988 lines) into 4 focused modules:
- management.py: Server status, user sessions, shared helpers (~520 lines)
- passwords.py: App password provisioning for BasicAuth mode (~300 lines)
- webhooks.py: Webhook registration management (~290 lines)
- visualization.py: Search and PDF preview endpoints (~810 lines)

Backward compatibility maintained via __init__.py re-exports.
Updated test imports to use new module paths.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-01-26 21:28:18 +01:00
co-authored by Claude Opus 4.5
parent 61ce873411
commit 2e7774654b
8 changed files with 1674 additions and 1522 deletions
@@ -16,7 +16,7 @@ from starlette.applications import Starlette
from starlette.routing import Route
from starlette.testclient import TestClient
from nextcloud_mcp_server.api.management import get_pdf_preview
from nextcloud_mcp_server.api.visualization import get_pdf_preview
pytestmark = pytest.mark.unit
@@ -68,12 +68,12 @@ class TestPdfPreviewParameterValidation:
"""Test that missing file_path parameter returns 400."""
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
):
@@ -93,12 +93,12 @@ class TestPdfPreviewParameterValidation:
"""Test that invalid page number (0 or negative) returns 400."""
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
):
@@ -126,12 +126,12 @@ class TestPdfPreviewParameterValidation:
"""Test that scale outside valid range returns 400."""
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
):
@@ -159,12 +159,12 @@ class TestPdfPreviewParameterValidation:
"""Test that non-numeric page parameter returns 400."""
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
):
@@ -186,7 +186,7 @@ class TestPdfPreviewAuthentication:
def test_unauthorized_without_token_returns_401(self):
"""Test that request without token returns 401."""
with patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
side_effect=Exception("Invalid token"),
):
@@ -201,7 +201,7 @@ class TestPdfPreviewAuthentication:
def test_unauthorized_with_invalid_token_returns_401(self):
"""Test that request with invalid token returns 401."""
with patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
side_effect=Exception("Token expired"),
):
@@ -235,12 +235,12 @@ class TestPdfPreviewRendering:
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
patch(
@@ -284,12 +284,12 @@ class TestPdfPreviewRendering:
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
patch(
@@ -324,12 +324,12 @@ class TestPdfPreviewRendering:
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
patch(
@@ -363,12 +363,12 @@ class TestPdfPreviewRendering:
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
patch(
@@ -407,12 +407,12 @@ class TestPdfPreviewEdgeCases:
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
patch(
@@ -438,12 +438,12 @@ class TestPdfPreviewEdgeCases:
"""Test handling when Nextcloud host is not configured."""
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
):
@@ -476,12 +476,12 @@ class TestPdfPreviewEdgeCases:
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
patch(
@@ -518,12 +518,12 @@ class TestPdfPreviewEdgeCases:
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
patch(
@@ -556,12 +556,12 @@ class TestPdfPreviewSecurityValidation:
"""Test that path traversal attempts are blocked with 400."""
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
):
@@ -605,12 +605,12 @@ class TestPdfPreviewSecurityValidation:
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
patch(
@@ -647,12 +647,12 @@ class TestPdfPreviewSecurityValidation:
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
patch(
@@ -691,12 +691,12 @@ class TestPdfPreviewSecurityValidation:
with (
patch(
"nextcloud_mcp_server.api.management.validate_token_and_get_user",
"nextcloud_mcp_server.api.visualization.validate_token_and_get_user",
new_callable=AsyncMock,
return_value=("testuser", True),
),
patch(
"nextcloud_mcp_server.api.management.extract_bearer_token",
"nextcloud_mcp_server.api.visualization.extract_bearer_token",
return_value="test-token",
),
patch(