4 Commits
Author SHA1 Message Date
Chris CoutinhoandClaude Opus 4.7 65345fd6eb refactor: drop OAuth-refresh background-sync path from oauth_sync.py
Follow-up to #787/#789 (ADR-022 cleanup). After
`oauth_enabled ↔ enable_login_flow` became an invariant, the
`use_basic_auth=False` branch in `vector/oauth_sync.py` — and the
parameter wiring that fed it — was no longer reachable from any
supported deployment mode. This commit removes the dead code.

- nextcloud_mcp_server/vector/oauth_sync.py:
  - Deleted `get_user_client_oauth` (the OAuth-token refresh helper) and
    its `VECTOR_SYNC_SCOPES` constant.
  - Deleted the `get_user_client` dispatcher. Internal callers now call
    `get_user_client_basic_auth` directly.
  - Dropped the `use_basic_auth: bool` parameter from `user_scanner_task`,
    `multi_user_processor_task`, `_run_user_scanner_with_scope`, and
    `user_manager_task`.
  - Dropped the `token_broker` parameter from the same four functions —
    they no longer need it now that the OAuth-refresh path is gone. The
    `TokenBrokerService` constructed in `app.py` is still used by the
    management API revoke endpoint, just not by background sync.
  - Simplified the user-list query in `user_manager_task` to always read
    from the `app_passwords` table.
  - Replaced all `mode_label = "BasicAuth" if use_basic_auth else "OAuth"`
    with a literal `[BasicAuth]` log prefix (keeps existing log filters
    working).
  - Updated the module docstring to describe the post-cleanup shape.
  - Dropped the now-unused `TYPE_CHECKING` import of `TokenBrokerService`.

- nextcloud_mcp_server/app.py: dropped the `use_basic_auth = True` block
  and the now-stale `token_broker if not use_basic_auth else None` /
  `use_basic_auth` positional args from the two `tg.start(...)` calls in
  the multi-user vector-sync lifespan. Token broker construction stays —
  still consumed by the management API revoke endpoint via
  `app.state.oauth_context["token_broker"]`.

- tests/integration/test_app_password_provisioning.py: deleted four tests
  that exercised the now-removed OAuth-refresh path
  (`test_oauth_mode_uses_refresh_token_only`,
  `test_oauth_mode_raises_error_without_token`,
  `test_get_user_client_oauth_function`,
  `test_oauth_mode_requires_token_broker`) plus the
  `test_get_user_client_dispatches_to_basic_auth` test for the deleted
  dispatcher. Updated the module docstring + imports accordingly. The
  BasicAuth-mode tests (`test_basic_auth_mode_uses_local_storage`,
  `test_multiple_users_basic_auth_mode`, etc.) all remain.

No runtime-behaviour change in any supported deployment mode — the deleted
branches were already unreachable post-PR #787. 3 files changed,
+59 / -301; 1010 unit tests pass; integration jobs for
`mcp-login-flow` and `mcp-multi-user-basic` are the critical regression
gates before merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 01:13:53 +02:00
Chris CoutinhoandClaude Opus 4.5 370c3ff444 test: Add comprehensive tests for app password storage and provisioning
- Add 12 unit tests for RefreshTokenStorage app password methods
  - Basic CRUD operations (store, get, delete)
  - Encryption verification (passwords encrypted at rest)
  - Error handling (missing encryption key, wrong key)
  - Multi-user independence

- Add 13 unit tests for Management API endpoints
  - POST /api/v1/users/{user_id}/app-password provisioning
  - GET /api/v1/users/{user_id}/app-password status
  - DELETE /api/v1/users/{user_id}/app-password deletion
  - Auth validation (BasicAuth, username matching)
  - Nextcloud credential validation

- Rewrite 10 integration tests for new architecture
  - Remove AstrolabeClient/OAuth dependency
  - Use local RefreshTokenStorage for app passwords
  - Test BasicAuth and OAuth mode separation
  - Test NotProvisionedError scenarios

Addresses reviewer feedback on PR #473 requiring test coverage.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 21:44:23 +01:00
Chris CoutinhoandClaude Opus 4.5 894bf5f916 refactor(auth): Decouple BasicAuth and OAuth authentication strategies
Completely separates multi-user BasicAuth mode from OAuth mode with no
fallback between them. These are now mutually exclusive authentication
strategies based on deployment configuration.

Changes:
- Create separate functions: get_user_client_basic_auth() and
  get_user_client_oauth() with clear separation of concerns
- Update get_user_client() to dispatch based on use_basic_auth parameter
- Pass use_basic_auth through all background sync tasks
- Update app.py to determine auth mode at startup
- Rewrite integration tests to verify no OAuth fallback in BasicAuth mode
- Fix test assertions for response field names and duplicate title handling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 08:27:15 -06:00
Chris CoutinhoandClaude Sonnet 4.5 286a3eb20f feat(auth): add multi-user BasicAuth pass-through mode
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>
2025-12-20 20:55:31 +01:00