From 29cc00e2847ae507e12b7b8119302a1273984060 Mon Sep 17 00:00:00 2001 From: Stefan Hacker Date: Sat, 11 Apr 2026 23:58:54 +0200 Subject: [PATCH] fix: Client-Upload akzeptiert SECRET_KEY oder JWT_SECRET_KEY + Download in Settings Upload-Auth: - Akzeptiert jetzt sowohl SECRET_KEY als auch JWT_SECRET_KEY (BUILD_UPLOAD_TOKEN in Entwicklungs-.env kann einer von beiden sein) Settings-View: - Zeigt verfuegbare Desktop/Mobile Clients zum Download an (nur wenn mindestens ein Client vorhanden) - Pro Client: Name, Dateiname, Download-Button .env.example: - Klarere Kommentare: "SECRET_KEY oder JWT_SECRET_KEY des Zielservers" Co-Authored-By: Claude Opus 4.6 (1M context) --- .env.example | 11 ++++---- backend/app/api/client_downloads.py | 10 ++++--- frontend/src/views/SettingsView.vue | 41 ++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/.env.example b/.env.example index 9f3179f..0e1a5b9 100644 --- a/.env.example +++ b/.env.example @@ -37,11 +37,12 @@ MAX_UPLOAD_SIZE_MB=500 ONLYOFFICE_URL= # ============================================= -# Client-Build Upload (NUR auf der Entwicklungsmaschine!) -# Diese Werte gehoeren NICHT auf den Produktionsserver, -# sondern in die .env der Maschine auf der ./build.sh laeuft. +# Client-Build Upload (NUR auf der ENTWICKLUNGSMASCHINE!) +# NICHT auf dem Produktionsserver setzen! +# Diese Werte braucht nur die Maschine auf der ./build.sh laeuft. # ============================================= -# Oeffentliche URL der Cloud-Instanz wohin die Builds hochgeladen werden +# URL der Cloud-Instanz wohin die Builds hochgeladen werden CLOUD_URL=https://cloud.example.com -# SECRET_KEY des Zielservers (identisch mit SECRET_KEY oben auf dem Server) +# SECRET_KEY oder JWT_SECRET_KEY des Zielservers +# (den gleichen Wert hier reinkopieren der auf dem Server steht) BUILD_UPLOAD_TOKEN= diff --git a/backend/app/api/client_downloads.py b/backend/app/api/client_downloads.py index f000552..186de72 100644 --- a/backend/app/api/client_downloads.py +++ b/backend/app/api/client_downloads.py @@ -26,11 +26,13 @@ def _clients_dir(): def _verify_build_token(): """Verify the build upload token from header or query param.""" - expected = os.environ.get('SECRET_KEY', '') - if not expected: - return False token = request.headers.get('X-Build-Token', '') or request.args.get('build_token', '') - return token == expected + if not token: + return False + # Accept SECRET_KEY or JWT_SECRET_KEY + secret = os.environ.get('SECRET_KEY', '') + jwt_secret = os.environ.get('JWT_SECRET_KEY', '') + return token == secret or token == jwt_secret # --- Public: list available clients --- diff --git a/frontend/src/views/SettingsView.vue b/frontend/src/views/SettingsView.vue index e48ac5a..de91d38 100644 --- a/frontend/src/views/SettingsView.vue +++ b/frontend/src/views/SettingsView.vue @@ -45,6 +45,24 @@ + +
+

Desktop & Mobile Clients

+
+
+
+ +
+ {{ client.name }} + {{ client.filename }} +
+
+
+
+
+
@@ -167,6 +185,13 @@ import InputSwitch from 'primevue/inputswitch' const auth = useAuthStore() const toast = useToast() +// Client downloads +const availableClients = ref([]) + +function downloadClient(client) { + window.location.href = `/api/clients/${client.platform}/download` +} + // --- Password change --- const currentPassword = ref('') const newPassword = ref('') @@ -307,7 +332,13 @@ async function doDeleteAccount() { } } -onMounted(loadAccounts) +onMounted(async () => { + loadAccounts() + try { + const res = await apiClient.get('/clients') + availableClients.value = res.data.clients + } catch { availableClients.value = [] } +})