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/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)) } } 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..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 @@ -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) @@ -470,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()) + ) + } }, }) } @@ -676,8 +685,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 +694,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 || 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 38eca0ffe..6111badae 100644 --- a/src/documents/serialisers.py +++ b/src/documents/serialisers.py @@ -162,6 +162,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, @@ -172,6 +173,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,