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>
This commit is contained in:
@@ -46,6 +46,9 @@ async def dropbox_setup_page(
|
|||||||
cfg = {}
|
cfg = {}
|
||||||
# Support both "folder" (DROPBOX destination) and "folder_path" (WATCH_FOLDER source)
|
# Support both "folder" (DROPBOX destination) and "folder_path" (WATCH_FOLDER source)
|
||||||
folder_path = cfg.get("folder", cfg.get("folder_path", ""))
|
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(
|
return templates.TemplateResponse(
|
||||||
"dropbox.html",
|
"dropbox.html",
|
||||||
{
|
{
|
||||||
@@ -56,8 +59,9 @@ async def dropbox_setup_page(
|
|||||||
"integration_name": integration.name,
|
"integration_name": integration.name,
|
||||||
"integration_type": integration.integration_type,
|
"integration_type": integration.integration_type,
|
||||||
"folder_path": folder_path,
|
"folder_path": folder_path,
|
||||||
"app_key_value": "",
|
"has_system_credentials": has_system_credentials,
|
||||||
"app_secret_value": "",
|
"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": "",
|
"refresh_token_value": "",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -71,6 +75,7 @@ async def dropbox_setup_page(
|
|||||||
"request": request,
|
"request": request,
|
||||||
"user_mode": False,
|
"user_mode": False,
|
||||||
"is_configured": is_configured,
|
"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_key_value": settings.dropbox_app_key or "",
|
||||||
"app_secret_value": settings.dropbox_app_secret if settings.dropbox_app_secret else "",
|
"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 "",
|
"refresh_token_value": settings.dropbox_refresh_token if settings.dropbox_refresh_token else "",
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ async def google_drive_setup_page(
|
|||||||
except (json.JSONDecodeError, TypeError):
|
except (json.JSONDecodeError, TypeError):
|
||||||
cfg = {}
|
cfg = {}
|
||||||
folder_id = cfg.get("folder_id", "")
|
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(
|
return templates.TemplateResponse(
|
||||||
"google_drive.html",
|
"google_drive.html",
|
||||||
{
|
{
|
||||||
@@ -58,10 +63,15 @@ async def google_drive_setup_page(
|
|||||||
"use_oauth": True,
|
"use_oauth": True,
|
||||||
"oauth_configured": bool(integration.credentials),
|
"oauth_configured": bool(integration.credentials),
|
||||||
"sa_configured": False,
|
"sa_configured": False,
|
||||||
"client_id": False,
|
"has_system_credentials": has_system_credentials,
|
||||||
"client_id_value": "",
|
"client_id": bool(settings.google_drive_client_id) if has_system_credentials else False,
|
||||||
"client_secret": False,
|
"client_id_value": (
|
||||||
"client_secret_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": False,
|
||||||
"refresh_token_value": "",
|
"refresh_token_value": "",
|
||||||
"has_credentials_json": False,
|
"has_credentials_json": False,
|
||||||
@@ -90,6 +100,9 @@ async def google_drive_setup_page(
|
|||||||
"use_oauth": use_oauth,
|
"use_oauth": use_oauth,
|
||||||
"oauth_configured": oauth_configured,
|
"oauth_configured": oauth_configured,
|
||||||
"sa_configured": sa_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": bool(settings.google_drive_client_id),
|
||||||
"client_id_value": settings.google_drive_client_id or "",
|
"client_id_value": settings.google_drive_client_id or "",
|
||||||
"client_secret": bool(settings.google_drive_client_secret),
|
"client_secret": bool(settings.google_drive_client_secret),
|
||||||
|
|||||||
+12
-5
@@ -44,6 +44,9 @@ async def onedrive_setup_page(
|
|||||||
cfg = {}
|
cfg = {}
|
||||||
# Support both "folder_path" (WATCH_FOLDER / ONEDRIVE destination)
|
# Support both "folder_path" (WATCH_FOLDER / ONEDRIVE destination)
|
||||||
folder_path = cfg.get("folder_path", cfg.get("folder", ""))
|
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(
|
return templates.TemplateResponse(
|
||||||
"onedrive.html",
|
"onedrive.html",
|
||||||
{
|
{
|
||||||
@@ -54,11 +57,14 @@ async def onedrive_setup_page(
|
|||||||
"integration_name": integration.name,
|
"integration_name": integration.name,
|
||||||
"integration_type": integration.integration_type,
|
"integration_type": integration.integration_type,
|
||||||
"folder_path": folder_path,
|
"folder_path": folder_path,
|
||||||
"client_id": False,
|
"has_system_credentials": has_system_credentials,
|
||||||
"client_id_value": "",
|
"client_id": bool(settings.onedrive_client_id) if has_system_credentials else False,
|
||||||
"client_secret": False,
|
"client_id_value": settings.onedrive_client_id or "" if has_system_credentials else "",
|
||||||
"client_secret_value": "",
|
"client_secret": bool(settings.onedrive_client_secret) if has_system_credentials else False,
|
||||||
"tenant_id": "common",
|
"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": False,
|
||||||
"refresh_token_value": "",
|
"refresh_token_value": "",
|
||||||
},
|
},
|
||||||
@@ -75,6 +81,7 @@ async def onedrive_setup_page(
|
|||||||
"request": request,
|
"request": request,
|
||||||
"user_mode": False,
|
"user_mode": False,
|
||||||
"is_configured": is_configured,
|
"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": bool(settings.onedrive_client_id),
|
||||||
"client_id_value": settings.onedrive_client_id or "",
|
"client_id_value": settings.onedrive_client_id or "",
|
||||||
"client_secret": bool(settings.onedrive_client_secret),
|
"client_secret": bool(settings.onedrive_client_secret),
|
||||||
|
|||||||
@@ -116,14 +116,31 @@
|
|||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div>
|
{% if user_mode and has_system_credentials %}
|
||||||
<label for="app-key" class="block text-sm font-medium text-gray-700">App Key <span class="text-red-500" aria-hidden="true">*</span></label>
|
<!-- System credentials toggle (user mode only) -->
|
||||||
<input type="text" id="app-key" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="Enter your Dropbox app key" value="{{ app_key_value }}">
|
<div class="bg-green-50 border border-green-200 rounded-md p-4">
|
||||||
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
|
<input type="checkbox" id="use-system-creds" checked class="rounded border-gray-300 text-green-600 focus:ring-green-500 h-5 w-5" />
|
||||||
|
<div>
|
||||||
|
<span class="text-sm font-medium text-green-800">Use DocuElevate's app credentials</span>
|
||||||
|
<p class="text-xs text-green-600 mt-0.5">Recommended — authorize with your Dropbox account without needing your own app registration.</p>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div>
|
<div id="custom-creds-section" {% if user_mode and has_system_credentials %}class="hidden"{% endif %}>
|
||||||
<label for="app-secret" class="block text-sm font-medium text-gray-700">App Secret <span class="text-red-500" aria-hidden="true">*</span></label>
|
<div class="space-y-4">
|
||||||
<input type="password" id="app-secret" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="Enter your Dropbox app secret" value="{{ app_secret_value }}">
|
<div>
|
||||||
|
<label for="app-key" class="block text-sm font-medium text-gray-700">App Key <span class="text-red-500" aria-hidden="true">*</span></label>
|
||||||
|
<input type="text" id="app-key" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="Enter your Dropbox app key" value="{{ app_key_value if not (user_mode and has_system_credentials) else '' }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="app-secret" class="block text-sm font-medium text-gray-700">App Secret <span class="text-red-500" aria-hidden="true">*</span></label>
|
||||||
|
<input type="password" id="app-secret" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="Enter your Dropbox app secret" value="{{ app_secret_value if not (user_mode and has_system_credentials) else '' }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if not user_mode %}
|
{% if not user_mode %}
|
||||||
@@ -268,6 +285,9 @@ DROPBOX_FOLDER={{ folder_path|default('/Documents/Uploads', true) }}</code></pre
|
|||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const userMode = {{ 'true' if user_mode else 'false' }};
|
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)
|
// Store integration_id if provided (for per-user OAuth flow)
|
||||||
const integrationId = "{{ integration_id or '' }}";
|
const integrationId = "{{ integration_id or '' }}";
|
||||||
@@ -281,6 +301,19 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
const refreshTokenBtn = document.getElementById('refresh-token-btn');
|
const refreshTokenBtn = document.getElementById('refresh-token-btn');
|
||||||
const tokenStatus = document.getElementById('token-status');
|
const tokenStatus = document.getElementById('token-status');
|
||||||
const appSecretInput = document.getElementById('app-secret');
|
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
|
// Modal elements
|
||||||
const resultModal = document.getElementById('resultModal');
|
const resultModal = document.getElementById('resultModal');
|
||||||
@@ -330,8 +363,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
// Start Authentication Flow button click
|
// Start Authentication Flow button click
|
||||||
startAuthFlowBtn.addEventListener('click', function() {
|
startAuthFlowBtn.addEventListener('click', function() {
|
||||||
const appKey = document.getElementById('app-key').value.trim();
|
// Determine which credentials to use
|
||||||
const appSecret = appSecretInput.value.trim();
|
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";
|
const redirectUri = window.location.origin + "/dropbox-callback";
|
||||||
|
|
||||||
if (!appKey) {
|
if (!appKey) {
|
||||||
@@ -347,6 +382,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
// Save app key and app secret to session storage temporarily
|
// Save app key and app secret to session storage temporarily
|
||||||
sessionStorage.setItem('dropbox_app_key', appKey);
|
sessionStorage.setItem('dropbox_app_key', appKey);
|
||||||
sessionStorage.setItem('dropbox_app_secret', appSecret);
|
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
|
// In admin mode also store folder path; in user mode the config is already set
|
||||||
if (!userMode) {
|
if (!userMode) {
|
||||||
|
|||||||
@@ -167,14 +167,31 @@
|
|||||||
<p class="mb-4">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.</p>
|
<p class="mb-4">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.</p>
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div>
|
{% if user_mode and has_system_credentials %}
|
||||||
<label for="client-id" class="block text-sm font-medium text-gray-700">Client ID</label>
|
<!-- System credentials toggle (user mode only) -->
|
||||||
<input type="text" id="client-id" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="Enter your OAuth Client ID" value="{{ client_id_value }}">
|
<div class="bg-green-50 border border-green-200 rounded-md p-4">
|
||||||
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
|
<input type="checkbox" id="use-system-creds" checked class="rounded border-gray-300 text-green-600 focus:ring-green-500 h-5 w-5" />
|
||||||
|
<div>
|
||||||
|
<span class="text-sm font-medium text-green-800">Use DocuElevate's app credentials</span>
|
||||||
|
<p class="text-xs text-green-600 mt-0.5">Recommended — authorize with your Google account without needing your own Google Cloud app registration.</p>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div>
|
<div id="custom-creds-section" {% if user_mode and has_system_credentials %}class="hidden"{% endif %}>
|
||||||
<label for="client-secret" class="block text-sm font-medium text-gray-700">Client Secret</label>
|
<div class="space-y-4">
|
||||||
<input type="password" id="client-secret" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="Enter your OAuth Client Secret" value="{{ client_secret_value }}">
|
<div>
|
||||||
|
<label for="client-id" class="block text-sm font-medium text-gray-700">Client ID</label>
|
||||||
|
<input type="text" id="client-id" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="Enter your OAuth Client ID" value="{{ client_id_value if not (user_mode and has_system_credentials) else '' }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="client-secret" class="block text-sm font-medium text-gray-700">Client Secret</label>
|
||||||
|
<input type="password" id="client-secret" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="Enter your OAuth Client Secret" value="{{ client_secret_value if not (user_mode and has_system_credentials) else '' }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@@ -430,6 +447,9 @@ GOOGLE_DRIVE_FOLDER_ID={{ folder_id|default('YOUR_FOLDER_ID', true) }}
|
|||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const userMode = {{ 'true' if user_mode else 'false' }};
|
const userMode = {{ 'true' if user_mode else 'false' }};
|
||||||
|
const hasSystemCredentials = {{ 'true' if (user_mode and has_system_credentials) else 'false' }};
|
||||||
|
const systemClientId = {{ (client_id_value or '') | tojson }};
|
||||||
|
const systemClientSecret = {{ (client_secret_value or '') | tojson }};
|
||||||
|
|
||||||
// Store integration_id if provided (for per-user OAuth flow)
|
// Store integration_id if provided (for per-user OAuth flow)
|
||||||
const integrationId = "{{ integration_id or '' }}";
|
const integrationId = "{{ integration_id or '' }}";
|
||||||
@@ -437,6 +457,19 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
sessionStorage.setItem('oauth_integration_id', integrationId);
|
sessionStorage.setItem('oauth_integration_id', integrationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// System credentials toggle
|
||||||
|
const useSystemCredsCheckbox = document.getElementById('use-system-creds');
|
||||||
|
const customCredsSection = document.getElementById('custom-creds-section');
|
||||||
|
if (useSystemCredsCheckbox && customCredsSection) {
|
||||||
|
useSystemCredsCheckbox.addEventListener('change', function() {
|
||||||
|
if (this.checked) {
|
||||||
|
customCredsSection.classList.add('hidden');
|
||||||
|
} else {
|
||||||
|
customCredsSection.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Form elements
|
// Form elements
|
||||||
const clientIdInput = document.getElementById('client-id');
|
const clientIdInput = document.getElementById('client-id');
|
||||||
const clientSecretInput = document.getElementById('client-secret');
|
const clientSecretInput = document.getElementById('client-secret');
|
||||||
@@ -719,8 +752,10 @@ GOOGLE_DRIVE_FOLDER_ID=${folderId}
|
|||||||
// Start OAuth flow button
|
// Start OAuth flow button
|
||||||
if (startOauthFlowBtn) {
|
if (startOauthFlowBtn) {
|
||||||
startOauthFlowBtn.addEventListener('click', function() {
|
startOauthFlowBtn.addEventListener('click', function() {
|
||||||
const clientId = clientIdInput.value.trim();
|
// Determine which credentials to use
|
||||||
const clientSecret = clientSecretInput.value.trim();
|
const useSystemCreds = hasSystemCredentials && useSystemCredsCheckbox && useSystemCredsCheckbox.checked;
|
||||||
|
const clientId = useSystemCreds ? systemClientId : clientIdInput.value.trim();
|
||||||
|
const clientSecret = useSystemCreds ? systemClientSecret : clientSecretInput.value.trim();
|
||||||
const folderId = folderIdInput ? folderIdInput.value.trim() : '';
|
const folderId = folderIdInput ? folderIdInput.value.trim() : '';
|
||||||
|
|
||||||
if (!clientId) {
|
if (!clientId) {
|
||||||
@@ -736,6 +771,9 @@ GOOGLE_DRIVE_FOLDER_ID=${folderId}
|
|||||||
// Save values to session storage for use after redirect
|
// Save values to session storage for use after redirect
|
||||||
sessionStorage.setItem('google_drive_client_id', clientId);
|
sessionStorage.setItem('google_drive_client_id', clientId);
|
||||||
sessionStorage.setItem('google_drive_client_secret', clientSecret);
|
sessionStorage.setItem('google_drive_client_secret', clientSecret);
|
||||||
|
if (useSystemCreds) {
|
||||||
|
sessionStorage.setItem('google_drive_use_system_creds', 'true');
|
||||||
|
}
|
||||||
|
|
||||||
// In admin mode store folder_id; in user mode the config is already set
|
// In admin mode store folder_id; in user mode the config is already set
|
||||||
if (!userMode && folderId) {
|
if (!userMode && folderId) {
|
||||||
|
|||||||
@@ -130,20 +130,37 @@
|
|||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div>
|
{% if user_mode and has_system_credentials %}
|
||||||
<label for="client-id" class="block text-sm font-medium text-gray-700">Client ID <span class="text-red-500" aria-hidden="true">*</span></label>
|
<!-- System credentials toggle (user mode only) -->
|
||||||
<input type="text" id="client-id" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="Enter your Azure AD application client ID" value="{{ client_id_value }}">
|
<div class="bg-green-50 border border-green-200 rounded-md p-4">
|
||||||
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
|
<input type="checkbox" id="use-system-creds" checked class="rounded border-gray-300 text-green-600 focus:ring-green-500 h-5 w-5" />
|
||||||
|
<div>
|
||||||
|
<span class="text-sm font-medium text-green-800">Use DocuElevate's app credentials</span>
|
||||||
|
<p class="text-xs text-green-600 mt-0.5">Recommended — authorize with your OneDrive account without needing your own Azure app registration.</p>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div>
|
<div id="custom-creds-section" {% if user_mode and has_system_credentials %}class="hidden"{% endif %}>
|
||||||
<label for="client-secret" class="block text-sm font-medium text-gray-700">Client Secret <span class="text-red-500" aria-hidden="true">*</span></label>
|
<div class="space-y-4">
|
||||||
<input type="password" id="client-secret" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="Enter your Azure AD application client secret" value="{{ client_secret_value }}">
|
<div>
|
||||||
</div>
|
<label for="client-id" class="block text-sm font-medium text-gray-700">Client ID <span class="text-red-500" aria-hidden="true">*</span></label>
|
||||||
|
<input type="text" id="client-id" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="Enter your Azure AD application client ID" value="{{ client_id_value if not (user_mode and has_system_credentials) else '' }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="tenant-id" class="block text-sm font-medium text-gray-700">Tenant ID (Optional)</label>
|
<label for="client-secret" class="block text-sm font-medium text-gray-700">Client Secret <span class="text-red-500" aria-hidden="true">*</span></label>
|
||||||
<input type="text" id="tenant-id" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="common" value="{{ tenant_id }}">
|
<input type="password" id="client-secret" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="Enter your Azure AD application client secret" value="{{ client_secret_value if not (user_mode and has_system_credentials) else '' }}">
|
||||||
<p class="text-xs text-gray-500 mt-1">Use "common" for personal accounts or your organization's Tenant ID for corporate accounts</p>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="tenant-id" class="block text-sm font-medium text-gray-700">Tenant ID (Optional)</label>
|
||||||
|
<input type="text" id="tenant-id" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="common" value="{{ tenant_id }}">
|
||||||
|
<p class="text-xs text-gray-500 mt-1">Use "common" for personal accounts or your organization's Tenant ID for corporate accounts</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if not user_mode %}
|
{% if not user_mode %}
|
||||||
@@ -289,6 +306,10 @@ ONEDRIVE_FOLDER_PATH={{ folder_path|default('Documents/Uploads', true) }}</code>
|
|||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const userMode = {{ 'true' if user_mode else 'false' }};
|
const userMode = {{ 'true' if user_mode else 'false' }};
|
||||||
|
const hasSystemCredentials = {{ 'true' if (user_mode and has_system_credentials) else 'false' }};
|
||||||
|
const systemClientId = {{ (client_id_value or '') | tojson }};
|
||||||
|
const systemClientSecret = {{ (client_secret_value or '') | tojson }};
|
||||||
|
const systemTenantId = {{ (tenant_id or 'common') | tojson }};
|
||||||
|
|
||||||
// Store integration_id if provided (for per-user OAuth flow)
|
// Store integration_id if provided (for per-user OAuth flow)
|
||||||
const integrationId = "{{ integration_id or '' }}";
|
const integrationId = "{{ integration_id or '' }}";
|
||||||
@@ -302,6 +323,19 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
const refreshTokenBtn = document.getElementById('refresh-token-btn');
|
const refreshTokenBtn = document.getElementById('refresh-token-btn');
|
||||||
const tokenStatus = document.getElementById('token-status');
|
const tokenStatus = document.getElementById('token-status');
|
||||||
const clientSecretInput = document.getElementById('client-secret');
|
const clientSecretInput = document.getElementById('client-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
|
// Modal elements
|
||||||
const resultModal = document.getElementById('resultModal');
|
const resultModal = document.getElementById('resultModal');
|
||||||
@@ -351,10 +385,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
// Start Authentication Flow button click
|
// Start Authentication Flow button click
|
||||||
startAuthFlowBtn.addEventListener('click', function() {
|
startAuthFlowBtn.addEventListener('click', function() {
|
||||||
const clientId = document.getElementById('client-id').value.trim();
|
// Determine which credentials to use
|
||||||
const clientSecret = clientSecretInput.value.trim();
|
const useSystemCreds = hasSystemCredentials && useSystemCredsCheckbox && useSystemCredsCheckbox.checked;
|
||||||
|
const clientId = useSystemCreds ? systemClientId : document.getElementById('client-id').value.trim();
|
||||||
|
const clientSecret = useSystemCreds ? systemClientSecret : clientSecretInput.value.trim();
|
||||||
const redirectUri = window.location.origin + "/onedrive-callback";
|
const redirectUri = window.location.origin + "/onedrive-callback";
|
||||||
const tenantId = document.getElementById('tenant-id').value.trim() || 'common';
|
const tenantId = useSystemCreds ? systemTenantId : (document.getElementById('tenant-id').value.trim() || 'common');
|
||||||
|
|
||||||
if (!clientId) {
|
if (!clientId) {
|
||||||
showModal('error', 'Validation Error', 'Please enter your Client ID');
|
showModal('error', 'Validation Error', 'Please enter your Client ID');
|
||||||
@@ -370,6 +406,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
sessionStorage.setItem('onedrive_client_id', clientId);
|
sessionStorage.setItem('onedrive_client_id', clientId);
|
||||||
sessionStorage.setItem('onedrive_client_secret', clientSecret);
|
sessionStorage.setItem('onedrive_client_secret', clientSecret);
|
||||||
sessionStorage.setItem('onedrive_tenant_id', tenantId);
|
sessionStorage.setItem('onedrive_tenant_id', tenantId);
|
||||||
|
if (useSystemCreds) {
|
||||||
|
sessionStorage.setItem('onedrive_use_system_creds', 'true');
|
||||||
|
}
|
||||||
|
|
||||||
// In admin mode also store folder path; in user mode the config is already set
|
// In admin mode also store folder path; in user mode the config is already set
|
||||||
if (!userMode) {
|
if (!userMode) {
|
||||||
|
|||||||
Reference in New Issue
Block a user