From 23c8c76b392a95e723f25f8cb3714d4e5f256b30 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 13:17:40 +0000 Subject: [PATCH] feat(auth): default to system-wide app credentials in OAuth wizards for user mode When system-wide Dropbox, Google Drive, or OneDrive app credentials are configured by the admin, user-mode OAuth wizards now default to using them. A toggle lets users switch to custom credentials if needed. This removes the need for end users to register their own cloud provider apps. Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> --- app/views/dropbox.py | 9 +++- app/views/google_drive.py | 21 +++++++-- app/views/onedrive.py | 17 ++++--- frontend/templates/dropbox.html | 54 ++++++++++++++++++---- frontend/templates/google_drive.html | 54 ++++++++++++++++++---- frontend/templates/onedrive.html | 67 ++++++++++++++++++++++------ 6 files changed, 181 insertions(+), 41 deletions(-) diff --git a/app/views/dropbox.py b/app/views/dropbox.py index f623a7c6..8f304784 100644 --- a/app/views/dropbox.py +++ b/app/views/dropbox.py @@ -46,6 +46,9 @@ async def dropbox_setup_page( cfg = {} # Support both "folder" (DROPBOX destination) and "folder_path" (WATCH_FOLDER source) folder_path = cfg.get("folder", cfg.get("folder_path", "")) + # Provide system-wide app credentials when available so users can + # authorize without creating their own Dropbox app. + has_system_credentials = bool(settings.dropbox_app_key and settings.dropbox_app_secret) return templates.TemplateResponse( "dropbox.html", { @@ -56,8 +59,9 @@ async def dropbox_setup_page( "integration_name": integration.name, "integration_type": integration.integration_type, "folder_path": folder_path, - "app_key_value": "", - "app_secret_value": "", + "has_system_credentials": has_system_credentials, + "app_key_value": settings.dropbox_app_key or "" if has_system_credentials else "", + "app_secret_value": settings.dropbox_app_secret or "" if has_system_credentials else "", "refresh_token_value": "", }, ) @@ -71,6 +75,7 @@ async def dropbox_setup_page( "request": request, "user_mode": False, "is_configured": is_configured, + "has_system_credentials": bool(settings.dropbox_app_key and settings.dropbox_app_secret), "app_key_value": settings.dropbox_app_key or "", "app_secret_value": settings.dropbox_app_secret if settings.dropbox_app_secret else "", "refresh_token_value": settings.dropbox_refresh_token if settings.dropbox_refresh_token else "", diff --git a/app/views/google_drive.py b/app/views/google_drive.py index f6bde9c0..20b38366 100644 --- a/app/views/google_drive.py +++ b/app/views/google_drive.py @@ -45,6 +45,11 @@ async def google_drive_setup_page( except (json.JSONDecodeError, TypeError): cfg = {} folder_id = cfg.get("folder_id", "") + # Provide system-wide OAuth credentials when available so users can + # authorize without registering their own Google Cloud app. + has_system_credentials = bool( + settings.google_drive_client_id and settings.google_drive_client_secret + ) return templates.TemplateResponse( "google_drive.html", { @@ -58,10 +63,15 @@ async def google_drive_setup_page( "use_oauth": True, "oauth_configured": bool(integration.credentials), "sa_configured": False, - "client_id": False, - "client_id_value": "", - "client_secret": False, - "client_secret_value": "", + "has_system_credentials": has_system_credentials, + "client_id": bool(settings.google_drive_client_id) if has_system_credentials else False, + "client_id_value": ( + settings.google_drive_client_id or "" if has_system_credentials else "" + ), + "client_secret": bool(settings.google_drive_client_secret) if has_system_credentials else False, + "client_secret_value": ( + settings.google_drive_client_secret or "" if has_system_credentials else "" + ), "refresh_token": False, "refresh_token_value": "", "has_credentials_json": False, @@ -90,6 +100,9 @@ async def google_drive_setup_page( "use_oauth": use_oauth, "oauth_configured": oauth_configured, "sa_configured": sa_configured, + "has_system_credentials": bool( + settings.google_drive_client_id and settings.google_drive_client_secret + ), "client_id": bool(settings.google_drive_client_id), "client_id_value": settings.google_drive_client_id or "", "client_secret": bool(settings.google_drive_client_secret), diff --git a/app/views/onedrive.py b/app/views/onedrive.py index 4b8b3763..18e823f5 100644 --- a/app/views/onedrive.py +++ b/app/views/onedrive.py @@ -44,6 +44,9 @@ async def onedrive_setup_page( cfg = {} # Support both "folder_path" (WATCH_FOLDER / ONEDRIVE destination) folder_path = cfg.get("folder_path", cfg.get("folder", "")) + # Provide system-wide app credentials when available so users can + # authorize without registering their own Azure/OneDrive app. + has_system_credentials = bool(settings.onedrive_client_id and settings.onedrive_client_secret) return templates.TemplateResponse( "onedrive.html", { @@ -54,11 +57,14 @@ async def onedrive_setup_page( "integration_name": integration.name, "integration_type": integration.integration_type, "folder_path": folder_path, - "client_id": False, - "client_id_value": "", - "client_secret": False, - "client_secret_value": "", - "tenant_id": "common", + "has_system_credentials": has_system_credentials, + "client_id": bool(settings.onedrive_client_id) if has_system_credentials else False, + "client_id_value": settings.onedrive_client_id or "" if has_system_credentials else "", + "client_secret": bool(settings.onedrive_client_secret) if has_system_credentials else False, + "client_secret_value": ( + settings.onedrive_client_secret or "" if has_system_credentials else "" + ), + "tenant_id": settings.onedrive_tenant_id or "common", "refresh_token": False, "refresh_token_value": "", }, @@ -75,6 +81,7 @@ async def onedrive_setup_page( "request": request, "user_mode": False, "is_configured": is_configured, + "has_system_credentials": bool(settings.onedrive_client_id and settings.onedrive_client_secret), "client_id": bool(settings.onedrive_client_id), "client_id_value": settings.onedrive_client_id or "", "client_secret": bool(settings.onedrive_client_secret), diff --git a/frontend/templates/dropbox.html b/frontend/templates/dropbox.html index a94a5b96..492598ba 100644 --- a/frontend/templates/dropbox.html +++ b/frontend/templates/dropbox.html @@ -116,14 +116,31 @@
-
- - + {% if user_mode and has_system_credentials %} + +
+
+ {% endif %} -
- - +
+
+
+ + +
+ +
+ + +
+
{% if not user_mode %} @@ -268,6 +285,9 @@ DROPBOX_FOLDER={{ folder_path|default('/Documents/Uploads', true) }} document.addEventListener('DOMContentLoaded', function() { const userMode = {{ 'true' if user_mode else 'false' }}; + const hasSystemCredentials = {{ 'true' if (user_mode and has_system_credentials) else 'false' }}; + const systemAppKey = {{ (app_key_value or '') | tojson }}; + const systemAppSecret = {{ (app_secret_value or '') | tojson }}; // Store integration_id if provided (for per-user OAuth flow) const integrationId = "{{ integration_id or '' }}"; @@ -281,6 +301,19 @@ document.addEventListener('DOMContentLoaded', function() { const refreshTokenBtn = document.getElementById('refresh-token-btn'); const tokenStatus = document.getElementById('token-status'); const appSecretInput = document.getElementById('app-secret'); + const useSystemCredsCheckbox = document.getElementById('use-system-creds'); + const customCredsSection = document.getElementById('custom-creds-section'); + + // Toggle custom credentials section visibility + if (useSystemCredsCheckbox && customCredsSection) { + useSystemCredsCheckbox.addEventListener('change', function() { + if (this.checked) { + customCredsSection.classList.add('hidden'); + } else { + customCredsSection.classList.remove('hidden'); + } + }); + } // Modal elements const resultModal = document.getElementById('resultModal'); @@ -330,8 +363,10 @@ document.addEventListener('DOMContentLoaded', function() { // Start Authentication Flow button click startAuthFlowBtn.addEventListener('click', function() { - const appKey = document.getElementById('app-key').value.trim(); - const appSecret = appSecretInput.value.trim(); + // Determine which credentials to use + const useSystemCreds = hasSystemCredentials && useSystemCredsCheckbox && useSystemCredsCheckbox.checked; + const appKey = useSystemCreds ? systemAppKey : document.getElementById('app-key').value.trim(); + const appSecret = useSystemCreds ? systemAppSecret : appSecretInput.value.trim(); const redirectUri = window.location.origin + "/dropbox-callback"; if (!appKey) { @@ -347,6 +382,9 @@ document.addEventListener('DOMContentLoaded', function() { // Save app key and app secret to session storage temporarily sessionStorage.setItem('dropbox_app_key', appKey); sessionStorage.setItem('dropbox_app_secret', appSecret); + if (useSystemCreds) { + sessionStorage.setItem('dropbox_use_system_creds', 'true'); + } // In admin mode also store folder path; in user mode the config is already set if (!userMode) { diff --git a/frontend/templates/google_drive.html b/frontend/templates/google_drive.html index 10a9aca9..43b46d73 100644 --- a/frontend/templates/google_drive.html +++ b/frontend/templates/google_drive.html @@ -167,14 +167,31 @@

Now enter your Client ID and Client Secret below, and we'll help you complete the OAuth flow. You can set the folder ID after authentication is complete.

-
- - + {% if user_mode and has_system_credentials %} + +
+
+ {% endif %} -
- - +
+
+
+ + +
+ +
+ + +
+
@@ -430,6 +447,9 @@ GOOGLE_DRIVE_FOLDER_ID={{ folder_id|default('YOUR_FOLDER_ID', true) }}