diff --git a/README.md b/README.md index db733ffa..092be36e 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ The project includes a **UI** for uploading and managing files, and an API docum ## Documentation Index - [User Guide](docs/UserGuide.md) - How to use DocuElevate +- [Browser Extension Guide](docs/BrowserExtension.md) - Install and use the browser extension - [API Documentation](docs/API.md) - API reference - [Deployment Guide](docs/DeploymentGuide.md) - How to deploy DocuElevate - [Configuration Guide](docs/ConfigurationGuide.md) - Available configuration options @@ -72,10 +73,11 @@ DocuElevate follows a streamlined document processing workflow: ### Document Ingestion -Documents enter DocuElevate through three possible channels: +Documents enter DocuElevate through four possible channels: 1. **Web Upload**: Users manually upload files via the web interface -2. **Email Attachments**: Automatic polling of configured IMAP mailboxes (supports multiple accounts) -3. **API**: Direct programmatic uploads via the REST API +2. **Browser Extension**: Send files directly from your browser with one click +3. **Email Attachments**: Automatic polling of configured IMAP mailboxes (supports multiple accounts) +4. **API**: Direct programmatic uploads via the REST API ### Processing Pipeline Every document goes through the following steps: @@ -102,8 +104,13 @@ Users can choose to send documents to any combination of these destinations thro - Drag-and-drop file upload on both Upload and Files pages—upload anywhere on the Files page - Real-time upload progress with validation - Support for PDF, Office documents, images, and more (up to 500MB per file) +- **Browser Extension**: + - Send files directly from your browser to DocuElevate with one click + - Compatible with Chrome, Firefox, Edge, and other Chromium-based browsers + - Context menu integration for quick access + - See [Browser Extension Guide](docs/BrowserExtension.md) for installation and usage - **Document Upload & Storage**: - - Manual uploads (via API or UI) to Dropbox, Nextcloud, Google Drive, or Paperless + - Manual uploads (via API or UI) to Dropbox, Nextcloud, Google Drive, or Paperless - **OCR Processing (Azure)**: - Extract text from scanned PDFs using Azure Document Intelligence - **Metadata Extraction (OpenAI)**: diff --git a/browser-extension/README.md b/browser-extension/README.md new file mode 100644 index 00000000..584a9385 --- /dev/null +++ b/browser-extension/README.md @@ -0,0 +1,238 @@ +# DocuElevate Browser Extension + +Send files from your browser directly to DocuElevate for processing with a single click. + +## Features + +- **One-Click File Sending**: Send file URLs from your browser to DocuElevate +- **Context Menu Integration**: Right-click on links or pages to send them to DocuElevate +- **Secure Configuration**: Store your DocuElevate server URL and authentication in the extension +- **Cross-Browser Support**: Compatible with Chrome, Firefox, Edge, and other Chromium-based browsers +- **Minimal Permissions**: Only requests necessary permissions for functionality +- **Status Feedback**: Get immediate feedback on file submission success or errors + +## Installation + +### Chrome / Edge / Chromium-based Browsers + +1. **Download the Extension**: + - Download or clone the DocuElevate repository + - Navigate to the `browser-extension` folder + +2. **Load the Extension**: + - Open your browser and go to the extensions page: + - Chrome: `chrome://extensions/` + - Edge: `edge://extensions/` + - Enable "Developer mode" (toggle in the top right) + - Click "Load unpacked" + - Select the `browser-extension` folder + +3. **Configure the Extension**: + - Click the DocuElevate icon in your browser toolbar + - Enter your DocuElevate server URL (e.g., `https://docuelevate.example.com`) + - If authentication is enabled, enter your session cookie (optional) + - Click "Save Configuration" + +### Firefox + +1. **Download the Extension**: + - Download or clone the DocuElevate repository + - Navigate to the `browser-extension` folder + +2. **Load the Extension Temporarily**: + - Open Firefox and go to `about:debugging#/runtime/this-firefox` + - Click "Load Temporary Add-on" + - Select the `manifest.json` file in the `browser-extension` folder + +3. **Configure the Extension**: + - Click the DocuElevate icon in your browser toolbar + - Enter your DocuElevate server URL + - If authentication is enabled, enter your session cookie (optional) + - Click "Save Configuration" + +**Note**: For permanent installation in Firefox, you'll need to sign the extension through Mozilla's add-on portal. + +## Usage + +### Method 1: Extension Popup + +1. Navigate to a page with a file URL (e.g., a PDF, DOCX, image) +2. Click the DocuElevate extension icon +3. Optionally, enter a custom filename +4. Click "Send to DocuElevate" +5. Wait for confirmation that the file was sent + +### Method 2: Context Menu + +1. Right-click on a link or the current page +2. Select "Send to DocuElevate" from the context menu +3. A notification will confirm the file was sent or show an error + +## Configuration + +### Server URL + +The DocuElevate server URL should point to your DocuElevate instance: +- Format: `https://your-domain.com` or `http://localhost:8000` +- Do not include trailing slashes or API paths +- The extension will automatically append `/api/process-url` + +### Session Cookie (Optional) + +If your DocuElevate instance has authentication enabled, you need to provide a session cookie: + +1. **Get Your Session Cookie**: + - Log in to DocuElevate in your browser + - Open browser DevTools (F12) + - Go to the "Application" or "Storage" tab + - Find "Cookies" in the left sidebar + - Look for a cookie named `session` + - Copy its value + +2. **Enter in Extension**: + - Format: `session=your_session_value_here` + - The extension will include this in API requests + +**Security Note**: Your session cookie is stored securely in the browser's extension storage. Never share your session cookie with others. + +## Supported File Types + +The extension can send any URL, but DocuElevate will only process supported file types: + +- **Documents**: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT, CSV, RTF +- **Images**: JPG, PNG, GIF, BMP, TIFF, WebP, SVG + +## Troubleshooting + +### "Failed to connect to DocuElevate server" + +**Cause**: The extension cannot reach your DocuElevate server. + +**Solutions**: +- Verify your server URL is correct +- Check that your DocuElevate server is running +- Ensure there are no firewall or CORS issues +- Try accessing the API directly: `https://your-server.com/api/process-url` + +### "Authentication required" or 401 Error + +**Cause**: Your DocuElevate instance requires authentication. + +**Solutions**: +- Get your session cookie (see Configuration section) +- Enter the session cookie in the extension settings +- Ensure your session hasn't expired (log in again if needed) + +### "Unsupported file type" + +**Cause**: The URL doesn't point to a supported file type. + +**Solution**: +- Verify the URL ends with a supported file extension +- Check that the Content-Type header is set correctly by the server + +### "File too large" + +**Cause**: The file exceeds the maximum upload size configured in DocuElevate. + +**Solutions**: +- Check your DocuElevate `MAX_UPLOAD_SIZE` configuration +- Try a smaller file +- Contact your DocuElevate administrator to increase the limit + +## Privacy & Security + +### Permissions Explained + +The extension requests minimal permissions: + +- **activeTab**: To get the URL of the current tab +- **storage**: To save your server URL and session cookie configuration +- **contextMenus**: To add the "Send to DocuElevate" option to right-click menus +- **notifications**: To show success/error notifications + +### Data Handling + +- **No Data Collection**: The extension does not collect, store, or transmit any data except what you explicitly send to your DocuElevate server +- **Local Configuration**: Your server URL and session cookie are stored locally in your browser +- **Direct Communication**: All API requests go directly from your browser to your DocuElevate server +- **No Third Parties**: No data is sent to third-party services + +## Development + +### Building from Source + +The extension is already in a usable state in the `browser-extension` folder. No build process is required. + +### File Structure + +``` +browser-extension/ +├── manifest.json # Extension manifest (Chrome/Firefox compatible) +├── icons/ # Extension icons +│ ├── icon16.png +│ ├── icon32.png +│ ├── icon48.png +│ └── icon128.png +├── popup/ # Extension popup UI +│ ├── popup.html +│ ├── popup.css +│ └── popup.js +└── scripts/ # Background and content scripts + ├── background.js # Service worker for background tasks + └── content.js # Content script for page interaction +``` + +### Testing + +1. Load the extension in developer mode +2. Configure it with your local DocuElevate instance +3. Test with various file URLs +4. Check the browser console for any errors +5. Verify files are being processed in DocuElevate + +## API Endpoint + +The extension uses the DocuElevate URL upload API: + +**Endpoint**: `POST /api/process-url` + +**Request Body**: +```json +{ + "url": "https://example.com/document.pdf", + "filename": "optional-custom-name.pdf" +} +``` + +**Response**: +```json +{ + "task_id": "abc123", + "status": "queued", + "message": "File downloaded from URL and queued for processing", + "filename": "document.pdf", + "size": 1024 +} +``` + +See the [DocuElevate API Documentation](../docs/API.md) for more details. + +## License + +This extension is part of the DocuElevate project and is licensed under the same terms as the main project. + +## Support + +For issues, questions, or feature requests: +- Open an issue on the [DocuElevate GitHub repository](https://github.com/christianlouis/DocuElevate/issues) +- Refer to the main [DocuElevate documentation](../docs/) + +## Version History + +### 1.0.0 (Current) +- Initial release +- Basic URL sending functionality +- Configuration management +- Context menu integration +- Notifications support diff --git a/browser-extension/icons/icon128.png b/browser-extension/icons/icon128.png new file mode 100644 index 00000000..591590b3 Binary files /dev/null and b/browser-extension/icons/icon128.png differ diff --git a/browser-extension/icons/icon16.png b/browser-extension/icons/icon16.png new file mode 100644 index 00000000..591590b3 Binary files /dev/null and b/browser-extension/icons/icon16.png differ diff --git a/browser-extension/icons/icon32.png b/browser-extension/icons/icon32.png new file mode 100644 index 00000000..591590b3 Binary files /dev/null and b/browser-extension/icons/icon32.png differ diff --git a/browser-extension/icons/icon48.png b/browser-extension/icons/icon48.png new file mode 100644 index 00000000..591590b3 Binary files /dev/null and b/browser-extension/icons/icon48.png differ diff --git a/browser-extension/manifest.json b/browser-extension/manifest.json new file mode 100644 index 00000000..d25bdba3 --- /dev/null +++ b/browser-extension/manifest.json @@ -0,0 +1,38 @@ +{ + "manifest_version": 3, + "name": "DocuElevate - Send to Document Processor", + "version": "1.0.0", + "description": "Send files from your browser directly to DocuElevate for processing", + "permissions": [ + "activeTab", + "storage", + "contextMenus", + "notifications" + ], + "host_permissions": [], + "action": { + "default_popup": "popup/popup.html", + "default_icon": { + "16": "icons/icon16.png", + "32": "icons/icon32.png", + "48": "icons/icon48.png", + "128": "icons/icon128.png" + } + }, + "icons": { + "16": "icons/icon16.png", + "32": "icons/icon32.png", + "48": "icons/icon48.png", + "128": "icons/icon128.png" + }, + "background": { + "service_worker": "scripts/background.js" + }, + "content_scripts": [ + { + "matches": [""], + "js": ["scripts/content.js"], + "run_at": "document_idle" + } + ] +} diff --git a/browser-extension/popup/popup.css b/browser-extension/popup/popup.css new file mode 100644 index 00000000..ad440377 --- /dev/null +++ b/browser-extension/popup/popup.css @@ -0,0 +1,200 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + font-size: 14px; + line-height: 1.5; + color: #333; + background-color: #f8f9fa; + width: 400px; + min-height: 300px; +} + +.container { + padding: 16px; +} + +.header { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 20px; + padding-bottom: 12px; + border-bottom: 2px solid #e9ecef; +} + +.logo { + width: 32px; + height: 32px; +} + +h1 { + font-size: 20px; + font-weight: 600; + color: #2c3e50; +} + +h2 { + font-size: 16px; + font-weight: 600; + color: #495057; + margin-bottom: 12px; +} + +.section { + margin-bottom: 16px; +} + +.section.hidden { + display: none; +} + +.form-group { + margin-bottom: 16px; +} + +label { + display: block; + margin-bottom: 6px; + font-weight: 500; + color: #495057; +} + +input[type="url"], +input[type="text"] { + width: 100%; + padding: 8px 12px; + border: 1px solid #ced4da; + border-radius: 4px; + font-size: 14px; + transition: border-color 0.15s ease-in-out; +} + +input[type="url"]:focus, +input[type="text"]:focus { + outline: none; + border-color: #4CAF50; + box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.1); +} + +small { + display: block; + margin-top: 4px; + color: #6c757d; + font-size: 12px; +} + +.btn { + width: 100%; + padding: 10px 16px; + border: none; + border-radius: 4px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.15s ease-in-out; +} + +.btn-primary { + background-color: #4CAF50; + color: white; + margin-bottom: 8px; +} + +.btn-primary:hover { + background-color: #45a049; +} + +.btn-primary:active { + background-color: #3d8b40; +} + +.btn-primary:disabled { + background-color: #95c997; + cursor: not-allowed; +} + +.btn-secondary { + background-color: #6c757d; + color: white; +} + +.btn-secondary:hover { + background-color: #5a6268; +} + +.info-box { + background-color: #e7f3ff; + border: 1px solid #b3d9ff; + border-radius: 4px; + padding: 12px; + margin-bottom: 16px; +} + +.info-box p { + margin-bottom: 4px; +} + +.info-box strong { + color: #0056b3; +} + +.url-display { + word-break: break-all; + font-family: 'Monaco', 'Courier New', monospace; + font-size: 12px; + color: #495057; +} + +#status-message { + padding: 12px; + border-radius: 4px; + margin-top: 12px; + font-size: 13px; +} + +#status-message.success { + background-color: #d4edda; + border: 1px solid #c3e6cb; + color: #155724; +} + +#status-message.error { + background-color: #f8d7da; + border: 1px solid #f5c6cb; + color: #721c24; +} + +#status-message.info { + background-color: #d1ecf1; + border: 1px solid #bee5eb; + color: #0c5460; +} + +.loading { + position: relative; +} + +.loading::after { + content: ""; + position: absolute; + width: 16px; + height: 16px; + top: 50%; + left: 50%; + margin-top: -8px; + margin-left: -8px; + border: 2px solid #f3f3f3; + border-top: 2px solid #4CAF50; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} diff --git a/browser-extension/popup/popup.html b/browser-extension/popup/popup.html new file mode 100644 index 00000000..0ee8885a --- /dev/null +++ b/browser-extension/popup/popup.html @@ -0,0 +1,51 @@ + + + + + + DocuElevate + + + +
+
+ +

