feat(integrations): add Paperless-ngx external attachment integration#1491
feat(integrations): add Paperless-ngx external attachment integration#1491szaiser wants to merge 1 commit into
Conversation
Link Paperless-ngx documents to Homebox inventory items via drag-and-drop
or manual URL entry. Documents are stored as lightweight external links
(no file copy) and enriched on-demand via the existing generic proxy.
## What changes
### Backend
- New handler: `GET /v1/integrations/{name}/proxy` — generic authenticated
reverse-proxy that forwards requests to any configured integration service.
Validates the integration name (regex), the path parameter (must start with
`/`, no `://`), and forwards `Authorization: Token {token}`.
- `POST /v1/entities/{id}/attachments/external` handler now accepts
`source_type=paperless` (or any future integration registered in the repo).
- `MimeTypePaperlessDocument = "paperless/document"` constant and
`MimeTypeForSourceType()` helper added to the attachment repo.
### Frontend
- `frontend/lib/integration-adapters.ts` — registry of `ServiceAdapter`
objects (name, MIME type, settings keys, ID extractor, title builder). Adding
a new integration only requires a new entry here.
- `frontend/stores/integration-cache.ts` — Pinia store that holds per-service
URL state and enriched-data/fetch-state caches; drives reactive card
promotion/demotion when the user saves or clears a service URL.
- `frontend/components/Item/AttachmentsList.vue` — Paperless document card
with thumbnail, title, correspondent, document type, colour-tagged tags, page
count, created date, open-in-Paperless button and unreachable/error badge.
Attachments stored as `link/url` are transparently promoted to the rich
Paperless card at render time when the service URL is configured.
- Drag-and-drop Paperless URL detection in the item edit page.
- Profile settings: Paperless URL + API token fields with live store update.
- `frontend/composables/preferences-utils.ts` — extracted shared preference
helpers (no functional change, pure refactor).
- 25 unit tests in `integration-adapters.test.ts` covering ID extraction,
service detection, URL classification, adapter lookup and registry shape.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Closing as #1492 seems to be the PR that actually matters. |
What type of PR is this?
What this PR does / why we need it:
Extends the external attachment infrastructure from #1481 with a full Paperless-ngx integration. Users can link Paperless documents to Homebox inventory items — no file copy, just a lightweight external reference — and get rich metadata directly in the attachment list.
Changes by file
Backend
backend/app/api/handlers/v1/v1_ctrl_integration_proxy.go(new) — generic authenticated reverse-proxyGET /v1/integrations/{name}/proxy?path={relPath}. Validates the integration name (regex^[a-z][a-z0-9_-]{0,31}$— prevents traversal), validates the path starts with/and contains no://, then proxies the request to the service's configured base URL withAuthorization: Token {token}. One handler serves all current and future integrations.backend/app/api/routes.go— wire the new proxy handler.backend/internal/data/repo/repo_item_attachments.go— addMimeTypePaperlessDocument = "paperless/document"constant and register it inMimeTypeForSourceType()/externalLinkMimeTypes.backend/internal/core/services/service_items_attachments_external_test.go— extend existing service tests to cover Paperless MIME type registration.backend/internal/data/repo/repo_item_attachments_test.go— extend existing repo tests.Frontend
frontend/lib/integration-adapters.ts(new) —ServiceAdapterinterface andSERVICE_ADAPTERSregistry (name, MIME type, settings keys, ID extractor, title builder). Adding a future integration only requires a new entry here; all detection, classification and hydration are registry-driven.frontend/lib/integration-adapters.test.ts(new) — 25 Vitest unit tests coveringextractPaperlessDocId,detectServiceFromUrl,classifyDroppedUrl,getAdapter,getAdapterByMimeType,buildTitleand registry shape.frontend/stores/integration-cache.ts(new) — Pinia store holding per-service URL state and enriched-data / fetch-state caches. Drives reactive card promotion/demotion when the user saves or clears a service URL in Profile settings while the attachment list is mounted.frontend/components/Item/AttachmentsList.vue— Paperless document card with: thumbnail, title (from Paperless API), correspondent, document type, colour-coded tags, page count, created date, open-in-Paperless button, and an amber ⚠ unreachable/error badge with tooltip.link/urlattachments whose URL matches the configured Paperless base URL are transparently promoted to the rich card at render time (and demoted back if the URL is cleared).frontend/pages/item/[id]/index/edit.vue— drag-and-drop Paperless URL detection: detects a dropped Paperless document URL, extracts the document ID and callsPOST /v1/entities/{id}/attachments/external.frontend/pages/profile.vue— Paperless URL + API token fields in the Integrations settings section; saves to user settings and immediately pushes the new URL into the shared store.frontend/composables/preferences-utils.ts(new) — shared preference helpers extracted fromuse-preferences.ts(no functional change, pure refactor to avoid circular imports).frontend/composables/use-preferences.test.ts(new) — tests for the extracted composable.frontend/locales/en.json— add Paperless i18n keys (paperless_settings,paperless_url,paperless_url_placeholder,paperless_token,paperless_token_placeholder,integrations_sub).Special notes for your reviewer:
v1_ctrl_integration_proxy.go) is intentionally Paperless-unaware. It reads{name}_urland{name}_tokenfrom user settings and forwards withAuthorization: Token {token}. Adding a future integration (e.g. Docspell) requires only a newSERVICE_ADAPTERSentry on the frontend and one line inMimeTypeForSourceType()on the backend.integration-adapters.ts) is the single source of truth: drop detection, URL classification and card hydration all iterateSERVICE_ADAPTERS— no service-specificif/elsechains.onBeforeUnmountto avoid memory leaks.Testing
frontend/lib/integration-adapters.test.ts— 25 tests, all green (npx vitest run lib/integration-adapters.test.ts).