feat(05-10): OAuth fetch + Nextcloud edit fix + Edit on ERROR + text overflow

- client.js: add initiateOAuth() and getConnectionConfig() helpers
- SettingsCloudTab: replace window.location.href with initiateOAuth() + fetch/JWT
- SettingsCloudTab: add Edit button to ACTIVE and ERROR blocks for non-OAuth providers
- SettingsCloudTab: wrap ConfirmBlock in w-full overflow-hidden div
- CloudCredentialModal: add existing prop, edit-mode pre-population via /config endpoint
- CloudCredentialModal: add showAdvanced + customEndpoint for Nextcloud custom paths
- ConfirmBlock: add break-words class to message paragraph
- cloud.py: add GET /api/cloud/connections/{id}/config endpoint (non-secret fields)
This commit is contained in:
curo1305
2026-05-30 11:30:13 +02:00
parent e2e499b8b1
commit 87de148a59
5 changed files with 310 additions and 58 deletions
+51
View File
@@ -642,6 +642,57 @@ async def list_connections(
return {"items": [CloudConnectionOut.model_validate(c).model_dump() for c in connections]}
# ── GET /api/cloud/connections/{connection_id}/config ────────────────────────
@router.get("/connections/{connection_id}/config")
async def get_connection_config(
connection_id: uuid.UUID,
session: AsyncSession = Depends(get_db),
current_user: User = Depends(get_regular_user),
) -> dict:
"""Return non-secret configuration fields for a WebDAV/Nextcloud connection.
Returns server_url and connection_username (not password) so the frontend
can pre-populate the Edit modal without exposing credentials.
Only applicable to WebDAV / Nextcloud connections (not OAuth providers).
Returns 404 for wrong-owner or unknown connections (prevents ID enumeration).
Returns 400 for OAuth providers (no non-secret config to return).
Security:
- Only connection owned by current_user.id is returned (T-05-05-04)
- password is never included in the response (D-18)
- Returns 404 for wrong-owner connections (prevents ID enumeration)
"""
conn = await session.get(CloudConnection, connection_id)
if conn is None or conn.user_id != current_user.id:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Connection not found")
if conn.provider not in VALID_WEBDAV_PROVIDERS:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Connection config is only available for WebDAV/Nextcloud connections",
)
master_key = settings.cloud_creds_key.encode()
try:
credentials = decrypt_credentials(master_key, str(current_user.id), conn.credentials_enc)
except Exception:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="Failed to decrypt connection credentials",
)
# Return non-secret fields only — never expose the password
return {
"id": str(conn.id),
"provider": conn.provider,
"server_url": credentials.get("server_url", ""),
"connection_username": credentials.get("username", ""),
}
# ── DELETE /api/cloud/connections/{connection_id} ─────────────────────────────