mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-10-21 07:18:13 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
354e52584c | ||
|
|
b904881472 |
No files matched your search
+1
-1
@@ -22,7 +22,7 @@
|
||||
"@angular/forms": "~22.2.0",
|
||||
"@angular/localize": "~22.2.0",
|
||||
"@angular/platform-browser": "~22.2.0",
|
||||
"@angular/router": "~22.2.0",
|
||||
"@angular/router": "~22.2.1",
|
||||
"@ng-bootstrap/ng-bootstrap": "^21.0.0",
|
||||
"@ng-select/ng-select": "~24.1.2",
|
||||
"@ngneat/dirty-check-forms": "^3.0.3",
|
||||
|
||||
Generated
+16
-16
@@ -30,8 +30,8 @@ importers:
|
||||
specifier: ~22.2.0
|
||||
version: 22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))
|
||||
'@angular/router':
|
||||
specifier: ~22.2.0
|
||||
version: 22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2)
|
||||
specifier: ~22.2.1
|
||||
version: 22.2.1(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2)
|
||||
'@ng-bootstrap/ng-bootstrap':
|
||||
specifier: ^21.0.0
|
||||
version: 21.0.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/forms@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(@angular/localize@22.2.0(@angular/compiler-cli@22.2.0(@angular/compiler@22.2.0)(typescript@6.0.3))(@angular/compiler@22.2.0))(@popperjs/core@2.11.8)(rxjs@7.8.2)
|
||||
@@ -40,7 +40,7 @@ importers:
|
||||
version: 24.1.2(4a7eb56833580f1a9810b0df0995c3c6)
|
||||
'@ngneat/dirty-check-forms':
|
||||
specifier: ^3.0.3
|
||||
version: 3.0.3(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/forms@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(@angular/router@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(lodash-es@4.18.1)(rxjs@7.8.2)
|
||||
version: 3.0.3(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/forms@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(@angular/router@22.2.1(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(lodash-es@4.18.1)(rxjs@7.8.2)
|
||||
'@popperjs/core':
|
||||
specifier: ^2.11.8
|
||||
version: 2.11.8
|
||||
@@ -73,7 +73,7 @@ importers:
|
||||
version: 12.0.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))
|
||||
ngx-ui-tour-ng-bootstrap:
|
||||
specifier: ^19.0.0
|
||||
version: 19.0.0(cd8c036435da1b7a89d66e1b1b6d40d2)
|
||||
version: 19.0.0(7c2af711d67c2f5a7d0db030f8fe42f5)
|
||||
normalize-diacritics:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
@@ -420,13 +420,13 @@ packages:
|
||||
'@angular/animations':
|
||||
optional: true
|
||||
|
||||
'@angular/router@22.2.0':
|
||||
resolution: {integrity: sha512-+pxHMwWWKg+ejS1vKa+tS91CDusCIK1MOSy6fVLc89McMOY/C8tsLrh1uJaMjklejsz+3XUhJgrLOvl3ISNz6w==}
|
||||
'@angular/router@22.2.1':
|
||||
resolution: {integrity: sha512-HJfJ4yA1znKd9YFtbDOJfKmD12x0PhS7LkmYdWlJRu2WkQZRBVrdGKdmbvV5UvrqCRllVWKpzw1TIZJM69rlcw==}
|
||||
engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0}
|
||||
peerDependencies:
|
||||
'@angular/common': 22.2.0
|
||||
'@angular/core': 22.2.0
|
||||
'@angular/platform-browser': 22.2.0
|
||||
'@angular/common': 22.2.1
|
||||
'@angular/core': 22.2.1
|
||||
'@angular/platform-browser': 22.2.1
|
||||
rxjs: ^6.5.3 || ^7.4.0
|
||||
|
||||
'@asamuzakjp/css-color@3.2.0':
|
||||
@@ -4514,7 +4514,7 @@ snapshots:
|
||||
'@angular/core': 22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)
|
||||
tslib: 2.8.1
|
||||
|
||||
'@angular/router@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2)':
|
||||
'@angular/router@22.2.1(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2)':
|
||||
dependencies:
|
||||
'@angular/common': 22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2)
|
||||
'@angular/core': 22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)
|
||||
@@ -5626,11 +5626,11 @@ snapshots:
|
||||
'@angular/forms': 22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2)
|
||||
tslib: 2.8.1
|
||||
|
||||
'@ngneat/dirty-check-forms@3.0.3(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/forms@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(@angular/router@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(lodash-es@4.18.1)(rxjs@7.8.2)':
|
||||
'@ngneat/dirty-check-forms@3.0.3(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/forms@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(@angular/router@22.2.1(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(lodash-es@4.18.1)(rxjs@7.8.2)':
|
||||
dependencies:
|
||||
'@angular/core': 22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)
|
||||
'@angular/forms': 22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2)
|
||||
'@angular/router': 22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2)
|
||||
'@angular/router': 22.2.1(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2)
|
||||
lodash-es: 4.18.1
|
||||
rxjs: 7.8.2
|
||||
tslib: 2.8.1
|
||||
@@ -7502,20 +7502,20 @@ snapshots:
|
||||
'@angular/core': 22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)
|
||||
tslib: 2.8.1
|
||||
|
||||
ngx-ui-tour-core@17.0.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/router@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(rxjs@7.8.2):
|
||||
ngx-ui-tour-core@17.0.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/router@22.2.1(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(rxjs@7.8.2):
|
||||
dependencies:
|
||||
'@angular/common': 22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2)
|
||||
'@angular/core': 22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)
|
||||
'@angular/router': 22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2)
|
||||
'@angular/router': 22.2.1(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2)
|
||||
rxjs: 7.8.2
|
||||
tslib: 2.8.1
|
||||
|
||||
ngx-ui-tour-ng-bootstrap@19.0.0(cd8c036435da1b7a89d66e1b1b6d40d2):
|
||||
ngx-ui-tour-ng-bootstrap@19.0.0(7c2af711d67c2f5a7d0db030f8fe42f5):
|
||||
dependencies:
|
||||
'@angular/common': 22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2)
|
||||
'@angular/core': 22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)
|
||||
'@ng-bootstrap/ng-bootstrap': 21.0.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/forms@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(@angular/localize@22.2.0(@angular/compiler-cli@22.2.0(@angular/compiler@22.2.0)(typescript@6.0.3))(@angular/compiler@22.2.0))(@popperjs/core@2.11.8)(rxjs@7.8.2)
|
||||
ngx-ui-tour-core: 17.0.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/router@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(rxjs@7.8.2)
|
||||
ngx-ui-tour-core: 17.0.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/router@22.2.1(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(@angular/platform-browser@22.2.0(@angular/common@22.2.0(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@22.2.0(@angular/compiler@22.2.0)(rxjs@7.8.2)))(rxjs@7.8.2))(rxjs@7.8.2)
|
||||
tslib: 2.8.1
|
||||
transitivePeerDependencies:
|
||||
- '@angular/router'
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
from collections.abc import Mapping
|
||||
from collections.abc import Sequence
|
||||
from typing import Any
|
||||
from typing import ClassVar
|
||||
from typing import Literal
|
||||
from typing import TypeGuard
|
||||
from typing import TypeVar
|
||||
from typing import cast
|
||||
|
||||
from django.contrib.auth.models import Group
|
||||
from django.contrib.auth.models import Permission
|
||||
@@ -62,28 +68,23 @@ class PaperlessAdminPermissions(BasePermission):
|
||||
return request.user.is_active and request.user.is_staff
|
||||
|
||||
|
||||
def has_global_statistics_permission(user: User | None) -> bool:
|
||||
if (
|
||||
user is None
|
||||
or not getattr(user, "is_active", False)
|
||||
or not getattr(user, "is_authenticated", False)
|
||||
):
|
||||
return False
|
||||
def _is_active_and_authenticated(user: User | None) -> TypeGuard[User]:
|
||||
return (
|
||||
user is not None
|
||||
and getattr(user, "is_active", False)
|
||||
and getattr(user, "is_authenticated", False)
|
||||
)
|
||||
|
||||
return getattr(user, "is_superuser", False) or user.has_perm(
|
||||
"paperless.view_global_statistics",
|
||||
|
||||
def has_global_statistics_permission(user: User | None) -> bool:
|
||||
return _is_active_and_authenticated(user) and (
|
||||
getattr(user, "is_superuser", False)
|
||||
or user.has_perm("paperless.view_global_statistics")
|
||||
)
|
||||
|
||||
|
||||
def has_system_status_permission(user: User | None) -> bool:
|
||||
if (
|
||||
user is None
|
||||
or not getattr(user, "is_active", False)
|
||||
or not getattr(user, "is_authenticated", False)
|
||||
):
|
||||
return False
|
||||
|
||||
return (
|
||||
return _is_active_and_authenticated(user) and (
|
||||
getattr(user, "is_superuser", False)
|
||||
or getattr(user, "is_staff", False)
|
||||
or user.has_perm("paperless.view_system_monitoring")
|
||||
@@ -727,7 +728,32 @@ def has_perms_owner_aware(user, perms, obj):
|
||||
return obj.owner is None or obj.owner == user or checker.has_perm(perms, obj)
|
||||
|
||||
|
||||
class ViewDocumentsPermissions(BasePermission):
|
||||
# HEAD is deliberately absent: GlobalPermissionsByMethod checks it against GET.
|
||||
MappedMethod = Literal["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
|
||||
|
||||
|
||||
class GlobalPermissionsByMethod(BasePermission):
|
||||
"""
|
||||
Requires the global (model-level) permissions listed in ``perms_map`` for
|
||||
the request's HTTP method. HEAD is checked against the ``"GET"`` entry,
|
||||
since DRF runs the GET handler for it. A method missing from
|
||||
``perms_map`` is denied.
|
||||
"""
|
||||
|
||||
perms_map: ClassVar[Mapping[MappedMethod, Sequence[str]]]
|
||||
|
||||
def has_permission(self, request: Any, view: Any) -> bool:
|
||||
if not request.user or not request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
method = "GET" if request.method == "HEAD" else request.method
|
||||
# An unknown method is not a MappedMethod, but .get() returns None for
|
||||
# it, so it is still denied.
|
||||
perms = self.perms_map.get(cast("MappedMethod", method))
|
||||
return perms is not None and request.user.has_perms(perms)
|
||||
|
||||
|
||||
class ViewDocumentsPermissions(GlobalPermissionsByMethod):
|
||||
"""
|
||||
Permissions class that checks for model permissions for only viewing Documents.
|
||||
"""
|
||||
@@ -738,31 +764,18 @@ class ViewDocumentsPermissions(BasePermission):
|
||||
"POST": ["documents.view_document"],
|
||||
}
|
||||
|
||||
def has_permission(self, request, view):
|
||||
if not request.user or (not request.user.is_authenticated): # pragma: no cover
|
||||
return False
|
||||
|
||||
return request.user.has_perms(self.perms_map.get(request.method, []))
|
||||
|
||||
|
||||
class TrashPermissions(BasePermission):
|
||||
class TrashPermissions(GlobalPermissionsByMethod):
|
||||
"""Check the global document permission for each trash operation."""
|
||||
|
||||
perms_map = {
|
||||
"OPTIONS": ["documents.view_document"],
|
||||
"HEAD": ["documents.view_document"],
|
||||
"GET": ["documents.view_document"],
|
||||
"POST": ["documents.delete_document"],
|
||||
}
|
||||
|
||||
def has_permission(self, request, view):
|
||||
if not request.user or not request.user.is_authenticated: # pragma: no cover
|
||||
return False
|
||||
|
||||
return request.user.has_perms(self.perms_map.get(request.method, []))
|
||||
|
||||
|
||||
class PaperlessNotePermissions(BasePermission):
|
||||
class PaperlessNotePermissions(GlobalPermissionsByMethod):
|
||||
"""
|
||||
Permissions class that checks for model permissions for Notes.
|
||||
"""
|
||||
@@ -782,28 +795,13 @@ class PaperlessNotePermissions(BasePermission):
|
||||
],
|
||||
}
|
||||
|
||||
def has_permission(self, request, view):
|
||||
if not request.user or (not request.user.is_authenticated): # pragma: no cover
|
||||
return False
|
||||
|
||||
perms = self.perms_map[request.method]
|
||||
|
||||
return request.user.has_perms(perms)
|
||||
|
||||
|
||||
class AcknowledgeTasksPermissions(BasePermission):
|
||||
class AcknowledgeTasksPermissions(GlobalPermissionsByMethod):
|
||||
"""
|
||||
Permissions class that checks for model permissions for acknowledging tasks.
|
||||
"""
|
||||
|
||||
perms_map = {
|
||||
"OPTIONS": ["documents.change_paperlesstask"],
|
||||
"POST": ["documents.change_paperlesstask"],
|
||||
}
|
||||
|
||||
def has_permission(self, request: Any, view: Any) -> bool:
|
||||
if not request.user or not request.user.is_authenticated: # pragma: no cover
|
||||
return False
|
||||
|
||||
perms = self.perms_map.get(request.method, [])
|
||||
|
||||
return request.user.has_perms(perms)
|
||||
@@ -3653,6 +3653,34 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
def test_notes_head_and_unsupported_methods(self) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
- A user allowed to view notes on their own document
|
||||
WHEN:
|
||||
- The notes endpoint is requested with HEAD, PUT and PATCH
|
||||
THEN:
|
||||
- HEAD is allowed like GET
|
||||
- PUT and PATCH are rejected with 403 rather than a server error
|
||||
"""
|
||||
user = UserFactory()
|
||||
grant_global(user, "view_note", "view_document")
|
||||
doc = DocumentFactory(owner=user)
|
||||
self.client.force_authenticate(user)
|
||||
|
||||
self.assertEqual(
|
||||
self.client.head(f"/api/documents/{doc.pk}/notes/").status_code,
|
||||
status.HTTP_200_OK,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.client.put(f"/api/documents/{doc.pk}/notes/").status_code,
|
||||
status.HTTP_403_FORBIDDEN,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.client.patch(f"/api/documents/{doc.pk}/notes/").status_code,
|
||||
status.HTTP_403_FORBIDDEN,
|
||||
)
|
||||
|
||||
def test_delete_note(self) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
|
||||
@@ -1001,6 +1001,21 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(response.data), 10)
|
||||
|
||||
def test_search_autocomplete_head_requires_view_document(self) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
- A user without the global view document permission
|
||||
WHEN:
|
||||
- A HEAD request is made for autocomplete
|
||||
THEN:
|
||||
- It is rejected like the equivalent GET request
|
||||
"""
|
||||
self.client.force_authenticate(user=UserFactory())
|
||||
|
||||
response = self.client.head("/api/search/autocomplete/?term=test")
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_search_autocomplete_respect_permissions(self) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
|
||||
Reference in new issue
Block a user