fix: address PR #589 review feedback for Login Flow v2
- Fix data loss in nc_auth_update_scopes: remove premature delete_app_password call; old password stays valid until upsert replaces it on successful re-provisioning - Replace assert with proper error return in nc_auth_check_status - Add lazy singleton for RefreshTokenStorage in auth_tools, scope_authorization, and context to avoid per-call re-initialization - Centralize _is_login_flow_mode() to get_settings().enable_login_flow and remove duplicate definitions and per-call os.getenv reads - Add dev-only comment to TOKEN_ENCRYPTION_KEY in docker-compose.yml - Gate OIDC build steps in CI behind matrix.needs-playwright - Add diagnostic step reporting Playwright skip count in CI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
"""Helper functions for accessing context in MCP tools."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
from httpx import BasicAuth
|
||||
from mcp.server.fastmcp import Context
|
||||
@@ -11,6 +10,7 @@ from nextcloud_mcp_server.auth.context_helper import (
|
||||
get_session_client_from_context,
|
||||
)
|
||||
from nextcloud_mcp_server.auth.scope_authorization import ProvisioningRequiredError
|
||||
from nextcloud_mcp_server.auth.storage import RefreshTokenStorage
|
||||
from nextcloud_mcp_server.client import NextcloudClient
|
||||
from nextcloud_mcp_server.config import (
|
||||
DeploymentMode,
|
||||
@@ -82,7 +82,7 @@ async def get_client(ctx: Context) -> NextcloudClient:
|
||||
|
||||
# Login Flow v2 multi-user mode: app password is REQUIRED for NC API access
|
||||
# OAuth token is only used for MCP session identity, not NC API calls
|
||||
if hasattr(lifespan_ctx, "nextcloud_host") and _is_login_flow_mode():
|
||||
if hasattr(lifespan_ctx, "nextcloud_host") and settings.enable_login_flow:
|
||||
return await _get_client_from_login_flow(ctx, lifespan_ctx.nextcloud_host)
|
||||
|
||||
# BasicAuth mode - use shared client (no token exchange)
|
||||
@@ -254,9 +254,16 @@ def _get_client_from_basic_auth(ctx: Context) -> NextcloudClient:
|
||||
)
|
||||
|
||||
|
||||
def _is_login_flow_mode() -> bool:
|
||||
"""Check if Login Flow v2 multi-user mode is active."""
|
||||
return os.getenv("ENABLE_LOGIN_FLOW", "false").lower() == "true"
|
||||
_login_flow_storage_instance = None
|
||||
|
||||
|
||||
async def _get_login_flow_storage():
|
||||
"""Get initialized storage instance for login flow (lazy singleton)."""
|
||||
global _login_flow_storage_instance
|
||||
if _login_flow_storage_instance is None:
|
||||
_login_flow_storage_instance = RefreshTokenStorage.from_env()
|
||||
await _login_flow_storage_instance.initialize()
|
||||
return _login_flow_storage_instance
|
||||
|
||||
|
||||
async def _get_client_from_login_flow(
|
||||
@@ -277,7 +284,6 @@ async def _get_client_from_login_flow(
|
||||
Raises:
|
||||
ProvisioningRequiredError: If no stored app password exists
|
||||
"""
|
||||
from nextcloud_mcp_server.auth.storage import RefreshTokenStorage # noqa: PLC0415
|
||||
from nextcloud_mcp_server.server.oauth_tools import ( # noqa: PLC0415
|
||||
extract_user_id_from_token,
|
||||
)
|
||||
@@ -288,8 +294,7 @@ async def _get_client_from_login_flow(
|
||||
"Cannot determine user identity from MCP token."
|
||||
)
|
||||
|
||||
storage = RefreshTokenStorage.from_env()
|
||||
await storage.initialize()
|
||||
storage = await _get_login_flow_storage()
|
||||
|
||||
app_data = await storage.get_app_password_with_scopes(user_id)
|
||||
if not app_data:
|
||||
|
||||
Reference in New Issue
Block a user