DocuElevate

+
+ +
+

Configuration

+
+ + +
+
+ + + Required if authentication is enabled +
+ +
+ + + + +
+ + + + diff --git a/browser-extension/popup/popup.js b/browser-extension/popup/popup.js new file mode 100644 index 00000000..8c7ae997 --- /dev/null +++ b/browser-extension/popup/popup.js @@ -0,0 +1,174 @@ +// Popup script for DocuElevate browser extension + +// DOM elements +const configSection = document.getElementById('config-section'); +const sendSection = document.getElementById('send-section'); +const statusSection = document.getElementById('status-section'); +const statusMessage = document.getElementById('status-message'); + +const serverUrlInput = document.getElementById('server-url'); +const sessionCookieInput = document.getElementById('session-cookie'); +const filenameInput = document.getElementById('filename'); +const currentUrlDisplay = document.getElementById('current-url'); + +const saveConfigBtn = document.getElementById('save-config'); +const sendFileBtn = document.getElementById('send-file'); +const showConfigBtn = document.getElementById('show-config'); + +// Load configuration and current tab URL on popup open +document.addEventListener('DOMContentLoaded', async () => { + // Load saved configuration + const config = await loadConfig(); + + if (config.serverUrl) { + serverUrlInput.value = config.serverUrl; + } + + if (config.sessionCookie) { + sessionCookieInput.value = config.sessionCookie; + } + + // Get current tab URL + const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); + const currentUrl = tabs[0]?.url || ''; + currentUrlDisplay.textContent = currentUrl; + + // Show appropriate section + if (config.serverUrl) { + showSendSection(); + } else { + showConfigSection(); + } +}); + +// Save configuration +saveConfigBtn.addEventListener('click', async () => { + const serverUrl = serverUrlInput.value.trim(); + + if (!serverUrl) { + showStatus('Please enter a server URL', 'error'); + return; + } + + // Validate URL format + try { + new URL(serverUrl); + } catch (e) { + showStatus('Invalid server URL format', 'error'); + return; + } + + const config = { + serverUrl: serverUrl, + sessionCookie: sessionCookieInput.value.trim() + }; + + await saveConfig(config); + showStatus('Configuration saved successfully!', 'success'); + + setTimeout(() => { + showSendSection(); + }, 1000); +}); + +// Send file to DocuElevate +sendFileBtn.addEventListener('click', async () => { + const config = await loadConfig(); + const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); + const currentUrl = tabs[0]?.url || ''; + + if (!currentUrl) { + showStatus('No URL found in current tab', 'error'); + return; + } + + // Disable button and show loading + sendFileBtn.disabled = true; + sendFileBtn.classList.add('loading'); + showStatus('Sending file to DocuElevate...', 'info'); + + try { + const payload = { + url: currentUrl, + filename: filenameInput.value.trim() || null + }; + + const headers = { + 'Content-Type': 'application/json' + }; + + // Add session cookie if provided + if (config.sessionCookie) { + headers['Cookie'] = config.sessionCookie; + } + + const response = await fetch(`${config.serverUrl}/api/process-url`, { + method: 'POST', + headers: headers, + body: JSON.stringify(payload), + credentials: 'include' + }); + + const result = await response.json(); + + if (response.ok) { + showStatus( + `✓ File sent successfully! Task ID: ${result.task_id}\nFilename: ${result.filename}`, + 'success' + ); + } else { + showStatus( + `Error: ${result.detail || 'Failed to send file'}`, + 'error' + ); + } + } catch (error) { + showStatus( + `Error: ${error.message || 'Failed to connect to DocuElevate server'}`, + 'error' + ); + } finally { + sendFileBtn.disabled = false; + sendFileBtn.classList.remove('loading'); + } +}); + +// Show configuration section +showConfigBtn.addEventListener('click', () => { + showConfigSection(); +}); + +// Utility functions +function showConfigSection() { + configSection.classList.remove('hidden'); + sendSection.classList.add('hidden'); + statusSection.classList.add('hidden'); +} + +function showSendSection() { + configSection.classList.add('hidden'); + sendSection.classList.remove('hidden'); + statusSection.classList.add('hidden'); +} + +function showStatus(message, type) { + statusMessage.textContent = message; + statusMessage.className = type; + statusSection.classList.remove('hidden'); +} + +async function loadConfig() { + return new Promise((resolve) => { + chrome.storage.sync.get(['serverUrl', 'sessionCookie'], (result) => { + resolve(result); + }); + }); +} + +async function saveConfig(config) { + return new Promise((resolve) => { + chrome.storage.sync.set(config, () => { + resolve(); + }); + }); +} diff --git a/browser-extension/scripts/background.js b/browser-extension/scripts/background.js new file mode 100644 index 00000000..90f90eaa --- /dev/null +++ b/browser-extension/scripts/background.js @@ -0,0 +1,113 @@ +// Background service worker for DocuElevate browser extension + +// Listen for installation +chrome.runtime.onInstalled.addListener((details) => { + if (details.reason === 'install') { + console.log('DocuElevate extension installed'); + // Open options page on first install + chrome.tabs.create({ + url: chrome.runtime.getURL('popup/popup.html') + }); + } else if (details.reason === 'update') { + console.log('DocuElevate extension updated'); + } +}); + +// Listen for messages from content script or popup +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (message.type === 'SEND_URL') { + handleSendUrl(message.data) + .then(result => sendResponse({ success: true, data: result })) + .catch(error => sendResponse({ success: false, error: error.message })); + return true; // Keep channel open for async response + } +}); + +// Handle sending URL to DocuElevate +async function handleSendUrl(data) { + const { url, filename, serverUrl, sessionCookie } = data; + + if (!url || !serverUrl) { + throw new Error('URL and server URL are required'); + } + + const headers = { + 'Content-Type': 'application/json' + }; + + if (sessionCookie) { + headers['Cookie'] = sessionCookie; + } + + const payload = { + url: url, + filename: filename || null + }; + + const response = await fetch(`${serverUrl}/api/process-url`, { + method: 'POST', + headers: headers, + body: JSON.stringify(payload), + credentials: 'include' + }); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({ detail: 'Unknown error' })); + throw new Error(errorData.detail || `HTTP ${response.status}`); + } + + return await response.json(); +} + +// Add context menu item for sending URLs +chrome.runtime.onInstalled.addListener(() => { + chrome.contextMenus.create({ + id: 'send-to-docuelevate', + title: 'Send to DocuElevate', + contexts: ['link', 'page'] + }); +}); + +// Handle context menu clicks +chrome.contextMenus.onClicked.addListener(async (info, tab) => { + if (info.menuItemId === 'send-to-docuelevate') { + // Get the URL to send (link URL or page URL) + const targetUrl = info.linkUrl || info.pageUrl; + + // Load configuration + const config = await new Promise((resolve) => { + chrome.storage.sync.get(['serverUrl', 'sessionCookie'], resolve); + }); + + if (!config.serverUrl) { + // Open popup to configure + chrome.action.openPopup(); + return; + } + + // Send the URL + try { + const result = await handleSendUrl({ + url: targetUrl, + serverUrl: config.serverUrl, + sessionCookie: config.sessionCookie + }); + + // Show success notification + chrome.notifications.create({ + type: 'basic', + iconUrl: 'icons/icon48.png', + title: 'DocuElevate', + message: `File sent successfully! Task ID: ${result.task_id}` + }); + } catch (error) { + // Show error notification + chrome.notifications.create({ + type: 'basic', + iconUrl: 'icons/icon48.png', + title: 'DocuElevate Error', + message: `Failed to send file: ${error.message}` + }); + } + } +}); diff --git a/browser-extension/scripts/content.js b/browser-extension/scripts/content.js new file mode 100644 index 00000000..464232e6 --- /dev/null +++ b/browser-extension/scripts/content.js @@ -0,0 +1,33 @@ +// Content script for DocuElevate browser extension + +// This script runs on all web pages to detect file URLs +// and enable communication between page content and the extension + +// Listen for messages from the popup +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (message.type === 'GET_PAGE_INFO') { + // Return information about the current page + const pageInfo = { + url: window.location.href, + title: document.title + }; + sendResponse(pageInfo); + } +}); + +// Detect if current page is a direct file link +function isDirectFileUrl(url) { + const fileExtensions = [ + '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', + '.txt', '.csv', '.rtf', '.jpg', '.jpeg', '.png', '.gif', + '.bmp', '.tiff', '.webp', '.svg' + ]; + + const urlLower = url.toLowerCase(); + return fileExtensions.some(ext => urlLower.endsWith(ext)); +} + +// Add visual indicator for file pages (optional enhancement) +if (isDirectFileUrl(window.location.href)) { + console.log('DocuElevate: Direct file URL detected'); +} diff --git a/docs/API.md b/docs/API.md index 6eeead7a..44042c56 100644 --- a/docs/API.md +++ b/docs/API.md @@ -99,6 +99,106 @@ curl -X GET "http:///api/files" \ #### Upload from Computer +Upload a file from your computer to DocuElevate for processing. + +**Endpoint**: `POST /api/upload` + +**Request**: +```bash +curl -X POST "http:///api/upload" \ + -H "Authorization: Bearer " \ + -F "file=@/path/to/document.pdf" +``` + +**Response (201 Created)**: +```json +{ + "task_id": "abc-123-def", + "status": "queued", + "message": "File uploaded and queued for processing", + "filename": "document.pdf" +} +``` + +#### Upload from URL + +Download and process a file from a URL. This endpoint is used by the browser extension. + +**Endpoint**: `POST /api/process-url` + +**Security Features**: +- SSRF protection (blocks private IPs, localhost, cloud metadata endpoints) +- File type validation (only supported document/image types) +- File size limits (enforces maximum upload size) +- Timeout protection (prevents hanging on slow/malicious servers) + +**Request**: +```bash +curl -X POST "http:///api/process-url" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "url": "https://example.com/document.pdf", + "filename": "custom-name.pdf" + }' +``` + +**Request Body**: +```json +{ + "url": "https://example.com/document.pdf", + "filename": "optional-custom-name.pdf" +} +``` + +**Response (200 OK)**: +```json +{ + "task_id": "abc-123-def", + "status": "queued", + "message": "File downloaded from URL and queued for processing", + "filename": "document.pdf", + "size": 1048576 +} +``` + +**Error Responses**: + +```json +// 400 Bad Request - Invalid URL or unsupported file type +{ + "detail": "Unsupported file type: text/html. Supported types: PDF, Office documents, images, plain text" +} + +// 400 Bad Request - Private IP (SSRF protection) +{ + "detail": "Access to private/internal IP addresses is not allowed for security reasons" +} + +// 408 Request Timeout +{ + "detail": "Request timeout: server took too long to respond" +} + +// 413 Payload Too Large +{ + "detail": "File too large: 2097152 bytes (max 1048576 bytes)" +} + +// 502 Bad Gateway +{ + "detail": "Failed to connect to URL: Connection refused" +} +``` + +**Usage with Browser Extension**: + +The DocuElevate browser extension uses this endpoint to send files directly from your browser. See the [Browser Extension Guide](BrowserExtension.md) for installation and usage instructions. + +**Supported File Types**: +- Documents: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT, CSV, RTF +- Images: JPG, PNG, GIF, BMP, TIFF, WebP, SVG + **POST** `/api/ui-upload` Upload one or more files from your computer for processing. diff --git a/docs/BrowserExtension.md b/docs/BrowserExtension.md new file mode 100644 index 00000000..bca6d1eb --- /dev/null +++ b/docs/BrowserExtension.md @@ -0,0 +1,324 @@ +# Browser Extension Guide + +The DocuElevate Browser Extension enables users to send files from their web browser directly to DocuElevate for processing. + +## Overview + +The browser extension provides a seamless way to process files without manually downloading them first. Users can send file URLs with a single click, and DocuElevate will download and process the files automatically. + +## Features + +### Core Functionality + +- **One-Click File Sending**: Send file URLs from the browser to DocuElevate +- **Context Menu Integration**: Right-click on links or pages to send them +- **Popup Interface**: Simple configuration and file submission UI +- **Status Notifications**: Immediate feedback on submission success or failure + +### Security Features + +- **Minimal Permissions**: Only requests necessary browser permissions +- **Secure Storage**: Configuration stored locally in browser extension storage +- **Direct Communication**: All requests go directly to your DocuElevate server +- **Session-Based Auth**: Supports DocuElevate authentication via session cookies + +### Cross-Browser Support + +The extension is compatible with: +- Google Chrome +- Microsoft Edge +- Chromium-based browsers (Brave, Opera, etc.) +- Mozilla Firefox (with minor adjustments) + +## Installation + +### For End Users + +See the [Browser Extension README](../browser-extension/README.md) for detailed installation instructions. + +Quick steps: +1. Load the extension from the `browser-extension` folder +2. Configure your DocuElevate server URL +3. Optionally add authentication (session cookie) +4. Start sending files! + +### For Administrators + +#### Prerequisites + +- DocuElevate server running with URL upload API enabled +- Server accessible from users' browsers (not blocked by firewall/CORS) +- Optional: Authentication configured if required + +#### Deployment Options + +**Option 1: Direct Distribution** +- Share the `browser-extension` folder with users +- Users load it as an unpacked extension + +**Option 2: Internal Extension Store** +- Package the extension as a .zip file +- Distribute via internal Chrome Web Store or Firefox Add-ons for Enterprise + +**Option 3: Public Store** (requires additional steps) +- Submit to Chrome Web Store +- Submit to Firefox Add-ons + +## Configuration + +### Extension Settings + +Users need to configure two settings: + +1. **DocuElevate Server URL** (required) + - Format: `https://docuelevate.example.com` + - Must be accessible from user's browser + - Should not include trailing slashes or API paths + +2. **Session Cookie** (optional, if auth enabled) + - Format: `session=cookie_value_here` + - Obtained by logging into DocuElevate and copying session cookie + - Expires when the session expires (users need to update it) + +### Server Configuration + +No server-side configuration is required. The extension uses the existing URL upload API endpoint: + +``` +POST /api/process-url +``` + +Ensure this endpoint is: +- Accessible from users' browsers +- Not blocked by CORS policies (if different domain) +- Properly secured with authentication if needed + +## Usage + +### Sending Files via Popup + +1. Click the DocuElevate extension icon +2. The current page URL is displayed +3. Optionally enter a custom filename +4. Click "Send to DocuElevate" +5. Status message shows success or error + +### Sending Files via Context Menu + +1. Right-click on any link or the current page +2. Select "Send to DocuElevate" +3. A notification appears with the result + +### Supported URLs + +The extension can send any URL, but DocuElevate will only process: + +**Document URLs**: +- PDFs: `https://example.com/document.pdf` +- Office: `https://example.com/report.docx` +- Spreadsheets: `https://example.com/data.xlsx` +- Text files: `https://example.com/notes.txt` + +**Image URLs**: +- `https://example.com/image.jpg` +- `https://example.com/scan.png` +- `https://example.com/diagram.svg` + +## How It Works + +### Architecture + +``` +┌─────────────┐ ┌──────────────────┐ ┌──────────────┐ +│ Browser │ │ Browser Ext. │ │ DocuElevate │ +│ Tab │────────▶│ (popup.js) │────────▶│ Server │ +│ │ URL │ │ API │ │ +└─────────────┘ └──────────────────┘ Request └──────────────┘ + │ + │ Stores config in + ▼ + ┌──────────────────┐ + │ Browser Storage │ + │ (chrome.storage) │ + └──────────────────┘ +``` + +### Data Flow + +1. **User initiates send**: Via popup or context menu +2. **Extension gets current URL**: From active tab +3. **Extension loads config**: Server URL and session cookie from storage +4. **API request sent**: POST to `/api/process-url` with URL and optional filename +5. **DocuElevate processes**: + - Downloads file from URL + - Validates file type and size + - Enqueues for processing (OCR, metadata extraction) +6. **Response returned**: Task ID and status +7. **User notified**: Success or error message displayed + +### Security Flow + +The extension implements several security measures: + +1. **No direct file access**: Extension only sends URLs, not file contents +2. **User-controlled config**: Server URL and auth stored per-user +3. **HTTPS recommended**: Encourages secure communication +4. **Minimal permissions**: Only requests necessary browser APIs +5. **Server-side validation**: DocuElevate validates all URLs (SSRF protection) + +## Technical Details + +### Extension Structure + +**manifest.json**: Extension metadata and configuration +- Manifest v3 format (latest standard) +- Minimal permissions requested +- Compatible with Chrome, Edge, and Firefox + +**popup/**: User interface files +- `popup.html`: Extension popup interface +- `popup.css`: Styling with modern UI design +- `popup.js`: Configuration and file sending logic + +**scripts/**: Background functionality +- `background.js`: Service worker for context menu and notifications +- `content.js`: Content script for page interaction (minimal) + +**icons/**: Extension icons in multiple sizes + +### API Integration + +The extension communicates with DocuElevate via the URL upload API: + +**Request Format**: +```javascript +POST /api/process-url +Content-Type: application/json +Cookie: session= // if auth enabled + +{ + "url": "https://example.com/file.pdf", + "filename": "optional-custom-name.pdf" // optional +} +``` + +**Response Format**: +```javascript +{ + "task_id": "abc-123-def", + "status": "queued", + "message": "File downloaded from URL and queued for processing", + "filename": "file.pdf", + "size": 1024 +} +``` + +**Error Response**: +```javascript +{ + "detail": "Error message explaining what went wrong" +} +``` + +### Browser Permissions + +The extension requests these permissions: + +- **activeTab**: Get URL of current tab +- **storage**: Save configuration (server URL, session cookie) +- **contextMenus**: Add "Send to DocuElevate" to right-click menu +- **notifications**: Show success/error notifications + +All permissions are used only for stated purposes. No data is collected or transmitted to third parties. + +## Troubleshooting + +### Common Issues + +**"Failed to connect to DocuElevate server"** +- Check server URL is correct and accessible +- Verify server is running +- Check firewall/network settings +- Test API directly: `curl https://your-server/api/process-url` + +**"Authentication required" (401 error)** +- User needs to add session cookie +- Session may have expired (log in again) +- Check AUTH_ENABLED setting in DocuElevate + +**"Unsupported file type" (400 error)** +- URL must point to a supported file type +- Check file extension and Content-Type header +- See DocuElevate supported file types + +**"File too large" (413 error)** +- File exceeds MAX_UPLOAD_SIZE setting +- Contact admin to increase limit or use smaller file + +**Extension not appearing** +- Ensure developer mode is enabled +- Reload the extension +- Check browser console for errors + +### Debug Mode + +To debug the extension: + +1. **Open Extension Console**: + - Chrome: Right-click extension icon → "Inspect popup" + - Or go to `chrome://extensions/` → Click "Inspect views: service worker" + +2. **Check Console Logs**: + - Look for error messages + - Verify API requests are being sent + - Check response status codes + +3. **Test API Directly**: + ```bash + curl -X POST https://your-server/api/process-url \ + -H "Content-Type: application/json" \ + -H "Cookie: session=your_session" \ + -d '{"url": "https://example.com/test.pdf"}' + ``` + +## Best Practices + +### For Users + +- Keep your session cookie secure and don't share it +- Verify the DocuElevate server URL is correct before saving +- Only send files from trusted sources +- Check file size limits before sending large files + +### For Administrators + +- Configure HTTPS for production servers +- Set appropriate MAX_UPLOAD_SIZE limits +- Enable authentication for security +- Monitor API usage and set rate limits if needed +- Provide clear documentation to users on getting session cookies + +## Future Enhancements + +Possible future improvements: + +- OAuth2 authentication instead of session cookies +- File preview before sending +- Batch processing multiple URLs +- Progress indication for large files +- History of sent files +- Custom processing options (OCR language, metadata fields, etc.) + +## Related Documentation + +- [DocuElevate API Documentation](./API.md) +- [DocuElevate Configuration Guide](./ConfigurationGuide.md) +- [DocuElevate Security Guide](../SECURITY_AUDIT.md) +- [Browser Extension README](../browser-extension/README.md) + +## Support + +For issues or questions: +- Check the troubleshooting section above +- Review the [main documentation](./README.md) +- Open an issue on [GitHub](https://github.com/christianlouis/DocuElevate/issues)