diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index 6864306a2..31ea93399 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -1186,9 +1186,7 @@ async def get_app_config(request: Request): "client_id": GOOGLE_DRIVE_CLIENT_ID.value, "api_key": GOOGLE_DRIVE_API_KEY.value, }, - "onedrive": { - "client_id": ONEDRIVE_CLIENT_ID.value - } + "onedrive": {"client_id": ONEDRIVE_CLIENT_ID.value}, } if user is not None else {} diff --git a/src/lib/components/admin/Settings/Documents.svelte b/src/lib/components/admin/Settings/Documents.svelte index 248f6e9f5..adc607168 100644 --- a/src/lib/components/admin/Settings/Documents.svelte +++ b/src/lib/components/admin/Settings/Documents.svelte @@ -667,7 +667,6 @@ -
diff --git a/src/lib/components/chat/ChatPlaceholder.svelte b/src/lib/components/chat/ChatPlaceholder.svelte index a2f1f080d..0dfaec968 100644 --- a/src/lib/components/chat/ChatPlaceholder.svelte +++ b/src/lib/components/chat/ChatPlaceholder.svelte @@ -127,8 +127,7 @@
- - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index 611644831..72ed2a462 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -350,7 +350,7 @@ {#if Object.keys(history?.messages ?? {}).length == 0} { let text = p; diff --git a/src/lib/components/chat/Placeholder.svelte b/src/lib/components/chat/Placeholder.svelte index f64b607aa..74d6cd9fc 100644 --- a/src/lib/components/chat/Placeholder.svelte +++ b/src/lib/components/chat/Placeholder.svelte @@ -213,8 +213,7 @@
{ const initials = sanitizedName.length > 0 ? sanitizedName[0] + - (sanitizedName.split(' ').length > 1 - ? sanitizedName[sanitizedName.lastIndexOf(' ') + 1] - : '') + (sanitizedName.split(' ').length > 1 + ? sanitizedName[sanitizedName.lastIndexOf(' ') + 1] + : '') : ''; ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); @@ -348,10 +348,10 @@ export const compareVersion = (latest, current) => { return current === '0.0.0' ? false : current.localeCompare(latest, undefined, { - numeric: true, - sensitivity: 'case', - caseFirst: 'upper' - }) < 0; + numeric: true, + sensitivity: 'case', + caseFirst: 'upper' + }) < 0; }; export const findWordIndices = (text) => { diff --git a/src/lib/utils/onedrive-file-picker.ts b/src/lib/utils/onedrive-file-picker.ts index e3a80c912..d26469529 100644 --- a/src/lib/utils/onedrive-file-picker.ts +++ b/src/lib/utils/onedrive-file-picker.ts @@ -1,266 +1,266 @@ let CLIENT_ID = ''; async function getCredentials() { - if (CLIENT_ID) return; - const response = await fetch('/api/config'); - if (!response.ok) { - throw new Error('Failed to fetch OneDrive credentials'); - } - const config = await response.json(); - CLIENT_ID = config.onedrive?.client_id; - if (!CLIENT_ID) { - throw new Error('OneDrive client ID not configured'); - } + if (CLIENT_ID) return; + const response = await fetch('/api/config'); + if (!response.ok) { + throw new Error('Failed to fetch OneDrive credentials'); + } + const config = await response.json(); + CLIENT_ID = config.onedrive?.client_id; + if (!CLIENT_ID) { + throw new Error('OneDrive client ID not configured'); + } } function loadMsalScript(): Promise { - return new Promise((resolve, reject) => { - const win = window; - if (win.msal) { - resolve(); - return; - } - const script = document.createElement('script'); - script.src = 'https://alcdn.msauth.net/browser/2.19.0/js/msal-browser.min.js'; - script.async = true; - script.onload = () => resolve(); - script.onerror = () => reject(new Error('Failed to load MSAL script')); - document.head.appendChild(script); - }); + return new Promise((resolve, reject) => { + const win = window; + if (win.msal) { + resolve(); + return; + } + const script = document.createElement('script'); + script.src = 'https://alcdn.msauth.net/browser/2.19.0/js/msal-browser.min.js'; + script.async = true; + script.onload = () => resolve(); + script.onerror = () => reject(new Error('Failed to load MSAL script')); + document.head.appendChild(script); + }); } let msalInstance: any; // Initialize MSAL authentication async function initializeMsal() { - if (!CLIENT_ID) { - await getCredentials(); - } - const msalParams = { - auth: { - authority: 'https://login.microsoftonline.com/consumers', - clientId: CLIENT_ID - } - }; - try { - await loadMsalScript(); - const win = window; - msalInstance = new win.msal.PublicClientApplication(msalParams); - if (msalInstance.initialize) { - await msalInstance.initialize(); - } - } catch (error) { - console.error('MSAL initialization error:', error); - } + if (!CLIENT_ID) { + await getCredentials(); + } + const msalParams = { + auth: { + authority: 'https://login.microsoftonline.com/consumers', + clientId: CLIENT_ID + } + }; + try { + await loadMsalScript(); + const win = window; + msalInstance = new win.msal.PublicClientApplication(msalParams); + if (msalInstance.initialize) { + await msalInstance.initialize(); + } + } catch (error) { + console.error('MSAL initialization error:', error); + } } // Retrieve OneDrive access token async function getToken(): Promise { - const authParams = { scopes: ['OneDrive.ReadWrite'] }; - let accessToken = ''; - try { - await initializeMsal(); - const resp = await msalInstance.acquireTokenSilent(authParams); - accessToken = resp.accessToken; - } catch (err) { - const resp = await msalInstance.loginPopup(authParams); - msalInstance.setActiveAccount(resp.account); - if (resp.idToken) { - const resp2 = await msalInstance.acquireTokenSilent(authParams); - accessToken = resp2.accessToken; - } - } - return accessToken; + const authParams = { scopes: ['OneDrive.ReadWrite'] }; + let accessToken = ''; + try { + await initializeMsal(); + const resp = await msalInstance.acquireTokenSilent(authParams); + accessToken = resp.accessToken; + } catch (err) { + const resp = await msalInstance.loginPopup(authParams); + msalInstance.setActiveAccount(resp.account); + if (resp.idToken) { + const resp2 = await msalInstance.acquireTokenSilent(authParams); + accessToken = resp2.accessToken; + } + } + return accessToken; } -const baseUrl = "https://onedrive.live.com/picker"; +const baseUrl = 'https://onedrive.live.com/picker'; const params = { - sdk: '8.0', - entry: { - oneDrive: { - files: {} - } - }, - authentication: {}, - messaging: { - origin: window?.location?.origin, - channelId: crypto.randomUUID() - }, - typesAndSources: { - mode: 'files', - pivots: { - oneDrive: true, - recent: true - } - } + sdk: '8.0', + entry: { + oneDrive: { + files: {} + } + }, + authentication: {}, + messaging: { + origin: window?.location?.origin, + channelId: crypto.randomUUID() + }, + typesAndSources: { + mode: 'files', + pivots: { + oneDrive: true, + recent: true + } + } }; // Download file from OneDrive async function downloadOneDriveFile(fileInfo: any): Promise { - const accessToken = await getToken(); - if (!accessToken) { - throw new Error('Unable to retrieve OneDrive access token.'); - } - const fileInfoUrl = `${fileInfo["@sharePoint.endpoint"]}/drives/${fileInfo.parentReference.driveId}/items/${fileInfo.id}`; - const response = await fetch(fileInfoUrl, { - headers: { - 'Authorization': `Bearer ${accessToken}` - } - }); - if (!response.ok) { - throw new Error('Failed to fetch file information.'); - } - const fileData = await response.json(); - const downloadUrl = fileData['@content.downloadUrl']; - const downloadResponse = await fetch(downloadUrl); - if (!downloadResponse.ok) { - throw new Error('Failed to download file.'); - } - return await downloadResponse.blob(); + const accessToken = await getToken(); + if (!accessToken) { + throw new Error('Unable to retrieve OneDrive access token.'); + } + const fileInfoUrl = `${fileInfo['@sharePoint.endpoint']}/drives/${fileInfo.parentReference.driveId}/items/${fileInfo.id}`; + const response = await fetch(fileInfoUrl, { + headers: { + Authorization: `Bearer ${accessToken}` + } + }); + if (!response.ok) { + throw new Error('Failed to fetch file information.'); + } + const fileData = await response.json(); + const downloadUrl = fileData['@content.downloadUrl']; + const downloadResponse = await fetch(downloadUrl); + if (!downloadResponse.ok) { + throw new Error('Failed to download file.'); + } + return await downloadResponse.blob(); } // Open OneDrive file picker and return selected file metadata export async function openOneDrivePicker(): Promise { - if (typeof window === 'undefined') { - throw new Error('Not in browser environment'); - } - return new Promise((resolve, reject) => { - let pickerWindow: Window | null = null; - let channelPort: MessagePort | null = null; + if (typeof window === 'undefined') { + throw new Error('Not in browser environment'); + } + return new Promise((resolve, reject) => { + let pickerWindow: Window | null = null; + let channelPort: MessagePort | null = null; - const handleWindowMessage = (event: MessageEvent) => { - if (event.source !== pickerWindow) return; - const message = event.data; - if (message?.type === 'initialize' && message?.channelId === params.messaging.channelId) { - channelPort = event.ports?.[0]; - if (!channelPort) return; - channelPort.addEventListener('message', handlePortMessage); - channelPort.start(); - channelPort.postMessage({ type: 'activate' }); - } - }; + const handleWindowMessage = (event: MessageEvent) => { + if (event.source !== pickerWindow) return; + const message = event.data; + if (message?.type === 'initialize' && message?.channelId === params.messaging.channelId) { + channelPort = event.ports?.[0]; + if (!channelPort) return; + channelPort.addEventListener('message', handlePortMessage); + channelPort.start(); + channelPort.postMessage({ type: 'activate' }); + } + }; - const handlePortMessage = async (portEvent: MessageEvent) => { - const portData = portEvent.data; - switch (portData.type) { - case 'notification': - break; - case 'command': { - channelPort?.postMessage({ type: 'acknowledge', id: portData.id }); - const command = portData.data; - switch (command.command) { - case 'authenticate': { - try { - const newToken = await getToken(); - if (newToken) { - channelPort?.postMessage({ - type: 'result', - id: portData.id, - data: { result: 'token', token: newToken } - }); - } else { - throw new Error('Could not retrieve auth token'); - } - } catch (err) { - console.error(err); - channelPort?.postMessage({ - result: 'error', - error: { code: 'tokenError', message: 'Failed to get token' }, - isExpected: true - }); - } - break; - } - case 'close': { - cleanup(); - resolve(null); - break; - } - case 'pick': { - channelPort?.postMessage({ - type: 'result', - id: portData.id, - data: { result: 'success' } - }); - cleanup(); - resolve(command); - break; - } - default: { - console.warn('Unsupported command:', command); - channelPort?.postMessage({ - result: 'error', - error: { code: 'unsupportedCommand', message: command.command }, - isExpected: true - }); - break; - } - } - break; - } - } - }; + const handlePortMessage = async (portEvent: MessageEvent) => { + const portData = portEvent.data; + switch (portData.type) { + case 'notification': + break; + case 'command': { + channelPort?.postMessage({ type: 'acknowledge', id: portData.id }); + const command = portData.data; + switch (command.command) { + case 'authenticate': { + try { + const newToken = await getToken(); + if (newToken) { + channelPort?.postMessage({ + type: 'result', + id: portData.id, + data: { result: 'token', token: newToken } + }); + } else { + throw new Error('Could not retrieve auth token'); + } + } catch (err) { + console.error(err); + channelPort?.postMessage({ + result: 'error', + error: { code: 'tokenError', message: 'Failed to get token' }, + isExpected: true + }); + } + break; + } + case 'close': { + cleanup(); + resolve(null); + break; + } + case 'pick': { + channelPort?.postMessage({ + type: 'result', + id: portData.id, + data: { result: 'success' } + }); + cleanup(); + resolve(command); + break; + } + default: { + console.warn('Unsupported command:', command); + channelPort?.postMessage({ + result: 'error', + error: { code: 'unsupportedCommand', message: command.command }, + isExpected: true + }); + break; + } + } + break; + } + } + }; - function cleanup() { - window.removeEventListener('message', handleWindowMessage); - if (channelPort) { - channelPort.removeEventListener('message', handlePortMessage); - } - if (pickerWindow) { - pickerWindow.close(); - pickerWindow = null; - } - } + function cleanup() { + window.removeEventListener('message', handleWindowMessage); + if (channelPort) { + channelPort.removeEventListener('message', handlePortMessage); + } + if (pickerWindow) { + pickerWindow.close(); + pickerWindow = null; + } + } - const initializePicker = async () => { - try { - const authToken = await getToken(); - if (!authToken) { - return reject(new Error('Failed to acquire access token')); - } - pickerWindow = window.open('', 'OneDrivePicker', 'width=800,height=600'); - if (!pickerWindow) { - return reject(new Error('Failed to open OneDrive picker window')); - } - const queryString = new URLSearchParams({ - filePicker: JSON.stringify(params) - }); - const url = `${baseUrl}?${queryString.toString()}`; - const form = pickerWindow.document.createElement('form'); - form.setAttribute('action', url); - form.setAttribute('method', 'POST'); - const input = pickerWindow.document.createElement('input'); - input.setAttribute('type', 'hidden'); - input.setAttribute('name', 'access_token'); - input.setAttribute('value', authToken); - form.appendChild(input); - pickerWindow.document.body.appendChild(form); - form.submit(); - window.addEventListener('message', handleWindowMessage); - } catch (err) { - if (pickerWindow) pickerWindow.close(); - reject(err); - } - }; + const initializePicker = async () => { + try { + const authToken = await getToken(); + if (!authToken) { + return reject(new Error('Failed to acquire access token')); + } + pickerWindow = window.open('', 'OneDrivePicker', 'width=800,height=600'); + if (!pickerWindow) { + return reject(new Error('Failed to open OneDrive picker window')); + } + const queryString = new URLSearchParams({ + filePicker: JSON.stringify(params) + }); + const url = `${baseUrl}?${queryString.toString()}`; + const form = pickerWindow.document.createElement('form'); + form.setAttribute('action', url); + form.setAttribute('method', 'POST'); + const input = pickerWindow.document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'access_token'); + input.setAttribute('value', authToken); + form.appendChild(input); + pickerWindow.document.body.appendChild(form); + form.submit(); + window.addEventListener('message', handleWindowMessage); + } catch (err) { + if (pickerWindow) pickerWindow.close(); + reject(err); + } + }; - initializePicker(); - }); + initializePicker(); + }); } // Pick and download file from OneDrive export async function pickAndDownloadFile(): Promise<{ blob: Blob; name: string } | null> { - try { - const pickerResult = await openOneDrivePicker(); - if (!pickerResult || !pickerResult.items || pickerResult.items.length === 0) { - return null; - } - const selectedFile = pickerResult.items[0]; - const blob = await downloadOneDriveFile(selectedFile); - return { blob, name: selectedFile.name }; - } catch (error) { - console.error('Error occurred during OneDrive file pick/download:', error); - throw error; - } + try { + const pickerResult = await openOneDrivePicker(); + if (!pickerResult || !pickerResult.items || pickerResult.items.length === 0) { + return null; + } + const selectedFile = pickerResult.items[0]; + const blob = await downloadOneDriveFile(selectedFile); + return { blob, name: selectedFile.name }; + } catch (error) { + console.error('Error occurred during OneDrive file pick/download:', error); + throw error; + } } export { downloadOneDriveFile };