refactor(config)!: drop ENABLE_MULTI_USER_BASIC_AUTH env var, fail loud on legacy aliases
Same pattern as the ENABLE_LOGIN_FLOW removal in the previous commit:
the deployment mode (MCP_DEPLOYMENT_MODE) is the single source of truth
for selecting an auth flow. The ENABLE_MULTI_USER_BASIC_AUTH env-var
alias is redundant with `MCP_DEPLOYMENT_MODE=multi_user_basic`.
Unlike the ENABLE_LOGIN_FLOW removal — where silent removal was safe
because Login Flow v2 is the auto-detection default — silent removal
here would be a surprise: a user with only ENABLE_MULTI_USER_BASIC_AUTH=true
in their .env would auto-detect into LOGIN_FLOW after upgrade (wrong
runtime mode). Mitigation: detect_auth_mode now reads os.environ
directly for both legacy aliases and raises ValueError with a one-line
migration message if either is set. Applied retroactively to
ENABLE_LOGIN_FLOW as well — loud is better than silent.
- nextcloud_mcp_server/config.py:
- Drop the dynaconf env-var alias entry for ENABLE_MULTI_USER_BASIC_AUTH.
- Update the `enable_multi_user_basic_auth` field docstring to mark it
as derived / not user-settable.
- `_is_multi_user_mode()` (early-config helper, runs before Settings
is built) switched to checking MCP_DEPLOYMENT_MODE directly. Now
consistent with the canonical detection in detect_auth_mode.
- nextcloud_mcp_server/config_validators.py:
- Drop the auto-detection branch (`if settings.enable_multi_user_basic_auth`).
Selection of MULTI_USER_BASIC is now exclusively via the explicit
MCP_DEPLOYMENT_MODE branch.
- Add `enable_multi_user_basic_auth` to `_sync_derived_flags` alongside
`enable_login_flow` — both flags are now derived from the resolved mode.
- Drop `enable_multi_user_basic_auth` from
`MODE_REQUIREMENTS[MULTI_USER_BASIC].required` and from the
`forbidden` lists of SINGLE_USER_BASIC and LOGIN_FLOW (no longer
user input → no meaningful forbidden check).
- Add loud-deprecation `ValueError` block at the top of detect_auth_mode
that errors with a clear migration message when ENABLE_MULTI_USER_BASIC_AUTH
or ENABLE_LOGIN_FLOW is found in os.environ.
- tests/unit/test_config_validators.py:
- Switch ~10 fixtures from `enable_multi_user_basic_auth=True` to
`deployment_mode="multi_user_basic"` (mirrors `enable_login_flow`
treatment from the previous commit).
- Switch two `patch.dict(os.environ, {"ENABLE_MULTI_USER_BASIC_AUTH": "true"})`
blocks to use MCP_DEPLOYMENT_MODE.
- Rename `test_forbidden_multi_user_basic_auth` to
`test_forbidden_multi_user_basic_when_credentials_present` — the
scenario is now an explicit-mode + credentials conflict, not an
env-var-flag conflict.
- Add `test_legacy_enable_multi_user_basic_auth_env_var_errors` and
`test_legacy_enable_login_flow_env_var_errors` to exercise the new
loud-deprecation ValueError path.
- docker-compose.yml: mcp-multi-user-basic profile switched to
`MCP_DEPLOYMENT_MODE=multi_user_basic`.
- env.sample: replaced `#ENABLE_MULTI_USER_BASIC_AUTH=true` example with
`#MCP_DEPLOYMENT_MODE=multi_user_basic`.
- docs/authentication.md, configuration.md, troubleshooting.md,
auth-flows.md, webhook-management-guide.md,
configuration-migration-v2.md, ADR-025: replaced env-var examples
with the canonical MCP_DEPLOYMENT_MODE form.
- docs/ADR-020: marked partly superseded by ADR-022.
- CLAUDE.md: Multi-User BasicAuth section updated to set
MCP_DEPLOYMENT_MODE.
- nextcloud_mcp_server/vector/oauth_sync.py: module docstring updated.
BREAKING CHANGE: ENABLE_MULTI_USER_BASIC_AUTH is no longer read from
the environment, and setting it now raises a startup ValueError with
a migration message. Replace `ENABLE_MULTI_USER_BASIC_AUTH=true` with
`MCP_DEPLOYMENT_MODE=multi_user_basic`. The same loud-deprecation
check is also applied to the recently-removed ENABLE_LOGIN_FLOW —
replace with `MCP_DEPLOYMENT_MODE=login_flow` (or drop both;
`login_flow` is the auto-detect default when no other auth env vars
are set).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
df4994e860
commit
282c245da1
@@ -9,6 +9,7 @@ See ADR-020 for detailed architecture and deployment mode documentation.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
|
||||
@@ -64,7 +65,6 @@ MODE_REQUIREMENTS: dict[AuthMode, ModeRequirements] = {
|
||||
"document_chunk_overlap",
|
||||
],
|
||||
forbidden=[
|
||||
"enable_multi_user_basic_auth",
|
||||
"oidc_client_id",
|
||||
"oidc_client_secret",
|
||||
],
|
||||
@@ -78,7 +78,7 @@ MODE_REQUIREMENTS: dict[AuthMode, ModeRequirements] = {
|
||||
"Suitable for personal Nextcloud instances and local development.",
|
||||
),
|
||||
AuthMode.MULTI_USER_BASIC: ModeRequirements(
|
||||
required=["nextcloud_host", "enable_multi_user_basic_auth"],
|
||||
required=["nextcloud_host"],
|
||||
optional=[
|
||||
# Background sync with app passwords (via Astrolabe)
|
||||
"enable_offline_access",
|
||||
@@ -138,7 +138,6 @@ MODE_REQUIREMENTS: dict[AuthMode, ModeRequirements] = {
|
||||
forbidden=[
|
||||
"nextcloud_username",
|
||||
"nextcloud_password",
|
||||
"enable_multi_user_basic_auth",
|
||||
],
|
||||
conditional={
|
||||
"enable_offline_access": [
|
||||
@@ -181,6 +180,21 @@ def detect_auth_mode(settings: Settings) -> AuthMode:
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# ADR-022 follow-up: fail loudly if a caller is still relying on the
|
||||
# removed env-var aliases. Bypass dynaconf and read os.environ directly
|
||||
# so the check survives even though the aliases are gone.
|
||||
for legacy, replacement in (
|
||||
("ENABLE_MULTI_USER_BASIC_AUTH", "multi_user_basic"),
|
||||
("ENABLE_LOGIN_FLOW", "login_flow"),
|
||||
):
|
||||
if os.getenv(legacy):
|
||||
raise ValueError(
|
||||
f"{legacy} is no longer read from the environment. "
|
||||
f"Set MCP_DEPLOYMENT_MODE={replacement} instead "
|
||||
"(ADR-022). The deployment mode is the single source of "
|
||||
"truth for selecting an auth flow."
|
||||
)
|
||||
|
||||
# ADR-021: Check for explicit deployment mode first
|
||||
if settings.deployment_mode:
|
||||
mode_str = settings.deployment_mode.lower().strip()
|
||||
@@ -204,11 +218,11 @@ def detect_auth_mode(settings: Settings) -> AuthMode:
|
||||
_sync_derived_flags(settings, explicit_mode)
|
||||
return explicit_mode
|
||||
|
||||
# Auto-detection (existing behavior)
|
||||
# Check for multi-user BasicAuth
|
||||
if settings.enable_multi_user_basic_auth:
|
||||
_sync_derived_flags(settings, AuthMode.MULTI_USER_BASIC)
|
||||
return AuthMode.MULTI_USER_BASIC
|
||||
# Auto-detection (no explicit deployment_mode).
|
||||
# MULTI_USER_BASIC is no longer auto-detectable — the ENABLE_MULTI_USER_BASIC_AUTH
|
||||
# env-var alias was dropped in the ADR-022 follow-up, so the only way to
|
||||
# opt into that mode is `MCP_DEPLOYMENT_MODE=multi_user_basic` (handled
|
||||
# above). The legacy env var fails loudly at the top of this function.
|
||||
|
||||
# Check for single-user BasicAuth (explicit credentials)
|
||||
if settings.nextcloud_username and settings.nextcloud_password:
|
||||
@@ -228,13 +242,12 @@ def _sync_derived_flags(settings: Settings, mode: AuthMode) -> None:
|
||||
Some runtime call sites (app.py, context.py, auth/scope_authorization.py)
|
||||
still read individual boolean flags rather than passing the mode around.
|
||||
Keep those flags in sync with the mode here so the mode is the single
|
||||
source of truth and users don't have to set redundant env vars.
|
||||
|
||||
Specifically: `enable_login_flow` is now derived from
|
||||
`mode == AuthMode.LOGIN_FLOW`. The ENABLE_LOGIN_FLOW env-var alias was
|
||||
source of truth and users don't have to set redundant env vars. The
|
||||
ENABLE_LOGIN_FLOW and ENABLE_MULTI_USER_BASIC_AUTH env-var aliases were
|
||||
removed in the ADR-022 follow-up (PR #787).
|
||||
"""
|
||||
settings.enable_login_flow = mode == AuthMode.LOGIN_FLOW
|
||||
settings.enable_multi_user_basic_auth = mode == AuthMode.MULTI_USER_BASIC
|
||||
|
||||
|
||||
def validate_configuration(settings: Settings) -> tuple[AuthMode, list[str]]:
|
||||
|
||||
Reference in New Issue
Block a user