+
Save
@if (hasNext()) {
diff --git a/src-ui/src/app/components/document-detail/document-detail.component.ts b/src-ui/src/app/components/document-detail/document-detail.component.ts
index 0e79b3deb..798e867bf 100644
--- a/src-ui/src/app/components/document-detail/document-detail.component.ts
+++ b/src-ui/src/app/components/document-detail/document-detail.component.ts
@@ -861,8 +861,11 @@ export class DocumentDetailComponent
get userIsOwner(): boolean {
let doc: Document = Object.assign({}, this.document)
// dont disable while editing
- if (this.document && this.store?.value.permissions_form?.owner) {
- doc.owner = this.store?.value.permissions_form?.owner
+ if (
+ this.document &&
+ this.store?.value.permissions_form?.hasOwnProperty('owner')
+ ) {
+ doc.owner = this.store.value.permissions_form.owner
}
return !this.document || this.permissionsService.currentUserOwnsObject(doc)
}
@@ -870,8 +873,11 @@ export class DocumentDetailComponent
get userCanEdit(): boolean {
let doc: Document = Object.assign({}, this.document)
// dont disable while editing
- if (this.document && this.store?.value.permissions_form?.owner) {
- doc.owner = this.store?.value.permissions_form?.owner
+ if (
+ this.document &&
+ this.store?.value.permissions_form?.hasOwnProperty('owner')
+ ) {
+ doc.owner = this.store.value.permissions_form.owner
}
return (
!this.document ||
diff --git a/src-ui/src/app/components/manage/custom-fields/custom-fields.component.spec.ts b/src-ui/src/app/components/manage/custom-fields/custom-fields.component.spec.ts
index 412fe3cc1..9e8663383 100644
--- a/src-ui/src/app/components/manage/custom-fields/custom-fields.component.spec.ts
+++ b/src-ui/src/app/components/manage/custom-fields/custom-fields.component.spec.ts
@@ -11,6 +11,7 @@ import {
NgbPaginationModule,
NgbModalModule,
NgbModalRef,
+ NgbPopoverModule,
} from '@ng-bootstrap/ng-bootstrap'
import { of, throwError } from 'rxjs'
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
@@ -64,6 +65,7 @@ describe('CustomFieldsComponent', () => {
FormsModule,
ReactiveFormsModule,
NgbModalModule,
+ NgbPopoverModule,
],
})
diff --git a/src-ui/src/app/components/manage/workflows/workflows.component.spec.ts b/src-ui/src/app/components/manage/workflows/workflows.component.spec.ts
index 1abbd2c5a..adf174207 100644
--- a/src-ui/src/app/components/manage/workflows/workflows.component.spec.ts
+++ b/src-ui/src/app/components/manage/workflows/workflows.component.spec.ts
@@ -7,6 +7,7 @@ import {
NgbPaginationModule,
NgbModalRef,
NgbModalModule,
+ NgbPopoverModule,
} from '@ng-bootstrap/ng-bootstrap'
import { of, throwError } from 'rxjs'
import { Workflow } from 'src/app/data/workflow'
@@ -99,6 +100,7 @@ describe('WorkflowsComponent', () => {
FormsModule,
ReactiveFormsModule,
NgbModalModule,
+ NgbPopoverModule,
],
})
diff --git a/src/paperless/auth.py b/src/paperless/auth.py
index a23b01cb4..98e2a8b30 100644
--- a/src/paperless/auth.py
+++ b/src/paperless/auth.py
@@ -47,3 +47,11 @@ class HttpRemoteUserMiddleware(PersistentRemoteUserMiddleware):
"""
header = settings.HTTP_REMOTE_USER_HEADER_NAME
+
+
+class PaperlessRemoteUserAuthentication(authentication.RemoteUserAuthentication):
+ """
+ REMOTE_USER authentication for DRF which overrides the default header.
+ """
+
+ header = settings.HTTP_REMOTE_USER_HEADER_NAME
diff --git a/src/paperless/settings.py b/src/paperless/settings.py
index bc815d4d5..54779006d 100644
--- a/src/paperless/settings.py
+++ b/src/paperless/settings.py
@@ -420,19 +420,31 @@ if AUTO_LOGIN_USERNAME:
# regular login in case the provided user does not exist.
MIDDLEWARE.insert(_index + 1, "paperless.auth.AutoLoginMiddleware")
-ENABLE_HTTP_REMOTE_USER = __get_boolean("PAPERLESS_ENABLE_HTTP_REMOTE_USER")
-HTTP_REMOTE_USER_HEADER_NAME = os.getenv(
- "PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME",
- "HTTP_REMOTE_USER",
-)
-if ENABLE_HTTP_REMOTE_USER:
- MIDDLEWARE.append("paperless.auth.HttpRemoteUserMiddleware")
- AUTHENTICATION_BACKENDS.insert(0, "django.contrib.auth.backends.RemoteUserBackend")
- REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"].append(
- "rest_framework.authentication.RemoteUserAuthentication",
+def _parse_remote_user_settings() -> str:
+ global MIDDLEWARE, AUTHENTICATION_BACKENDS, REST_FRAMEWORK
+ enable = __get_boolean("PAPERLESS_ENABLE_HTTP_REMOTE_USER")
+ if enable:
+ MIDDLEWARE.append("paperless.auth.HttpRemoteUserMiddleware")
+ AUTHENTICATION_BACKENDS.insert(
+ 0,
+ "django.contrib.auth.backends.RemoteUserBackend",
+ )
+ REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"].insert(
+ 0,
+ "paperless.auth.PaperlessRemoteUserAuthentication",
+ )
+
+ header_name = os.getenv(
+ "PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME",
+ "HTTP_REMOTE_USER",
)
+ return header_name
+
+
+HTTP_REMOTE_USER_HEADER_NAME = _parse_remote_user_settings()
+
# X-Frame options for embedded PDF display:
X_FRAME_OPTIONS = "ANY" if DEBUG else "SAMEORIGIN"
diff --git a/src/paperless/tests/test_remote_user.py b/src/paperless/tests/test_remote_user.py
new file mode 100644
index 000000000..194026e4d
--- /dev/null
+++ b/src/paperless/tests/test_remote_user.py
@@ -0,0 +1,75 @@
+import os
+from unittest import mock
+
+from django.contrib.auth.models import User
+from rest_framework import status
+from rest_framework.test import APITestCase
+
+from documents.tests.utils import DirectoriesMixin
+from paperless.settings import _parse_remote_user_settings
+
+
+class TestRemoteUser(DirectoriesMixin, APITestCase):
+ def setUp(self):
+ super().setUp()
+
+ self.user = User.objects.create_superuser(
+ username="temp_admin",
+ )
+
+ def test_remote_user(self):
+ """
+ GIVEN:
+ - Configured user
+ - Remote user auth is enabled
+ WHEN:
+ - API call is made to get documents
+ THEN:
+ - Call succeeds
+ """
+
+ with mock.patch.dict(
+ os.environ,
+ {
+ "PAPERLESS_ENABLE_HTTP_REMOTE_USER": "True",
+ },
+ ):
+ _parse_remote_user_settings()
+
+ response = self.client.get("/api/documents/")
+
+ # 403 testing locally, 401 on ci...
+ self.assertIn(
+ response.status_code,
+ [status.HTTP_401_UNAUTHORIZED, status.HTTP_403_FORBIDDEN],
+ )
+
+ response = self.client.get(
+ "/api/documents/",
+ headers={
+ "Remote-User": self.user.username,
+ },
+ )
+
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+ def test_remote_user_header_setting(self):
+ """
+ GIVEN:
+ - Remote user header name is set
+ WHEN:
+ - Settings are parsed
+ THEN:
+ - Correct header name is returned
+ """
+
+ with mock.patch.dict(
+ os.environ,
+ {
+ "PAPERLESS_ENABLE_HTTP_REMOTE_USER": "True",
+ "PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME": "HTTP_FOO",
+ },
+ ):
+ header_name = _parse_remote_user_settings()
+
+ self.assertEqual(header_name, "HTTP_FOO")