Merge branch 'main' into dev
14
docs/api.md
@ -14,14 +14,15 @@ The API provides 7 main endpoints:
|
|||||||
- `/api/document_types/`: Full CRUD support.
|
- `/api/document_types/`: Full CRUD support.
|
||||||
- `/api/logs/`: Read-Only.
|
- `/api/logs/`: Read-Only.
|
||||||
- `/api/tags/`: Full CRUD support.
|
- `/api/tags/`: Full CRUD support.
|
||||||
|
- `/api/tasks/`: Read-only.
|
||||||
- `/api/mail_accounts/`: Full CRUD support.
|
- `/api/mail_accounts/`: Full CRUD support.
|
||||||
- `/api/mail_rules/`: Full CRUD support.
|
- `/api/mail_rules/`: Full CRUD support.
|
||||||
- `/api/users/`: Full CRUD support.
|
- `/api/users/`: Full CRUD support.
|
||||||
- `/api/groups/`: Full CRUD support.
|
- `/api/groups/`: Full CRUD support.
|
||||||
|
|
||||||
All of these endpoints except for the logging endpoint allow you to
|
All of these endpoints except for the logging endpoint allow you to
|
||||||
fetch, edit and delete individual objects by appending their primary key
|
fetch (and edit and delete where appropriate) individual objects by
|
||||||
to the path, for example `/api/documents/454/`.
|
appending their primary key to the path, e.g. `/api/documents/454/`.
|
||||||
|
|
||||||
The objects served by the document endpoint contain the following
|
The objects served by the document endpoint contain the following
|
||||||
fields:
|
fields:
|
||||||
@ -261,10 +262,11 @@ The endpoint supports the following optional form fields:
|
|||||||
|
|
||||||
The endpoint will immediately return HTTP 200 if the document consumption
|
The endpoint will immediately return HTTP 200 if the document consumption
|
||||||
process was started successfully, with the UUID of the consumption task
|
process was started successfully, with the UUID of the consumption task
|
||||||
as the data. No additional status information about
|
as the data. No additional status information about the consumption process
|
||||||
the consumption process itself is available immediately, since that happens in a
|
itself is available immediately, since that happens in a different process.
|
||||||
different process. Querying the tasks endpoint with the returned UUID will
|
However, querying the tasks endpoint with the returned UUID e.g.
|
||||||
provide information on the state of the consumption.
|
`/api/tasks/?task_id={uuid}` will provide information on the state of the
|
||||||
|
consumption including the ID of a created document if consumption succeeded.
|
||||||
|
|
||||||
## API Versioning
|
## API Versioning
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 661 KiB After Width: | Height: | Size: 740 KiB |
Before Width: | Height: | Size: 457 KiB After Width: | Height: | Size: 383 KiB |
Before Width: | Height: | Size: 890 KiB After Width: | Height: | Size: 704 KiB |
Before Width: | Height: | Size: 462 KiB After Width: | Height: | Size: 474 KiB |
Before Width: | Height: | Size: 608 KiB After Width: | Height: | Size: 616 KiB |
Before Width: | Height: | Size: 698 KiB After Width: | Height: | Size: 708 KiB |
Before Width: | Height: | Size: 706 KiB After Width: | Height: | Size: 705 KiB |
Before Width: | Height: | Size: 480 KiB After Width: | Height: | Size: 480 KiB |
Before Width: | Height: | Size: 680 KiB After Width: | Height: | Size: 689 KiB |
Before Width: | Height: | Size: 686 KiB After Width: | Height: | Size: 685 KiB |
Before Width: | Height: | Size: 848 KiB After Width: | Height: | Size: 859 KiB |
Before Width: | Height: | Size: 703 KiB After Width: | Height: | Size: 706 KiB |
Before Width: | Height: | Size: 388 KiB After Width: | Height: | Size: 393 KiB |
Before Width: | Height: | Size: 517 KiB After Width: | Height: | Size: 516 KiB |
@ -1,5 +1,188 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## paperless-ngx 1.14.0
|
||||||
|
|
||||||
|
### Notable Changes
|
||||||
|
|
||||||
|
- Feature: multi-user permissions [@shamoon](https://github.com/shamoon) ([#2147](https://github.com/paperless-ngx/paperless-ngx/pull/2147))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Feature: Stronger typing for file consumption [@stumpylog](https://github.com/stumpylog) ([#2744](https://github.com/paperless-ngx/paperless-ngx/pull/2744))
|
||||||
|
- Feature: double-click docs [@shamoon](https://github.com/shamoon) ([#2966](https://github.com/paperless-ngx/paperless-ngx/pull/2966))
|
||||||
|
- feature: Add support for zxing as barcode scanning lib [@margau](https://github.com/margau) ([#2907](https://github.com/paperless-ngx/paperless-ngx/pull/2907))
|
||||||
|
- Feature: Enable images to be released on Quay.io [@stumpylog](https://github.com/stumpylog) ([#2972](https://github.com/paperless-ngx/paperless-ngx/pull/2972))
|
||||||
|
- Feature: test mail account [@shamoon](https://github.com/shamoon) ([#2949](https://github.com/paperless-ngx/paperless-ngx/pull/2949))
|
||||||
|
- Feature: Capture celery and kombu logs to a file [@stumpylog](https://github.com/stumpylog) ([#2954](https://github.com/paperless-ngx/paperless-ngx/pull/2954))
|
||||||
|
- Fix: Resolve Redis connection issues with ACLs [@stumpylog](https://github.com/stumpylog) ([#2939](https://github.com/paperless-ngx/paperless-ngx/pull/2939))
|
||||||
|
- Feature: Allow mail account to use access tokens [@stumpylog](https://github.com/stumpylog) ([#2930](https://github.com/paperless-ngx/paperless-ngx/pull/2930))
|
||||||
|
- Fix: Consumer polling could overwhelm database [@stumpylog](https://github.com/stumpylog) ([#2922](https://github.com/paperless-ngx/paperless-ngx/pull/2922))
|
||||||
|
- Feature: Improved statistics widget [@shamoon](https://github.com/shamoon) ([#2910](https://github.com/paperless-ngx/paperless-ngx/pull/2910))
|
||||||
|
- Enhancement: rename comments to notes and improve notes UI [@shamoon](https://github.com/shamoon) ([#2904](https://github.com/paperless-ngx/paperless-ngx/pull/2904))
|
||||||
|
- Allow psql client certificate authentication [@Ongy](https://github.com/Ongy) ([#2899](https://github.com/paperless-ngx/paperless-ngx/pull/2899))
|
||||||
|
- Enhancement: support filtering multiple correspondents, doctypes \& storage paths [@shamoon](https://github.com/shamoon) ([#2893](https://github.com/paperless-ngx/paperless-ngx/pull/2893))
|
||||||
|
- Feature: Change celery serializer to pickle [@stumpylog](https://github.com/stumpylog) ([#2861](https://github.com/paperless-ngx/paperless-ngx/pull/2861))
|
||||||
|
- Feature: Allow naming to include owner and original name [@stumpylog](https://github.com/stumpylog) ([#2873](https://github.com/paperless-ngx/paperless-ngx/pull/2873))
|
||||||
|
- Feature: Allows filtering email by the TO value(s) as well [@stumpylog](https://github.com/stumpylog) ([#2871](https://github.com/paperless-ngx/paperless-ngx/pull/2871))
|
||||||
|
- Feature: owner-aware unique model name constraint [@shamoon](https://github.com/shamoon) ([#2827](https://github.com/paperless-ngx/paperless-ngx/pull/2827))
|
||||||
|
- Feature/2396 better mail actions [@jonaswinkler](https://github.com/jonaswinkler) ([#2718](https://github.com/paperless-ngx/paperless-ngx/pull/2718))
|
||||||
|
- Feature: Reduce classifier memory usage somewhat during training [@stumpylog](https://github.com/stumpylog) ([#2733](https://github.com/paperless-ngx/paperless-ngx/pull/2733))
|
||||||
|
- Feature: Add PAPERLESS_OCR_SKIP_ARCHIVE_FILE config setting [@bdr99](https://github.com/bdr99) ([#2743](https://github.com/paperless-ngx/paperless-ngx/pull/2743))
|
||||||
|
- Feature: dynamic document counts in dropdowns [@shamoon](https://github.com/shamoon) ([#2704](https://github.com/paperless-ngx/paperless-ngx/pull/2704))
|
||||||
|
- Allow setting the ASN on document upload [@stumpylog](https://github.com/stumpylog) ([#2713](https://github.com/paperless-ngx/paperless-ngx/pull/2713))
|
||||||
|
- Feature: Log failed login attempts [@shamoon](https://github.com/shamoon) ([#2359](https://github.com/paperless-ngx/paperless-ngx/pull/2359))
|
||||||
|
- Feature: Rename documents when storage path format changes [@stumpylog](https://github.com/stumpylog) ([#2696](https://github.com/paperless-ngx/paperless-ngx/pull/2696))
|
||||||
|
- Feature: update error message colors \& show on document failures [@shamoon](https://github.com/shamoon) ([#2689](https://github.com/paperless-ngx/paperless-ngx/pull/2689))
|
||||||
|
- Feature: multi-user permissions [@shamoon](https://github.com/shamoon) ([#2147](https://github.com/paperless-ngx/paperless-ngx/pull/2147))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- Fix: Allow setting additional Django settings for proxies [@stumpylog](https://github.com/stumpylog) ([#3135](https://github.com/paperless-ngx/paperless-ngx/pull/3135))
|
||||||
|
- Fix: Use exclude instead of difference for mariadb [@shamoon](https://github.com/shamoon) ([#2983](https://github.com/paperless-ngx/paperless-ngx/pull/2983))
|
||||||
|
- Fix: permissions display should not show users with inherited permissions \& unable to change owner [@shamoon](https://github.com/shamoon) ([#2818](https://github.com/paperless-ngx/paperless-ngx/pull/2818))
|
||||||
|
- Fix: Resolve Redis connection issues with ACLs [@stumpylog](https://github.com/stumpylog) ([#2939](https://github.com/paperless-ngx/paperless-ngx/pull/2939))
|
||||||
|
- Fix: unable to edit correspondents (in ) [@shamoon](https://github.com/shamoon) ([#2938](https://github.com/paperless-ngx/paperless-ngx/pull/2938))
|
||||||
|
- Fix: Consumer polling could overwhelm database [@stumpylog](https://github.com/stumpylog) ([#2922](https://github.com/paperless-ngx/paperless-ngx/pull/2922))
|
||||||
|
- Fix: Chrome struggles with commas [@stumpylog](https://github.com/stumpylog) ([#2892](https://github.com/paperless-ngx/paperless-ngx/pull/2892))
|
||||||
|
- Fix formatting in Setup documentation page [@igrybkov](https://github.com/igrybkov) ([#2880](https://github.com/paperless-ngx/paperless-ngx/pull/2880))
|
||||||
|
- Fix: logout on change password via frontend [@shamoon](https://github.com/shamoon) ([#2863](https://github.com/paperless-ngx/paperless-ngx/pull/2863))
|
||||||
|
- Fix: give superuser full doc perms [@shamoon](https://github.com/shamoon) ([#2820](https://github.com/paperless-ngx/paperless-ngx/pull/2820))
|
||||||
|
- Fix: Append Gmail labels instead of replacing [@stumpylog](https://github.com/stumpylog) ([#2860](https://github.com/paperless-ngx/paperless-ngx/pull/2860))
|
||||||
|
- Fix: Ensure email date is made aware during action processing [@stumpylog](https://github.com/stumpylog) ([#2837](https://github.com/paperless-ngx/paperless-ngx/pull/2837))
|
||||||
|
- Fix: disable bulk edit dialog buttons during operation [@shamoon](https://github.com/shamoon) ([#2819](https://github.com/paperless-ngx/paperless-ngx/pull/2819))
|
||||||
|
- fix database locked error [@jonaswinkler](https://github.com/jonaswinkler) ([#2808](https://github.com/paperless-ngx/paperless-ngx/pull/2808))
|
||||||
|
- Fix: Disable suggestions for read-only docs [@shamoon](https://github.com/shamoon) ([#2813](https://github.com/paperless-ngx/paperless-ngx/pull/2813))
|
||||||
|
- Update processed mail migration [@shamoon](https://github.com/shamoon) ([#2804](https://github.com/paperless-ngx/paperless-ngx/pull/2804))
|
||||||
|
- Fix: Ensure scratch directory exists before using [@stumpylog](https://github.com/stumpylog) ([#2775](https://github.com/paperless-ngx/paperless-ngx/pull/2775))
|
||||||
|
- Don't submit owner via API on document upload [@jonaswinkler](https://github.com/jonaswinkler) ([#2777](https://github.com/paperless-ngx/paperless-ngx/pull/2777))
|
||||||
|
- Fix: only offer log files that exist [@shamoon](https://github.com/shamoon) ([#2739](https://github.com/paperless-ngx/paperless-ngx/pull/2739))
|
||||||
|
- Fix: permissions editing and initial view issues [@shamoon](https://github.com/shamoon) ([#2717](https://github.com/paperless-ngx/paperless-ngx/pull/2717))
|
||||||
|
- Fix: reset saved view ID on quickFilter [@shamoon](https://github.com/shamoon) ([#2703](https://github.com/paperless-ngx/paperless-ngx/pull/2703))
|
||||||
|
- Fix: bulk edit reset apply button state [@shamoon](https://github.com/shamoon) ([#2701](https://github.com/paperless-ngx/paperless-ngx/pull/2701))
|
||||||
|
- Fix: add missing i18n for mobile preview tab title [@nathanaelhoun](https://github.com/nathanaelhoun) ([#2692](https://github.com/paperless-ngx/paperless-ngx/pull/2692))
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- Whitespace changes, making sure the example is correcly aligned [@denilsonsa](https://github.com/denilsonsa) ([#3089](https://github.com/paperless-ngx/paperless-ngx/pull/3089))
|
||||||
|
- Docs: Include additional information about barcodes [@stumpylog](https://github.com/stumpylog) ([#2889](https://github.com/paperless-ngx/paperless-ngx/pull/2889))
|
||||||
|
- Fix formatting in Setup documentation page [@igrybkov](https://github.com/igrybkov) ([#2880](https://github.com/paperless-ngx/paperless-ngx/pull/2880))
|
||||||
|
- [Documentation] Update docker-compose steps to support podman [@white-gecko](https://github.com/white-gecko) ([#2855](https://github.com/paperless-ngx/paperless-ngx/pull/2855))
|
||||||
|
- docs: better language code help [@tooomm](https://github.com/tooomm) ([#2830](https://github.com/paperless-ngx/paperless-ngx/pull/2830))
|
||||||
|
- Feature: Add an option to disable matching [@bdr99](https://github.com/bdr99) ([#2727](https://github.com/paperless-ngx/paperless-ngx/pull/2727))
|
||||||
|
- Docs: Remove outdated PAPERLESS_WORKER_RETRY [@shamoon](https://github.com/shamoon) ([#2694](https://github.com/paperless-ngx/paperless-ngx/pull/2694))
|
||||||
|
- Fix: add missing i18n for mobile preview tab title [@nathanaelhoun](https://github.com/nathanaelhoun) ([#2692](https://github.com/paperless-ngx/paperless-ngx/pull/2692))
|
||||||
|
|
||||||
|
### Maintenance
|
||||||
|
|
||||||
|
- Chore: Configure ruff as the primary linter for Python [@stumpylog](https://github.com/stumpylog) ([#2988](https://github.com/paperless-ngx/paperless-ngx/pull/2988))
|
||||||
|
- Feature: Enable images to be released on Quay.io [@stumpylog](https://github.com/stumpylog) ([#2972](https://github.com/paperless-ngx/paperless-ngx/pull/2972))
|
||||||
|
- Chore: Updates locked pipenv to latest version [@stumpylog](https://github.com/stumpylog) ([#2943](https://github.com/paperless-ngx/paperless-ngx/pull/2943))
|
||||||
|
- Chore: Properly collapse section in releases [@tooomm](https://github.com/tooomm) ([#2838](https://github.com/paperless-ngx/paperless-ngx/pull/2838))
|
||||||
|
- Chore: Don't include changelog PR for different releases [@tooomm](https://github.com/tooomm) ([#2832](https://github.com/paperless-ngx/paperless-ngx/pull/2832))
|
||||||
|
- Chore: Speed up frontend CI testing [@stumpylog](https://github.com/stumpylog) ([#2796](https://github.com/paperless-ngx/paperless-ngx/pull/2796))
|
||||||
|
- Bump leonsteinhaeuser/project-beta-automations from 2.0.1 to 2.1.0 [@dependabot](https://github.com/dependabot) ([#2789](https://github.com/paperless-ngx/paperless-ngx/pull/2789))
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>15 changes</summary>
|
||||||
|
|
||||||
|
- Bump ng2-pdf-viewer from 9.1.4 to 9.1.5 in /src-ui [@dependabot](https://github.com/dependabot) ([#3109](https://github.com/paperless-ngx/paperless-ngx/pull/3109))
|
||||||
|
- Grouped bump angular packages from 15.2.6 to 15.2.7 in /src-ui [@dependabot](https://github.com/dependabot) ([#3108](https://github.com/paperless-ngx/paperless-ngx/pull/3108))
|
||||||
|
- Bump typescript from 4.8.4 to 4.9.5 in /src-ui [@dependabot](https://github.com/dependabot) ([#3071](https://github.com/paperless-ngx/paperless-ngx/pull/3071))
|
||||||
|
- Bulk Bump npm packages 04.23 [@dependabot](https://github.com/dependabot) ([#3068](https://github.com/paperless-ngx/paperless-ngx/pull/3068))
|
||||||
|
- Bump wait-on from 6.0.1 to 7.0.1 in /src-ui [@dependabot](https://github.com/dependabot) ([#2990](https://github.com/paperless-ngx/paperless-ngx/pull/2990))
|
||||||
|
- Bulk bump angular packages to 15.2.5 in /src-ui [@dependabot](https://github.com/dependabot) ([#2991](https://github.com/paperless-ngx/paperless-ngx/pull/2991))
|
||||||
|
- Bump [@<!---->types/node from 18.11.18 to 18.15.11 in /src-ui @dependabot](https://github.com/<!---->types/node from 18.11.18 to 18.15.11 in /src-ui @dependabot) ([#2993](https://github.com/paperless-ngx/paperless-ngx/pull/2993))
|
||||||
|
- Bump [@<!---->ng-select/ng-select from 10.0.3 to 10.0.4 in /src-ui @dependabot](https://github.com/<!---->ng-select/ng-select from 10.0.3 to 10.0.4 in /src-ui @dependabot) ([#2992](https://github.com/paperless-ngx/paperless-ngx/pull/2992))
|
||||||
|
- Bump [@<!---->typescript-eslint/eslint-plugin from 5.50.0 to 5.57.0 in /src-ui @dependabot](https://github.com/<!---->typescript-eslint/eslint-plugin from 5.50.0 to 5.57.0 in /src-ui @dependabot) ([#2989](https://github.com/paperless-ngx/paperless-ngx/pull/2989))
|
||||||
|
- Chore: Update cryptography to latest version [@stumpylog](https://github.com/stumpylog) ([#2891](https://github.com/paperless-ngx/paperless-ngx/pull/2891))
|
||||||
|
- Chore: Update to qpdf 11.3.0 in Docker image [@stumpylog](https://github.com/stumpylog) ([#2862](https://github.com/paperless-ngx/paperless-ngx/pull/2862))
|
||||||
|
- Bump leonsteinhaeuser/project-beta-automations from 2.0.1 to 2.1.0 [@dependabot](https://github.com/dependabot) ([#2789](https://github.com/paperless-ngx/paperless-ngx/pull/2789))
|
||||||
|
- Bump zone.js from 0.11.8 to 0.12.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#2793](https://github.com/paperless-ngx/paperless-ngx/pull/2793))
|
||||||
|
- Bump [@<!---->typescript-eslint/parser from 5.50.0 to 5.54.0 in /src-ui @dependabot](https://github.com/<!---->typescript-eslint/parser from 5.50.0 to 5.54.0 in /src-ui @dependabot) ([#2792](https://github.com/paperless-ngx/paperless-ngx/pull/2792))
|
||||||
|
- Bulk Bump angular packages to 15.2.1 in /src-ui [@dependabot](https://github.com/dependabot) ([#2788](https://github.com/paperless-ngx/paperless-ngx/pull/2788))
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### All App Changes
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>72 changes</summary>
|
||||||
|
|
||||||
|
- Feature: Catalan translation [@shamoon](https://github.com/shamoon) ([#3146](https://github.com/paperless-ngx/paperless-ngx/pull/3146))
|
||||||
|
- Fix: Allow setting additional Django settings for proxies [@stumpylog](https://github.com/stumpylog) ([#3135](https://github.com/paperless-ngx/paperless-ngx/pull/3135))
|
||||||
|
- Fix: Increase mail account password field length [@stumpylog](https://github.com/stumpylog) ([#3134](https://github.com/paperless-ngx/paperless-ngx/pull/3134))
|
||||||
|
- Fix: respect permissions for matching suggestions [@shamoon](https://github.com/shamoon) ([#3103](https://github.com/paperless-ngx/paperless-ngx/pull/3103))
|
||||||
|
- Bump ng2-pdf-viewer from 9.1.4 to 9.1.5 in /src-ui [@dependabot](https://github.com/dependabot) ([#3109](https://github.com/paperless-ngx/paperless-ngx/pull/3109))
|
||||||
|
- Grouped bump angular packages from 15.2.6 to 15.2.7 in /src-ui [@dependabot](https://github.com/dependabot) ([#3108](https://github.com/paperless-ngx/paperless-ngx/pull/3108))
|
||||||
|
- Fix: update PaperlessTask on hard failures [@shamoon](https://github.com/shamoon) ([#3062](https://github.com/paperless-ngx/paperless-ngx/pull/3062))
|
||||||
|
- Bump typescript from 4.8.4 to 4.9.5 in /src-ui [@dependabot](https://github.com/dependabot) ([#3071](https://github.com/paperless-ngx/paperless-ngx/pull/3071))
|
||||||
|
- Bulk Bump npm packages 04.23 [@dependabot](https://github.com/dependabot) ([#3068](https://github.com/paperless-ngx/paperless-ngx/pull/3068))
|
||||||
|
- Fix: Hide UI tour steps if user doesnt have permissions [@shamoon](https://github.com/shamoon) ([#3060](https://github.com/paperless-ngx/paperless-ngx/pull/3060))
|
||||||
|
- Fix: Hide Permissions tab if user cannot view users [@shamoon](https://github.com/shamoon) ([#3061](https://github.com/paperless-ngx/paperless-ngx/pull/3061))
|
||||||
|
- v1.14.0 delete document fixes [@shamoon](https://github.com/shamoon) ([#3020](https://github.com/paperless-ngx/paperless-ngx/pull/3020))
|
||||||
|
- Bump wait-on from 6.0.1 to 7.0.1 in /src-ui [@dependabot](https://github.com/dependabot) ([#2990](https://github.com/paperless-ngx/paperless-ngx/pull/2990))
|
||||||
|
- Fix: inline plaintext docs to enforce styling [@shamoon](https://github.com/shamoon) ([#3013](https://github.com/paperless-ngx/paperless-ngx/pull/3013))
|
||||||
|
- Chore: Configure ruff as the primary linter for Python [@stumpylog](https://github.com/stumpylog) ([#2988](https://github.com/paperless-ngx/paperless-ngx/pull/2988))
|
||||||
|
- Bulk bump angular packages to 15.2.5 in /src-ui [@dependabot](https://github.com/dependabot) ([#2991](https://github.com/paperless-ngx/paperless-ngx/pull/2991))
|
||||||
|
- Bump [@<!---->types/node from 18.11.18 to 18.15.11 in /src-ui @dependabot](https://github.com/<!---->types/node from 18.11.18 to 18.15.11 in /src-ui @dependabot) ([#2993](https://github.com/paperless-ngx/paperless-ngx/pull/2993))
|
||||||
|
- Bump [@<!---->ng-select/ng-select from 10.0.3 to 10.0.4 in /src-ui @dependabot](https://github.com/<!---->ng-select/ng-select from 10.0.3 to 10.0.4 in /src-ui @dependabot) ([#2992](https://github.com/paperless-ngx/paperless-ngx/pull/2992))
|
||||||
|
- Bump [@<!---->typescript-eslint/eslint-plugin from 5.50.0 to 5.57.0 in /src-ui @dependabot](https://github.com/<!---->typescript-eslint/eslint-plugin from 5.50.0 to 5.57.0 in /src-ui @dependabot) ([#2989](https://github.com/paperless-ngx/paperless-ngx/pull/2989))
|
||||||
|
- Feature: Stronger typing for file consumption [@stumpylog](https://github.com/stumpylog) ([#2744](https://github.com/paperless-ngx/paperless-ngx/pull/2744))
|
||||||
|
- Fix: Use exclude instead of difference for mariadb [@shamoon](https://github.com/shamoon) ([#2983](https://github.com/paperless-ngx/paperless-ngx/pull/2983))
|
||||||
|
- Fix: permissions display should not show users with inherited permissions \& unable to change owner [@shamoon](https://github.com/shamoon) ([#2818](https://github.com/paperless-ngx/paperless-ngx/pull/2818))
|
||||||
|
- Feature: double-click docs [@shamoon](https://github.com/shamoon) ([#2966](https://github.com/paperless-ngx/paperless-ngx/pull/2966))
|
||||||
|
- feature: Add support for zxing as barcode scanning lib [@margau](https://github.com/margau) ([#2907](https://github.com/paperless-ngx/paperless-ngx/pull/2907))
|
||||||
|
- Feature: test mail account [@shamoon](https://github.com/shamoon) ([#2949](https://github.com/paperless-ngx/paperless-ngx/pull/2949))
|
||||||
|
- Feature: Capture celery and kombu logs to a file [@stumpylog](https://github.com/stumpylog) ([#2954](https://github.com/paperless-ngx/paperless-ngx/pull/2954))
|
||||||
|
- Fix: Resolve Redis connection issues with ACLs [@stumpylog](https://github.com/stumpylog) ([#2939](https://github.com/paperless-ngx/paperless-ngx/pull/2939))
|
||||||
|
- Feature: Allow mail account to use access tokens [@stumpylog](https://github.com/stumpylog) ([#2930](https://github.com/paperless-ngx/paperless-ngx/pull/2930))
|
||||||
|
- Fix: Consumer polling could overwhelm database [@stumpylog](https://github.com/stumpylog) ([#2922](https://github.com/paperless-ngx/paperless-ngx/pull/2922))
|
||||||
|
- Feature: Improved statistics widget [@shamoon](https://github.com/shamoon) ([#2910](https://github.com/paperless-ngx/paperless-ngx/pull/2910))
|
||||||
|
- Enhancement: rename comments to notes and improve notes UI [@shamoon](https://github.com/shamoon) ([#2904](https://github.com/paperless-ngx/paperless-ngx/pull/2904))
|
||||||
|
- Allow psql client certificate authentication [@Ongy](https://github.com/Ongy) ([#2899](https://github.com/paperless-ngx/paperless-ngx/pull/2899))
|
||||||
|
- Enhancement: support filtering multiple correspondents, doctypes \& storage paths [@shamoon](https://github.com/shamoon) ([#2893](https://github.com/paperless-ngx/paperless-ngx/pull/2893))
|
||||||
|
- Fix: frontend handle private tags, doctypes, correspondents [@shamoon](https://github.com/shamoon) ([#2839](https://github.com/paperless-ngx/paperless-ngx/pull/2839))
|
||||||
|
- Fix: Chrome struggles with commas [@stumpylog](https://github.com/stumpylog) ([#2892](https://github.com/paperless-ngx/paperless-ngx/pull/2892))
|
||||||
|
- Feature: Change celery serializer to pickle [@stumpylog](https://github.com/stumpylog) ([#2861](https://github.com/paperless-ngx/paperless-ngx/pull/2861))
|
||||||
|
- Feature: Allow naming to include owner and original name [@stumpylog](https://github.com/stumpylog) ([#2873](https://github.com/paperless-ngx/paperless-ngx/pull/2873))
|
||||||
|
- Feature: Allows filtering email by the TO value(s) as well [@stumpylog](https://github.com/stumpylog) ([#2871](https://github.com/paperless-ngx/paperless-ngx/pull/2871))
|
||||||
|
- Fix: logout on change password via frontend [@shamoon](https://github.com/shamoon) ([#2863](https://github.com/paperless-ngx/paperless-ngx/pull/2863))
|
||||||
|
- Fix: give superuser full doc perms [@shamoon](https://github.com/shamoon) ([#2820](https://github.com/paperless-ngx/paperless-ngx/pull/2820))
|
||||||
|
- Fix: Append Gmail labels instead of replacing [@stumpylog](https://github.com/stumpylog) ([#2860](https://github.com/paperless-ngx/paperless-ngx/pull/2860))
|
||||||
|
- Feature: owner-aware unique model name constraint [@shamoon](https://github.com/shamoon) ([#2827](https://github.com/paperless-ngx/paperless-ngx/pull/2827))
|
||||||
|
- Chore: Create list parsing utility for settings [@stumpylog](https://github.com/stumpylog) ([#2816](https://github.com/paperless-ngx/paperless-ngx/pull/2816))
|
||||||
|
- Fix: Ensure email date is made aware during action processing [@stumpylog](https://github.com/stumpylog) ([#2837](https://github.com/paperless-ngx/paperless-ngx/pull/2837))
|
||||||
|
- Chore: Convert more code to pathlib [@stumpylog](https://github.com/stumpylog) ([#2817](https://github.com/paperless-ngx/paperless-ngx/pull/2817))
|
||||||
|
- Fix: disable bulk edit dialog buttons during operation [@shamoon](https://github.com/shamoon) ([#2819](https://github.com/paperless-ngx/paperless-ngx/pull/2819))
|
||||||
|
- fix database locked error [@jonaswinkler](https://github.com/jonaswinkler) ([#2808](https://github.com/paperless-ngx/paperless-ngx/pull/2808))
|
||||||
|
- Fix: Disable suggestions for read-only docs [@shamoon](https://github.com/shamoon) ([#2813](https://github.com/paperless-ngx/paperless-ngx/pull/2813))
|
||||||
|
- update django.po messages [@jonaswinkler](https://github.com/jonaswinkler) ([#2806](https://github.com/paperless-ngx/paperless-ngx/pull/2806))
|
||||||
|
- Update processed mail migration [@shamoon](https://github.com/shamoon) ([#2804](https://github.com/paperless-ngx/paperless-ngx/pull/2804))
|
||||||
|
- Feature/2396 better mail actions [@jonaswinkler](https://github.com/jonaswinkler) ([#2718](https://github.com/paperless-ngx/paperless-ngx/pull/2718))
|
||||||
|
- Bump zone.js from 0.11.8 to 0.12.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#2793](https://github.com/paperless-ngx/paperless-ngx/pull/2793))
|
||||||
|
- Bump [@<!---->typescript-eslint/parser from 5.50.0 to 5.54.0 in /src-ui @dependabot](https://github.com/<!---->typescript-eslint/parser from 5.50.0 to 5.54.0 in /src-ui @dependabot) ([#2792](https://github.com/paperless-ngx/paperless-ngx/pull/2792))
|
||||||
|
- Bulk Bump angular packages to 15.2.1 in /src-ui [@dependabot](https://github.com/dependabot) ([#2788](https://github.com/paperless-ngx/paperless-ngx/pull/2788))
|
||||||
|
- Fix: Ensure scratch directory exists before using [@stumpylog](https://github.com/stumpylog) ([#2775](https://github.com/paperless-ngx/paperless-ngx/pull/2775))
|
||||||
|
- Don't submit owner via API on document upload [@jonaswinkler](https://github.com/jonaswinkler) ([#2777](https://github.com/paperless-ngx/paperless-ngx/pull/2777))
|
||||||
|
- Feature: Reduce classifier memory usage somewhat during training [@stumpylog](https://github.com/stumpylog) ([#2733](https://github.com/paperless-ngx/paperless-ngx/pull/2733))
|
||||||
|
- Chore: Setup for mypy typing checks [@stumpylog](https://github.com/stumpylog) ([#2742](https://github.com/paperless-ngx/paperless-ngx/pull/2742))
|
||||||
|
- Feature: Add PAPERLESS_OCR_SKIP_ARCHIVE_FILE config setting [@bdr99](https://github.com/bdr99) ([#2743](https://github.com/paperless-ngx/paperless-ngx/pull/2743))
|
||||||
|
- Fix: only offer log files that exist [@shamoon](https://github.com/shamoon) ([#2739](https://github.com/paperless-ngx/paperless-ngx/pull/2739))
|
||||||
|
- Feature: dynamic document counts in dropdowns [@shamoon](https://github.com/shamoon) ([#2704](https://github.com/paperless-ngx/paperless-ngx/pull/2704))
|
||||||
|
- Fix: permissions editing and initial view issues [@shamoon](https://github.com/shamoon) ([#2717](https://github.com/paperless-ngx/paperless-ngx/pull/2717))
|
||||||
|
- Fix: reset saved view ID on quickFilter [@shamoon](https://github.com/shamoon) ([#2703](https://github.com/paperless-ngx/paperless-ngx/pull/2703))
|
||||||
|
- Feature: Add an option to disable matching [@bdr99](https://github.com/bdr99) ([#2727](https://github.com/paperless-ngx/paperless-ngx/pull/2727))
|
||||||
|
- Chore: Improve clarity of some test asserting [@stumpylog](https://github.com/stumpylog) ([#2714](https://github.com/paperless-ngx/paperless-ngx/pull/2714))
|
||||||
|
- Allow setting the ASN on document upload [@stumpylog](https://github.com/stumpylog) ([#2713](https://github.com/paperless-ngx/paperless-ngx/pull/2713))
|
||||||
|
- Fix: bulk edit reset apply button state [@shamoon](https://github.com/shamoon) ([#2701](https://github.com/paperless-ngx/paperless-ngx/pull/2701))
|
||||||
|
- Feature: Log failed login attempts [@shamoon](https://github.com/shamoon) ([#2359](https://github.com/paperless-ngx/paperless-ngx/pull/2359))
|
||||||
|
- Feature: Rename documents when storage path format changes [@stumpylog](https://github.com/stumpylog) ([#2696](https://github.com/paperless-ngx/paperless-ngx/pull/2696))
|
||||||
|
- Feature: update error message colors \& show on document failures [@shamoon](https://github.com/shamoon) ([#2689](https://github.com/paperless-ngx/paperless-ngx/pull/2689))
|
||||||
|
- Feature: multi-user permissions [@shamoon](https://github.com/shamoon) ([#2147](https://github.com/paperless-ngx/paperless-ngx/pull/2147))
|
||||||
|
- Fix: add missing i18n for mobile preview tab title [@nathanaelhoun](https://github.com/nathanaelhoun) ([#2692](https://github.com/paperless-ngx/paperless-ngx/pull/2692))
|
||||||
|
</details>
|
||||||
|
|
||||||
## paperless-ngx 1.13.0
|
## paperless-ngx 1.13.0
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
@ -453,6 +453,33 @@ redirect the user back to the SSO application's logout page.
|
|||||||
|
|
||||||
Defaults to None, which disables this feature.
|
Defaults to None, which disables this feature.
|
||||||
|
|
||||||
|
`PAPERLESS_USE_X_FORWARD_HOST=<bool>`
|
||||||
|
|
||||||
|
: Configures the Django setting [USE_X_FORWARDED_HOST](https://docs.djangoproject.com/en/4.2/ref/settings/#use-x-forwarded-host)
|
||||||
|
which may be needed for hosting behind a proxy.
|
||||||
|
|
||||||
|
Defaults to False
|
||||||
|
|
||||||
|
`PAPERLESS_USE_X_FORWARD_PORT=<bool>`
|
||||||
|
|
||||||
|
: Configures the Django setting [USE_X_FORWARDED_PORT](https://docs.djangoproject.com/en/4.2/ref/settings/#use-x-forwarded-port)
|
||||||
|
which may be needed for hosting behind a proxy.
|
||||||
|
|
||||||
|
Defaults to False
|
||||||
|
|
||||||
|
`PAPERLESS_PROXY_SSL_HEADER=<json-list>`
|
||||||
|
|
||||||
|
: Configures the Django setting [SECURE_PROXY_SSL_HEADER](https://docs.djangoproject.com/en/4.2/ref/settings/#secure-proxy-ssl-header)
|
||||||
|
which may be needed for hosting behind a proxy. The two values in the list will form the tuple of
|
||||||
|
HTTP header/value expected by Django, eg `'["HTTP_X_FORWARDED_PROTO", "https"]'`.
|
||||||
|
|
||||||
|
Defaults to None
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Settings this value has security implications. Read the Django documentation
|
||||||
|
and be sure you understand its usage before setting it.
|
||||||
|
|
||||||
## OCR settings {#ocr}
|
## OCR settings {#ocr}
|
||||||
|
|
||||||
Paperless uses [OCRmyPDF](https://ocrmypdf.readthedocs.io/en/latest/)
|
Paperless uses [OCRmyPDF](https://ocrmypdf.readthedocs.io/en/latest/)
|
||||||
|
@ -169,6 +169,12 @@ steps described in [Docker setup](#docker_hub) automatically.
|
|||||||
$ docker-compose run --rm webserver createsuperuser
|
$ docker-compose run --rm webserver createsuperuser
|
||||||
```
|
```
|
||||||
|
|
||||||
|
or using docker exec from within the container:
|
||||||
|
|
||||||
|
```shell-session
|
||||||
|
$ python3 manage.py createsuperuser
|
||||||
|
```
|
||||||
|
|
||||||
This will prompt you to set a username, an optional e-mail address
|
This will prompt you to set a username, an optional e-mail address
|
||||||
and finally a password (at least 8 characters).
|
and finally a password (at least 8 characters).
|
||||||
|
|
||||||
|
@ -56,8 +56,6 @@ describe('settings', () => {
|
|||||||
'GET',
|
'GET',
|
||||||
'http://localhost:8000/api/mail_accounts/*',
|
'http://localhost:8000/api/mail_accounts/*',
|
||||||
(req) => {
|
(req) => {
|
||||||
console.log(req, this.newMailAccounts)
|
|
||||||
|
|
||||||
let response = { ...mailAccountsJson }
|
let response = { ...mailAccountsJson }
|
||||||
if (this.newMailAccounts.length) {
|
if (this.newMailAccounts.length) {
|
||||||
response.results = response.results.concat(this.newMailAccounts)
|
response.results = response.results.concat(this.newMailAccounts)
|
||||||
@ -142,7 +140,7 @@ describe('settings', () => {
|
|||||||
cy.get('app-saved-view-widget').contains('Inbox').should('not.exist')
|
cy.get('app-saved-view-widget').contains('Inbox').should('not.exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should show a list of mail accounts & rules & support creation', () => {
|
it('should show a list of mail accounts & support creation', () => {
|
||||||
cy.contains('a', 'Mail').click()
|
cy.contains('a', 'Mail').click()
|
||||||
cy.get('app-settings .tab-content ul li').its('length').should('eq', 5) // 2 headers, 2 accounts, 1 rule
|
cy.get('app-settings .tab-content ul li').its('length').should('eq', 5) // 2 headers, 2 accounts, 1 rule
|
||||||
cy.contains('button', 'Add Account').click()
|
cy.contains('button', 'Add Account').click()
|
||||||
@ -162,6 +160,13 @@ describe('settings', () => {
|
|||||||
.wait('@getAccounts')
|
.wait('@getAccounts')
|
||||||
cy.contains('Saved account')
|
cy.contains('Saved account')
|
||||||
|
|
||||||
|
cy.get('app-settings .tab-content ul li').its('length').should('eq', 6)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should show a list of mail rules & support creation', () => {
|
||||||
|
cy.contains('a', 'Mail').click()
|
||||||
|
cy.get('app-settings .tab-content ul li').its('length').should('eq', 5) // 2 headers, 2 accounts, 1 rule
|
||||||
|
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
cy.contains('button', 'Add Rule').click()
|
cy.contains('button', 'Add Rule').click()
|
||||||
cy.contains('Create new mail rule')
|
cy.contains('Create new mail rule')
|
||||||
@ -177,6 +182,6 @@ describe('settings', () => {
|
|||||||
.wait('@getRules')
|
.wait('@getRules')
|
||||||
cy.contains('Saved rule').wait(1000)
|
cy.contains('Saved rule').wait(1000)
|
||||||
|
|
||||||
cy.get('app-settings .tab-content ul li').its('length').should('eq', 7)
|
cy.get('app-settings .tab-content ul li').its('length').should('eq', 6)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -155,6 +155,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
content: $localize`Drag-and-drop documents here to start uploading or place them in the consume folder. You can also drag-and-drop documents anywhere on all other pages of the web app. Once you do, Paperless-ngx will start training its machine learning algorithms.`,
|
content: $localize`Drag-and-drop documents here to start uploading or place them in the consume folder. You can also drag-and-drop documents anywhere on all other pages of the web app. Once you do, Paperless-ngx will start training its machine learning algorithms.`,
|
||||||
route: '/dashboard',
|
route: '/dashboard',
|
||||||
enableBackdrop: true,
|
enableBackdrop: true,
|
||||||
|
isOptional: true,
|
||||||
prevBtnTitle,
|
prevBtnTitle,
|
||||||
nextBtnTitle,
|
nextBtnTitle,
|
||||||
endBtnTitle,
|
endBtnTitle,
|
||||||
@ -167,6 +168,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
enableBackdrop: true,
|
enableBackdrop: true,
|
||||||
disableScrollToAnchor: true,
|
disableScrollToAnchor: true,
|
||||||
|
isOptional: true,
|
||||||
prevBtnTitle,
|
prevBtnTitle,
|
||||||
nextBtnTitle,
|
nextBtnTitle,
|
||||||
endBtnTitle,
|
endBtnTitle,
|
||||||
@ -177,6 +179,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
route: '/documents?sort=created&reverse=1&page=1',
|
route: '/documents?sort=created&reverse=1&page=1',
|
||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
enableBackdrop: true,
|
enableBackdrop: true,
|
||||||
|
isOptional: true,
|
||||||
prevBtnTitle,
|
prevBtnTitle,
|
||||||
nextBtnTitle,
|
nextBtnTitle,
|
||||||
endBtnTitle,
|
endBtnTitle,
|
||||||
@ -186,6 +189,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
content: $localize`Any combination of filters can be saved as a 'view' which can then be displayed on the dashboard and / or sidebar.`,
|
content: $localize`Any combination of filters can be saved as a 'view' which can then be displayed on the dashboard and / or sidebar.`,
|
||||||
route: '/documents?sort=created&reverse=1&page=1',
|
route: '/documents?sort=created&reverse=1&page=1',
|
||||||
enableBackdrop: true,
|
enableBackdrop: true,
|
||||||
|
isOptional: true,
|
||||||
prevBtnTitle,
|
prevBtnTitle,
|
||||||
nextBtnTitle,
|
nextBtnTitle,
|
||||||
endBtnTitle,
|
endBtnTitle,
|
||||||
@ -195,6 +199,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
content: $localize`Tags, correspondents, document types and storage paths can all be managed using these pages. They can also be created from the document edit view.`,
|
content: $localize`Tags, correspondents, document types and storage paths can all be managed using these pages. They can also be created from the document edit view.`,
|
||||||
route: '/tags',
|
route: '/tags',
|
||||||
enableBackdrop: true,
|
enableBackdrop: true,
|
||||||
|
isOptional: true,
|
||||||
prevBtnTitle,
|
prevBtnTitle,
|
||||||
nextBtnTitle,
|
nextBtnTitle,
|
||||||
endBtnTitle,
|
endBtnTitle,
|
||||||
@ -204,6 +209,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
content: $localize`File Tasks shows you documents that have been consumed, are waiting to be, or may have failed during the process.`,
|
content: $localize`File Tasks shows you documents that have been consumed, are waiting to be, or may have failed during the process.`,
|
||||||
route: '/tasks',
|
route: '/tasks',
|
||||||
enableBackdrop: true,
|
enableBackdrop: true,
|
||||||
|
isOptional: true,
|
||||||
prevBtnTitle,
|
prevBtnTitle,
|
||||||
nextBtnTitle,
|
nextBtnTitle,
|
||||||
endBtnTitle,
|
endBtnTitle,
|
||||||
@ -213,6 +219,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
content: $localize`Check out the settings for various tweaks to the web app, toggle settings for saved views or setup e-mail checking.`,
|
content: $localize`Check out the settings for various tweaks to the web app, toggle settings for saved views or setup e-mail checking.`,
|
||||||
route: '/settings',
|
route: '/settings',
|
||||||
enableBackdrop: true,
|
enableBackdrop: true,
|
||||||
|
isOptional: true,
|
||||||
prevBtnTitle,
|
prevBtnTitle,
|
||||||
nextBtnTitle,
|
nextBtnTitle,
|
||||||
endBtnTitle,
|
endBtnTitle,
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<div class="input-group-text" i18n>of {{previewNumPages}}</div>
|
<div class="input-group-text" i18n>of {{previewNumPages}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-danger me-2 ms-auto" (click)="delete()" [disabled]="!userIsOwner">
|
<button type="button" class="btn btn-sm btn-outline-danger me-2 ms-auto" (click)="delete()" [disabled]="!userIsOwner" *appIfPermissions="{ action: PermissionAction.Delete, type: PermissionType.Document }">
|
||||||
<svg class="buttonicon" fill="currentColor">
|
<svg class="buttonicon" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#trash" />
|
<use xlink:href="assets/bootstrap-icons.svg#trash" />
|
||||||
</svg><span class="d-none d-lg-inline ps-1" i18n>Delete</span>
|
</svg><span class="d-none d-lg-inline ps-1" i18n>Delete</span>
|
||||||
@ -178,7 +178,7 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li [ngbNavItem]="DocumentDetailNavIDs.Permissions" *appIfOwner="document">
|
<li [ngbNavItem]="DocumentDetailNavIDs.Permissions" *ngIf="showPermissions">
|
||||||
<a ngbNavLink i18n>Permissions</a>
|
<a ngbNavLink i18n>Permissions</a>
|
||||||
<ng-template ngbNavContent>
|
<ng-template ngbNavContent>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
|
@ -496,7 +496,7 @@ export class DocumentDetailComponent
|
|||||||
this.toastService.showError(
|
this.toastService.showError(
|
||||||
$localize`Error saving document` +
|
$localize`Error saving document` +
|
||||||
': ' +
|
': ' +
|
||||||
(error.message ?? error.toString())
|
(error.error?.detail ?? error.message ?? JSON.stringify(error))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -541,7 +541,7 @@ export class DocumentDetailComponent
|
|||||||
this.toastService.showError(
|
this.toastService.showError(
|
||||||
$localize`Error saving document` +
|
$localize`Error saving document` +
|
||||||
': ' +
|
': ' +
|
||||||
(error.message ?? error.toString())
|
(error.error?.detail ?? error.message ?? JSON.stringify(error))
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -573,6 +573,10 @@ export class DocumentDetailComponent
|
|||||||
modal.componentInstance.message = $localize`The files for this document will be deleted permanently. This operation cannot be undone.`
|
modal.componentInstance.message = $localize`The files for this document will be deleted permanently. This operation cannot be undone.`
|
||||||
modal.componentInstance.btnClass = 'btn-danger'
|
modal.componentInstance.btnClass = 'btn-danger'
|
||||||
modal.componentInstance.btnCaption = $localize`Delete document`
|
modal.componentInstance.btnCaption = $localize`Delete document`
|
||||||
|
this.subscribeModalDelete(modal) // so can be re-subscribed if error
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeModalDelete(modal) {
|
||||||
modal.componentInstance.confirmClicked
|
modal.componentInstance.confirmClicked
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap(() => {
|
switchMap(() => {
|
||||||
@ -581,18 +585,21 @@ export class DocumentDetailComponent
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
.pipe(takeUntil(this.unsubscribeNotifier))
|
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||||
.subscribe(
|
.subscribe({
|
||||||
() => {
|
next: () => {
|
||||||
modal.close()
|
modal.close()
|
||||||
this.close()
|
this.close()
|
||||||
},
|
},
|
||||||
(error) => {
|
error: (error) => {
|
||||||
this.toastService.showError(
|
this.toastService.showError(
|
||||||
$localize`Error deleting document: ${JSON.stringify(error)}`
|
$localize`Error deleting document: ${
|
||||||
|
error.error?.detail ?? error.message ?? JSON.stringify(error)
|
||||||
|
}`
|
||||||
)
|
)
|
||||||
modal.componentInstance.buttonsEnabled = true
|
modal.componentInstance.buttonsEnabled = true
|
||||||
}
|
this.subscribeModalDelete(modal)
|
||||||
)
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
moreLike() {
|
moreLike() {
|
||||||
@ -681,12 +688,21 @@ export class DocumentDetailComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get showPermissions(): boolean {
|
||||||
|
return (
|
||||||
|
this.permissionsService.currentUserCan(
|
||||||
|
PermissionAction.View,
|
||||||
|
PermissionType.User
|
||||||
|
) && this.userIsOwner
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
get notesEnabled(): boolean {
|
get notesEnabled(): boolean {
|
||||||
return (
|
return (
|
||||||
this.settings.get(SETTINGS_KEYS.NOTES_ENABLED) &&
|
this.settings.get(SETTINGS_KEYS.NOTES_ENABLED) &&
|
||||||
this.permissionsService.currentUserCan(
|
this.permissionsService.currentUserCan(
|
||||||
PermissionAction.View,
|
PermissionAction.View,
|
||||||
PermissionType.Document
|
PermissionType.Note
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,15 @@ import {
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { PermissionsService } from '../services/permissions.service'
|
import { PermissionsService } from '../services/permissions.service'
|
||||||
import { ToastService } from '../services/toast.service'
|
import { ToastService } from '../services/toast.service'
|
||||||
|
import { TourService } from 'ngx-ui-tour-ng-bootstrap'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PermissionsGuard implements CanActivate {
|
export class PermissionsGuard implements CanActivate {
|
||||||
constructor(
|
constructor(
|
||||||
private permissionsService: PermissionsService,
|
private permissionsService: PermissionsService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private toastService: ToastService
|
private toastService: ToastService,
|
||||||
|
private tourService: TourService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
canActivate(
|
canActivate(
|
||||||
@ -27,9 +29,12 @@ export class PermissionsGuard implements CanActivate {
|
|||||||
route.data.requiredPermission.type
|
route.data.requiredPermission.type
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
this.toastService.showError(
|
// Check if tour is running 1 = TourState.ON
|
||||||
$localize`You don't have permissions to do that`
|
if (this.tourService.getStatus() !== 1) {
|
||||||
)
|
this.toastService.showError(
|
||||||
|
$localize`You don't have permissions to do that`
|
||||||
|
)
|
||||||
|
}
|
||||||
return this.router.parseUrl('/dashboard')
|
return this.router.parseUrl('/dashboard')
|
||||||
} else {
|
} else {
|
||||||
return true
|
return true
|
||||||
|
@ -5,7 +5,7 @@ export const environment = {
|
|||||||
apiBaseUrl: document.baseURI + 'api/',
|
apiBaseUrl: document.baseURI + 'api/',
|
||||||
apiVersion: '2',
|
apiVersion: '2',
|
||||||
appTitle: 'Paperless-ngx',
|
appTitle: 'Paperless-ngx',
|
||||||
version: '1.14.0-beta.rc1',
|
version: '1.14.0',
|
||||||
webSocketHost: window.location.host,
|
webSocketHost: window.location.host,
|
||||||
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
|
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
|
||||||
webSocketBaseUrl: base_url.pathname + 'ws/',
|
webSocketBaseUrl: base_url.pathname + 'ws/',
|
||||||
|
@ -6,6 +6,7 @@ from documents.models import DocumentType
|
|||||||
from documents.models import MatchingModel
|
from documents.models import MatchingModel
|
||||||
from documents.models import StoragePath
|
from documents.models import StoragePath
|
||||||
from documents.models import Tag
|
from documents.models import Tag
|
||||||
|
from documents.permissions import get_objects_for_user_owner_aware
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger("paperless.matching")
|
logger = logging.getLogger("paperless.matching")
|
||||||
@ -19,40 +20,64 @@ def log_reason(matching_model, document, reason):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def match_correspondents(document, classifier):
|
def match_correspondents(document, classifier, user=None):
|
||||||
pred_id = classifier.predict_correspondent(document.content) if classifier else None
|
pred_id = classifier.predict_correspondent(document.content) if classifier else None
|
||||||
|
|
||||||
correspondents = Correspondent.objects.all()
|
if user is not None:
|
||||||
|
correspondents = get_objects_for_user_owner_aware(
|
||||||
|
user,
|
||||||
|
"documents.view_correspondent",
|
||||||
|
Correspondent,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
correspondents = Correspondent.objects.all()
|
||||||
|
|
||||||
return list(
|
return list(
|
||||||
filter(lambda o: matches(o, document) or o.pk == pred_id, correspondents),
|
filter(lambda o: matches(o, document) or o.pk == pred_id, correspondents),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def match_document_types(document, classifier):
|
def match_document_types(document, classifier, user=None):
|
||||||
pred_id = classifier.predict_document_type(document.content) if classifier else None
|
pred_id = classifier.predict_document_type(document.content) if classifier else None
|
||||||
|
|
||||||
document_types = DocumentType.objects.all()
|
if user is not None:
|
||||||
|
document_types = get_objects_for_user_owner_aware(
|
||||||
|
user,
|
||||||
|
"documents.view_documenttype",
|
||||||
|
DocumentType,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
document_types = DocumentType.objects.all()
|
||||||
|
|
||||||
return list(
|
return list(
|
||||||
filter(lambda o: matches(o, document) or o.pk == pred_id, document_types),
|
filter(lambda o: matches(o, document) or o.pk == pred_id, document_types),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def match_tags(document, classifier):
|
def match_tags(document, classifier, user=None):
|
||||||
predicted_tag_ids = classifier.predict_tags(document.content) if classifier else []
|
predicted_tag_ids = classifier.predict_tags(document.content) if classifier else []
|
||||||
|
|
||||||
tags = Tag.objects.all()
|
if user is not None:
|
||||||
|
tags = get_objects_for_user_owner_aware(user, "documents.view_tag", Tag)
|
||||||
|
else:
|
||||||
|
tags = Tag.objects.all()
|
||||||
|
|
||||||
return list(
|
return list(
|
||||||
filter(lambda o: matches(o, document) or o.pk in predicted_tag_ids, tags),
|
filter(lambda o: matches(o, document) or o.pk in predicted_tag_ids, tags),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def match_storage_paths(document, classifier):
|
def match_storage_paths(document, classifier, user=None):
|
||||||
pred_id = classifier.predict_storage_path(document.content) if classifier else None
|
pred_id = classifier.predict_storage_path(document.content) if classifier else None
|
||||||
|
|
||||||
storage_paths = StoragePath.objects.all()
|
if user is not None:
|
||||||
|
storage_paths = get_objects_for_user_owner_aware(
|
||||||
|
user,
|
||||||
|
"documents.view_storagepath",
|
||||||
|
StoragePath,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
storage_paths = StoragePath.objects.all()
|
||||||
|
|
||||||
return list(
|
return list(
|
||||||
filter(
|
filter(
|
||||||
|
@ -4,6 +4,7 @@ from django.contrib.auth.models import User
|
|||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from guardian.models import GroupObjectPermission
|
from guardian.models import GroupObjectPermission
|
||||||
from guardian.shortcuts import assign_perm
|
from guardian.shortcuts import assign_perm
|
||||||
|
from guardian.shortcuts import get_objects_for_user
|
||||||
from guardian.shortcuts import get_users_with_perms
|
from guardian.shortcuts import get_users_with_perms
|
||||||
from guardian.shortcuts import remove_perm
|
from guardian.shortcuts import remove_perm
|
||||||
from rest_framework.permissions import BasePermission
|
from rest_framework.permissions import BasePermission
|
||||||
@ -101,3 +102,15 @@ def set_permissions_for_object(permissions, object):
|
|||||||
group,
|
group,
|
||||||
object,
|
object,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_objects_for_user_owner_aware(user, perms, Model):
|
||||||
|
objects_owned = Model.objects.filter(owner=user)
|
||||||
|
objects_unowned = Model.objects.filter(owner__isnull=True)
|
||||||
|
objects_with_perms = get_objects_for_user(
|
||||||
|
user=user,
|
||||||
|
perms=perms,
|
||||||
|
klass=Model,
|
||||||
|
accept_global_perms=False,
|
||||||
|
)
|
||||||
|
return objects_owned | objects_unowned | objects_with_perms
|
||||||
|
@ -4,6 +4,7 @@ import shutil
|
|||||||
|
|
||||||
from celery import states
|
from celery import states
|
||||||
from celery.signals import before_task_publish
|
from celery.signals import before_task_publish
|
||||||
|
from celery.signals import task_failure
|
||||||
from celery.signals import task_postrun
|
from celery.signals import task_postrun
|
||||||
from celery.signals import task_prerun
|
from celery.signals import task_prerun
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -591,3 +592,29 @@ def task_postrun_handler(
|
|||||||
# Don't let an exception in the signal handlers prevent
|
# Don't let an exception in the signal handlers prevent
|
||||||
# a document from being consumed.
|
# a document from being consumed.
|
||||||
logger.exception("Updating PaperlessTask failed")
|
logger.exception("Updating PaperlessTask failed")
|
||||||
|
|
||||||
|
|
||||||
|
@task_failure.connect
|
||||||
|
def task_failure_handler(
|
||||||
|
sender=None,
|
||||||
|
task_id=None,
|
||||||
|
exception=None,
|
||||||
|
args=None,
|
||||||
|
traceback=None,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Updates the result of a failed PaperlessTask.
|
||||||
|
|
||||||
|
https://docs.celeryq.dev/en/stable/userguide/signals.html#task-failure
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
task_instance = PaperlessTask.objects.filter(task_id=task_id).first()
|
||||||
|
|
||||||
|
if task_instance is not None and task_instance.result is None:
|
||||||
|
task_instance.status = states.FAILURE
|
||||||
|
task_instance.result = traceback
|
||||||
|
task_instance.date_done = timezone.now()
|
||||||
|
task_instance.save()
|
||||||
|
except Exception: # pragma: no cover
|
||||||
|
logger.exception("Updating PaperlessTask failed")
|
||||||
|
@ -9,6 +9,7 @@ from documents.models import PaperlessTask
|
|||||||
from documents.signals.handlers import before_task_publish_handler
|
from documents.signals.handlers import before_task_publish_handler
|
||||||
from documents.signals.handlers import task_postrun_handler
|
from documents.signals.handlers import task_postrun_handler
|
||||||
from documents.signals.handlers import task_prerun_handler
|
from documents.signals.handlers import task_prerun_handler
|
||||||
|
from documents.signals.handlers import task_failure_handler
|
||||||
from documents.tests.test_consumer import fake_magic_from_file
|
from documents.tests.test_consumer import fake_magic_from_file
|
||||||
from documents.tests.utils import DirectoriesMixin
|
from documents.tests.utils import DirectoriesMixin
|
||||||
|
|
||||||
@ -146,3 +147,44 @@ class TestTaskSignalHandler(DirectoriesMixin, TestCase):
|
|||||||
task = PaperlessTask.objects.get()
|
task = PaperlessTask.objects.get()
|
||||||
|
|
||||||
self.assertEqual(celery.states.SUCCESS, task.status)
|
self.assertEqual(celery.states.SUCCESS, task.status)
|
||||||
|
|
||||||
|
def test_task_failure_handler(self):
|
||||||
|
"""
|
||||||
|
GIVEN:
|
||||||
|
- A celery task is started via the consume folder
|
||||||
|
WHEN:
|
||||||
|
- Task failed execution
|
||||||
|
THEN:
|
||||||
|
- The task is marked as failed
|
||||||
|
"""
|
||||||
|
headers = {
|
||||||
|
"id": str(uuid.uuid4()),
|
||||||
|
"task": "documents.tasks.consume_file",
|
||||||
|
}
|
||||||
|
body = (
|
||||||
|
# args
|
||||||
|
(
|
||||||
|
ConsumableDocument(
|
||||||
|
source=DocumentSource.ConsumeFolder,
|
||||||
|
original_file="/consume/hello-9.pdf",
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
# kwargs
|
||||||
|
{},
|
||||||
|
# celery stuff
|
||||||
|
{"callbacks": None, "errbacks": None, "chain": None, "chord": None},
|
||||||
|
)
|
||||||
|
self.util_call_before_task_publish_handler(
|
||||||
|
headers_to_use=headers,
|
||||||
|
body_to_use=body,
|
||||||
|
)
|
||||||
|
|
||||||
|
task_failure_handler(
|
||||||
|
task_id=headers["id"],
|
||||||
|
exception="Example failure",
|
||||||
|
)
|
||||||
|
|
||||||
|
task = PaperlessTask.objects.get()
|
||||||
|
|
||||||
|
self.assertEqual(celery.states.FAILURE, task.status)
|
||||||
|
@ -401,12 +401,16 @@ class DocumentViewSet(
|
|||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
{
|
{
|
||||||
"correspondents": [c.id for c in match_correspondents(doc, classifier)],
|
"correspondents": [
|
||||||
"tags": [t.id for t in match_tags(doc, classifier)],
|
c.id for c in match_correspondents(doc, classifier, request.user)
|
||||||
"document_types": [
|
],
|
||||||
dt.id for dt in match_document_types(doc, classifier)
|
"tags": [t.id for t in match_tags(doc, classifier, request.user)],
|
||||||
|
"document_types": [
|
||||||
|
dt.id for dt in match_document_types(doc, classifier, request.user)
|
||||||
|
],
|
||||||
|
"storage_paths": [
|
||||||
|
dt.id for dt in match_storage_paths(doc, classifier, request.user)
|
||||||
],
|
],
|
||||||
"storage_paths": [dt.id for dt in match_storage_paths(doc, classifier)],
|
|
||||||
"dates": [
|
"dates": [
|
||||||
date.strftime("%Y-%m-%d") for date in dates if date is not None
|
date.strftime("%Y-%m-%d") for date in dates if date is not None
|
||||||
],
|
],
|
||||||
|
@ -431,6 +431,14 @@ if _paperless_url:
|
|||||||
# For use with trusted proxies
|
# For use with trusted proxies
|
||||||
TRUSTED_PROXIES = __get_list("PAPERLESS_TRUSTED_PROXIES")
|
TRUSTED_PROXIES = __get_list("PAPERLESS_TRUSTED_PROXIES")
|
||||||
|
|
||||||
|
USE_X_FORWARDED_HOST = __get_boolean("PAPERLESS_USE_X_FORWARD_HOST", "false")
|
||||||
|
USE_X_FORWARDED_PORT = __get_boolean("PAPERLESS_USE_X_FORWARD_PORT", "false")
|
||||||
|
SECURE_PROXY_SSL_HEADER = (
|
||||||
|
tuple(json.loads(os.environ["PAPERLESS_PROXY_SSL_HEADER"]))
|
||||||
|
if "PAPERLESS_PROXY_SSL_HEADER" in os.environ
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
# The secret key has a default that should be fine so long as you're hosting
|
# The secret key has a default that should be fine so long as you're hosting
|
||||||
# Paperless on a closed network. However, if you're putting this anywhere
|
# Paperless on a closed network. However, if you're putting this anywhere
|
||||||
# public, you should change the key to something unique and verbose.
|
# public, you should change the key to something unique and verbose.
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 4.1.7 on 2023-04-20 15:03
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("paperless_mail", "0020_mailaccount_is_token"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="mailaccount",
|
||||||
|
name="password",
|
||||||
|
field=models.CharField(max_length=2048, verbose_name="password"),
|
||||||
|
),
|
||||||
|
]
|
@ -36,7 +36,7 @@ class MailAccount(document_models.ModelWithOwner):
|
|||||||
|
|
||||||
username = models.CharField(_("username"), max_length=256)
|
username = models.CharField(_("username"), max_length=256)
|
||||||
|
|
||||||
password = models.CharField(_("password"), max_length=256)
|
password = models.CharField(_("password"), max_length=2048)
|
||||||
|
|
||||||
is_token = models.BooleanField(_("Is token authentication"), default=False)
|
is_token = models.BooleanField(_("Is token authentication"), default=False)
|
||||||
|
|
||||||
|