Files

7.4 KiB

phase, plan, subsystem, tags, dependency_graph, tech_stack, key_files, decisions, metrics
phase plan subsystem tags dependency_graph tech_stack key_files decisions metrics
05-cloud-storage-backends 10 cloud-storage
oauth
ui
webdav
nextcloud
gap-closure
requires provides affects
05-05
05-06
05-07
05-08
05-09
oauth-json-initiate
nextcloud-edit-round-trip
error-state-edit
confirm-overflow-fix
frontend/src/components/settings/SettingsCloudTab.vue
frontend/src/components/cloud/CloudCredentialModal.vue
backend/api/cloud.py
added patterns
fetch-with-bearer-for-oauth
non-secret-config-endpoint
vue-watch-edit-pre-population
created modified
backend/api/cloud.py
backend/tests/test_cloud.py
frontend/src/api/client.js
frontend/src/components/settings/SettingsCloudTab.vue
frontend/src/components/cloud/CloudCredentialModal.vue
frontend/src/components/ui/ConfirmBlock.vue
Added GET /api/cloud/connections/{id}/config to expose non-secret WebDAV connection fields (server_url, connection_username) for the edit modal — password never included
CloudCredentialModal rewritten with full edit-mode support: existing prop, getConnectionConfig() call, showAdvanced/customEndpoint for Nextcloud custom paths
Updated test_connect_google_drive to expect 200 JSON (was 302 redirect) — regression fix following oauth_initiate behavior change
duration completed tasks_completed files_modified
~20 minutes 2026-05-30T09:30:26Z 2 6

Phase 05 Plan 10: Cloud UI Gap Closure — OAuth Initiate + Edit Fixes Summary

Fixed four cloud settings UI gaps: OAuth initiate 401, Nextcloud custom endpoint lost on edit, missing Edit button on ERROR rows, and confirmation text overflow.

Tasks Completed

Task Description Commit Files
1 Fix OAuth initiate: return 200 JSON {url} instead of 302 redirect e2e499b backend/api/cloud.py, backend/tests/test_cloud.py
RED Failing tests for OAuth initiate JSON return 9b6d3f9 backend/tests/test_cloud.py
2 Frontend OAuth fetch, Nextcloud edit fix, Edit on ERROR, text overflow 87de148 5 frontend/backend files

What Was Built

Backend changes:

  • GET /api/cloud/oauth/initiate/{provider} now returns 200 JSON {"url": authorization_url} instead of 302 RedirectResponse. The Bearer-authenticated frontend can now read the URL and navigate with window.location.href = data.url — closing the 401 gap caused by the browser not sending auth headers on bare navigation.
  • GET /api/cloud/connections/{connection_id}/config — new endpoint returning non-secret WebDAV/Nextcloud connection fields (server_url, connection_username, never the password) for the edit modal pre-population flow.

Frontend changes:

  • client.js: Added initiateOAuth(provider) using request() (injects Bearer header, handles 401 → refresh). Added getConnectionConfig(connectionId) for edit modal.
  • SettingsCloudTab.vue: handleConnect for OAuth providers now uses await initiateOAuth() + window.location.href = data.url with error display. Added handleEdit() function. Added Edit buttons to ACTIVE and ERROR blocks (non-OAuth providers only). Wrapped all ConfirmBlock instances in div.w-full.overflow-hidden.
  • CloudCredentialModal.vue: Full rewrite with edit-mode support — existing prop, getConnectionConfig() call on open, serverBase/username/showAdvanced/customEndpoint refs, computed autoServerUrl/resolvedServerUrl. Nextcloud watch handler detects when stored server_url differs from auto-constructed URL and opens Advanced section with the custom endpoint pre-filled.
  • ConfirmBlock.vue: Added break-words class to message paragraph.

Test Results

All 25 tests in test_cloud.py pass:

  • 2 new tests: test_oauth_initiate_returns_json_url, test_oauth_initiate_requires_auth
  • test_connect_google_drive updated to expect 200 JSON (was 302 — stale after behavioral change)
  • Frontend build: zero errors (1 pre-existing dynamic import warning)

Deviations from Plan

Auto-added Missing Critical Functionality

1. [Rule 2 - Missing] Added GET /api/cloud/connections/{id}/config backend endpoint

  • Found during: Task 2 — CloudCredentialModal needs existing server_url to pre-populate edit form
  • Issue: The plan described existing.server_url and existing.connection_username as available from the existing prop passed from SettingsCloudTab, but CloudConnectionOut (the whitelist model) only exposes id, provider, display_name, status, connected_at — no decrypted credential fields
  • Fix: Added a dedicated /config endpoint that decrypts just the non-secret fields (server_url, username — never password). Added getConnectionConfig() to client.js. Modal calls this endpoint when existing prop is set.
  • Files modified: backend/api/cloud.py, frontend/src/api/client.js

2. [Rule 1 - Bug] Updated test_connect_google_drive to expect 200 JSON

  • Found during: Task 1 implementation — existing test expected 302 redirect, which is now 200 JSON
  • Fix: Updated test to mock Flow.from_client_config and assert resp.status_code == 200 + data["url"] starts with Google domain
  • Files modified: backend/tests/test_cloud.py

3. [Rule 2 - Missing] Added Edit button to ACTIVE block as well

  • Found during: Task 2 — Plan said "mirror the ACTIVE block" for ERROR, but ACTIVE block had no Edit button
  • Fix: Added Edit button to both ACTIVE and ERROR blocks for non-OAuth providers (Nextcloud/WebDAV)
  • Files modified: frontend/src/components/settings/SettingsCloudTab.vue

4. [Rule 2 - Missing] Rewrote CloudCredentialModal with full edit-mode support

  • Found during: Task 2 — Plan described fixing a watch handler with specific logic (serverBase, customEndpoint, showAdvanced) that didn't exist yet in the modal
  • Fix: Added all missing reactive state, the advanced section UI, and the full watch handler with Nextcloud custom endpoint detection
  • Files modified: frontend/src/components/cloud/CloudCredentialModal.vue

Known Stubs

None — all functionality is fully wired. The edit modal requires the user to re-enter their password (backend connect_webdav always requires password for health-check). A future enhancement could add a PATCH endpoint that accepts partial credential updates (password optional on edit).

Threat Flags

Flag File Description
threat_flag: new-endpoint backend/api/cloud.py GET /api/cloud/connections/{id}/config — new endpoint decrypting partial credentials. Mitigations: get_regular_user enforced, 404 on wrong-owner (ID enumeration prevention), password field excluded, only applicable to VALID_WEBDAV_PROVIDERS

Self-Check: PASSED

Check Result
backend/api/cloud.py exists FOUND
backend/tests/test_cloud.py exists FOUND
frontend/src/api/client.js exists FOUND
SettingsCloudTab.vue exists FOUND
CloudCredentialModal.vue exists FOUND
ConfirmBlock.vue exists FOUND
05-10-SUMMARY.md exists FOUND
Commit 9b6d3f9 (RED tests) FOUND
Commit e2e499b (GREEN implementation) FOUND
Commit 87de148 (Task 2 frontend) FOUND
JSONResponse in cloud.py FOUND
initiateOAuth in client.js FOUND
handleEdit in SettingsCloudTab.vue FOUND
break-words in ConfirmBlock.vue FOUND
existing prop in CloudCredentialModal.vue FOUND
All 25 tests pass PASSED
Frontend build ZERO ERRORS