From e373ca7bdc1a0d2e7a22acf4b0d15c0729cfd655 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 3 Mar 2023 15:52:28 -0800 Subject: [PATCH 1/5] fix unable to change owner to someone else --- .../document-detail/document-detail.component.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 e154cd03b..2038bd41e 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 @@ -676,8 +676,8 @@ export class DocumentDetailComponent get userIsOwner(): boolean { let doc: PaperlessDocument = Object.assign({}, this.document) // dont disable while editing - if (this.document && this.store?.value.owner) { - doc.owner = this.store?.value.owner + if (this.document && this.store?.value.permissions_form?.owner) { + doc.owner = this.store?.value.permissions_form?.owner } return !this.document || this.permissionsService.currentUserOwnsObject(doc) } @@ -685,8 +685,8 @@ export class DocumentDetailComponent get userCanEdit(): boolean { let doc: PaperlessDocument = Object.assign({}, this.document) // dont disable while editing - if (this.document && this.store?.value.owner) { - doc.owner = this.store?.value.owner + if (this.document && this.store?.value.permissions_form?.owner) { + doc.owner = this.store?.value.permissions_form?.owner } return ( !this.document || From 9902c4745d4d2ae30f7a08ff7dafeb672b629d81 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 3 Mar 2023 19:22:11 -0800 Subject: [PATCH 2/5] fix doc detail discard perm changes --- .../components/document-detail/document-detail.component.ts | 4 ++++ 1 file changed, 4 insertions(+) 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 2038bd41e..0fc617434 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 @@ -446,6 +446,10 @@ export class DocumentDetailComponent .subscribe({ next: (doc) => { Object.assign(this.document, doc) + doc['permissions_form'] = { + owner: doc.owner, + set_permissions: doc.permissions, + } this.title = doc.title this.documentForm.patchValue(doc) this.openDocumentService.setDirty(doc, false) From 4cfc416cdcf3528f586f45d9d768bf3bfe8f9e1b Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 6 Mar 2023 10:04:18 -0800 Subject: [PATCH 3/5] Handle user saved and no longer has permissions --- .../document-detail.component.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) 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 0fc617434..bb22c49ab 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 @@ -474,12 +474,17 @@ export class DocumentDetailComponent }, error: (error) => { this.networkActive = false - this.error = error.error - this.toastService.showError( - $localize`Error saving document` + - ': ' + - (error.message ?? error.toString()) - ) + if (!this.userCanEdit) { + this.toastService.showInfo($localize`Document saved successfully.`) + this.close() + } else { + this.error = error.error + this.toastService.showError( + $localize`Error saving document` + + ': ' + + (error.message ?? error.toString()) + ) + } }, }) } From ae0c58591867bd5bd238123f120ee974e116a2dc Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 17 Mar 2023 20:49:47 -0700 Subject: [PATCH 4/5] Fix inherited permissions should not display per user in permissions form --- .../cypress/fixtures/documents/documents.json | 44 +++++++++++++++++-- .../fixtures/ui_settings/settings.json | 3 +- .../ui_settings/settings_restricted.json | 3 +- .../common/input/select/select.component.ts | 2 +- src-ui/src/app/data/paperless-user.ts | 2 +- .../src/app/services/permissions.service.ts | 11 +++-- src/documents/permissions.py | 1 + src/documents/serialisers.py | 2 + src/documents/views.py | 1 + 9 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src-ui/cypress/fixtures/documents/documents.json b/src-ui/cypress/fixtures/documents/documents.json index be7640c8f..e3938dba1 100644 --- a/src-ui/cypress/fixtures/documents/documents.json +++ b/src-ui/cypress/fixtures/documents/documents.json @@ -21,7 +21,16 @@ "original_file_name": "2022-03-22 no latin title.pdf", "archived_file_name": "2022-03-22 no latin title.pdf", "owner": null, - "permissions": [], + "permissions": { + "view": { + "users": [], + "groups": [] + }, + "change": { + "users": [], + "groups": [] + } + }, "notes": [ { "id": 9, @@ -59,7 +68,16 @@ "original_file_name": "2022-03-23 lorem ipsum dolor sit amet.pdf", "archived_file_name": "2022-03-23 llorem ipsum dolor sit amet.pdf", "owner": null, - "permissions": [], + "permissions": { + "view": { + "users": [], + "groups": [] + }, + "change": { + "users": [], + "groups": [] + } + }, "notes": [] }, { @@ -80,7 +98,16 @@ "original_file_name": "2022-03-24 dolor.pdf", "archived_file_name": "2022-03-24 dolor.pdf", "owner": null, - "permissions": [], + "permissions": { + "view": { + "users": [], + "groups": [] + }, + "change": { + "users": [], + "groups": [] + } + }, "notes": [] }, { @@ -101,7 +128,16 @@ "original_file_name": "2022-06-01 sit amet.pdf", "archived_file_name": "2022-06-01 sit amet.pdf", "owner": null, - "permissions": [], + "permissions": { + "view": { + "users": [], + "groups": [] + }, + "change": { + "users": [], + "groups": [] + } + }, "notes": [] } ] diff --git a/src-ui/cypress/fixtures/ui_settings/settings.json b/src-ui/cypress/fixtures/ui_settings/settings.json index 3183943fe..b885eeccb 100644 --- a/src-ui/cypress/fixtures/ui_settings/settings.json +++ b/src-ui/cypress/fixtures/ui_settings/settings.json @@ -2,7 +2,8 @@ "user": { "id": 1, "username": "admin", - "is_superuser": true + "is_superuser": true, + "groups": [] }, "settings": { "language": "", diff --git a/src-ui/cypress/fixtures/ui_settings/settings_restricted.json b/src-ui/cypress/fixtures/ui_settings/settings_restricted.json index 72ebe51b1..1f7f61fdc 100644 --- a/src-ui/cypress/fixtures/ui_settings/settings_restricted.json +++ b/src-ui/cypress/fixtures/ui_settings/settings_restricted.json @@ -2,7 +2,8 @@ "user": { "id": 1, "username": "admin", - "is_superuser": false + "is_superuser": false, + "groups": [] }, "settings": { "language": "", diff --git a/src-ui/src/app/components/common/input/select/select.component.ts b/src-ui/src/app/components/common/input/select/select.component.ts index 0f65d76b6..ddf900bf6 100644 --- a/src-ui/src/app/components/common/input/select/select.component.ts +++ b/src-ui/src/app/components/common/input/select/select.component.ts @@ -77,7 +77,7 @@ export class SelectComponent extends AbstractInputComponent { } get isPrivate(): boolean { - return this.items.find((i) => i.id === this.value)?.private + return this.items?.find((i) => i.id === this.value)?.private } getSuggestions() { diff --git a/src-ui/src/app/data/paperless-user.ts b/src-ui/src/app/data/paperless-user.ts index 125a2f509..1cd64ebf9 100644 --- a/src-ui/src/app/data/paperless-user.ts +++ b/src-ui/src/app/data/paperless-user.ts @@ -9,7 +9,7 @@ export interface PaperlessUser extends ObjectWithId { is_staff?: boolean is_active?: boolean is_superuser?: boolean - groups?: PaperlessGroup[] + groups?: number[] // PaperlessGroup[] user_permissions?: string[] inherited_permissions?: string[] } diff --git a/src-ui/src/app/services/permissions.service.ts b/src-ui/src/app/services/permissions.service.ts index e1ce94977..c19a4ee94 100644 --- a/src-ui/src/app/services/permissions.service.ts +++ b/src-ui/src/app/services/permissions.service.ts @@ -58,11 +58,16 @@ export class PermissionsService { action: string, object: ObjectWithPermissions ): boolean { + let actionObject = null + if (action === PermissionAction.View) actionObject = object.permissions.view + else if (action === PermissionAction.Change) + actionObject = object.permissions.change + if (!actionObject) return false return ( this.currentUserOwnsObject(object) || - (object.permissions[action]['users'] as Array)?.includes( - this.currentUser.id - ) + actionObject.users.includes(this.currentUser.id) || + actionObject.groups.filter((g) => this.currentUser.groups.includes(g)) + .length > 0 ) } diff --git a/src/documents/permissions.py b/src/documents/permissions.py index c0e7ac345..c50cdc5b9 100644 --- a/src/documents/permissions.py +++ b/src/documents/permissions.py @@ -63,6 +63,7 @@ def set_permissions_for_object(permissions, object): users_to_remove = get_users_with_perms( object, only_with_perms_in=[permission], + with_group_users=False, ) if len(users_to_add) > 0 and len(users_to_remove) > 0: users_to_remove = users_to_remove.difference(users_to_add) diff --git a/src/documents/serialisers.py b/src/documents/serialisers.py index 4e2fafe34..e1187b446 100644 --- a/src/documents/serialisers.py +++ b/src/documents/serialisers.py @@ -161,6 +161,7 @@ class OwnedObjectSerializer(serializers.ModelSerializer, SetPermissionsMixin): "users": get_users_with_perms( obj, only_with_perms_in=[view_codename], + with_group_users=False, ).values_list("id", flat=True), "groups": get_groups_with_only_permission( obj, @@ -171,6 +172,7 @@ class OwnedObjectSerializer(serializers.ModelSerializer, SetPermissionsMixin): "users": get_users_with_perms( obj, only_with_perms_in=[change_codename], + with_group_users=False, ).values_list("id", flat=True), "groups": get_groups_with_only_permission( obj, diff --git a/src/documents/views.py b/src/documents/views.py index 6a0eae051..1b30ec770 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -964,6 +964,7 @@ class UiSettingsView(GenericAPIView): "id": user.id, "username": user.username, "is_superuser": user.is_superuser, + "groups": user.groups.values_list("id", flat=True), }, "settings": ui_settings, "permissions": roles, From 20c6abae63c8940dd6b658f6c68026e01ffe258f Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 3 Mar 2023 20:45:03 -0800 Subject: [PATCH 5/5] exclude current user from permissions retrieval users Revert "exclude current user from permissions retrieval users" This reverts commit 87efd0ccc8d4eb9d8acb614d22a5c95ffdb895ae. Update permissions-user.component.ts --- .../permissions-user/permissions-user.component.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src-ui/src/app/components/common/input/permissions/permissions-user/permissions-user.component.ts b/src-ui/src/app/components/common/input/permissions/permissions-user/permissions-user.component.ts index 5c08a06a2..1db4e0ff9 100644 --- a/src-ui/src/app/components/common/input/permissions/permissions-user/permissions-user.component.ts +++ b/src-ui/src/app/components/common/input/permissions/permissions-user/permissions-user.component.ts @@ -28,11 +28,6 @@ export class PermissionsUserComponent extends AbstractInputComponent< userService .listAll() .pipe(first()) - .subscribe( - (result) => - (this.users = result.results.filter( - (u) => u.id !== settings.currentUser.id - )) - ) + .subscribe((result) => (this.users = result.results)) } }