Refactor backend and frontend cleanup paths

This commit is contained in:
curo1305
2026-06-16 11:50:17 +02:00
parent 6b56763689
commit e97ca164d7
29 changed files with 1106 additions and 2280 deletions
+33
View File
@@ -0,0 +1,33 @@
"""Factory for user-scoped cloud storage backends."""
def build_cloud_backend(provider: str, credentials: dict):
if provider == "google_drive":
from storage.google_drive_backend import GoogleDriveBackend # lazy import
return GoogleDriveBackend(credentials)
if provider == "onedrive":
from storage.onedrive_backend import OneDriveBackend # lazy import
return OneDriveBackend(credentials)
if provider == "nextcloud":
from storage.nextcloud_backend import NextcloudBackend # lazy import
return NextcloudBackend(
credentials["server_url"],
credentials["username"],
credentials["password"],
)
if provider == "webdav":
from storage.webdav_backend import WebDAVBackend # lazy import
return WebDAVBackend(
credentials["server_url"],
credentials["username"],
credentials["password"],
)
raise ValueError(f"Unknown provider: {provider}")
+1 -5
View File
@@ -6,12 +6,8 @@ class CloudConnectionError(Exception):
"""Raised when a cloud provider signals a non-retryable connection problem.
Attributes:
reason: "token_expired" — access token expired; API layer can refresh and retry.
reason: "token_expired" — access token expired.
"invalid_grant" — refresh token revoked; user must reconnect.
The backend never updates the DB. The API layer (_call_cloud_op in cloud.py)
catches this exception, performs the DB state transition, and decides whether
to retry or surface a 503 to the client (B2 design, D-05/D-06).
"""
def __init__(self, msg: str = "", *, reason: str = "") -> None:
+2 -4
View File
@@ -11,10 +11,8 @@ Design notes:
- D-14: presigned_get_url and generate_presigned_put_url raise
NotImplementedError. The API upload endpoint detects cloud backends and
uses the direct put_object() path instead.
- B2 design: This backend is STATELESS. It raises CloudConnectionError but
does NOT update the DB or CloudConnection objects. DB state transitions
(e.g., REQUIRES_REAUTH) are handled by the _call_cloud_op() helper in
cloud.py (Plan 05-05), which has the DB session.
- This backend is stateless. It raises CloudConnectionError but does not
update the DB or CloudConnection objects.
- Token key format stored in credentials dict:
access_token — current OAuth bearer token
refresh_token — long-lived refresh token
+2 -3
View File
@@ -10,9 +10,8 @@ Design notes:
already async and awaited directly.
- CloudConnectionError is imported from google_drive_backend (shared type).
This keeps the exception hierarchy unified across all cloud backends.
- B2 design: This backend is STATELESS. It raises CloudConnectionError but
does NOT update the DB or CloudConnection objects. DB state transitions
(e.g., REQUIRES_REAUTH) are handled by _call_cloud_op() in cloud.py.
- This backend is stateless. It raises CloudConnectionError but does not
update the DB or CloudConnection objects.
- _ensure_valid_token() checks expiry before each API call and calls
_refresh_token() if the token is within 60 seconds of expiry. If the
refresh returns None (invalid_grant), CloudConnectionError is raised.