feat(auth): save OAuth credentials per-user to UserIntegration records
- Add 'Authorize' button to integration cards for OAuth types without credentials
- Add isOAuthType() helper and update info box in create/edit modal
- Accept integration_id query param in Dropbox, Google Drive, OneDrive setup views
- Store integration_id in sessionStorage on setup pages
- Add per-user flow in OAuth callbacks: PUT credentials to /api/integrations/{id}
- Preserve existing global flow as fallback when no integration_id is present
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -97,6 +97,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const appKey = sessionStorage.getItem('dropbox_app_key') || "{{ app_key_value }}";
|
||||
const appSecret = sessionStorage.getItem('dropbox_app_secret') || "{{ app_secret_value }}";
|
||||
const folderPath = sessionStorage.getItem('dropbox_folder_path') || "{{ folder_path }}" || '/Documents/Uploads';
|
||||
const integrationId = sessionStorage.getItem('oauth_integration_id');
|
||||
|
||||
const redirectUri = window.location.origin + "/dropbox-callback";
|
||||
|
||||
@@ -137,7 +138,50 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
})
|
||||
.then(data => {
|
||||
if (data.refresh_token) {
|
||||
// Update settings in memory
|
||||
// Per-user flow: save to the user's integration record
|
||||
if (integrationId) {
|
||||
const creds = {
|
||||
refresh_token: data.refresh_token,
|
||||
app_key: appKey,
|
||||
app_secret: appSecret,
|
||||
};
|
||||
const cfgUpdate = {};
|
||||
if (folderPath) cfgUpdate.folder = folderPath;
|
||||
|
||||
const body = { credentials: creds };
|
||||
if (Object.keys(cfgUpdate).length > 0) body.config = cfgUpdate;
|
||||
|
||||
document.getElementById('processing-message').innerHTML =
|
||||
'<p>Saving credentials to your integration...</p>';
|
||||
|
||||
return fetch(`/api/integrations/${integrationId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(body),
|
||||
}).then(response => {
|
||||
if (!response.ok) {
|
||||
return response.json().then(err => {
|
||||
throw new Error('Failed to save credentials: ' + (err.detail || 'Unknown error'));
|
||||
});
|
||||
}
|
||||
return response.json();
|
||||
}).then(() => {
|
||||
// Clean up
|
||||
sessionStorage.removeItem('dropbox_app_key');
|
||||
sessionStorage.removeItem('dropbox_app_secret');
|
||||
sessionStorage.removeItem('dropbox_folder_path');
|
||||
sessionStorage.removeItem('oauth_integration_id');
|
||||
|
||||
// Show brief success then redirect to integrations
|
||||
document.getElementById('processing-message').innerHTML =
|
||||
'<p class="text-green-600 font-semibold">✓ Dropbox authorized successfully!</p>' +
|
||||
'<p class="text-sm text-gray-500 mt-2">Redirecting to Integrations...</p>';
|
||||
document.querySelector('.animate-spin').parentNode.classList.add('hidden');
|
||||
setTimeout(() => { window.location.href = '/integrations'; }, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
// Global flow: update settings in memory
|
||||
const updateFormData = new FormData();
|
||||
updateFormData.append('refresh_token', data.refresh_token);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user