]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Enhancement: Hide columns in document list if user does not have permissions (#6415)
authorDominik Bruhn <dominik@dbruhn.de>
Tue, 16 Apr 2024 21:41:15 +0000 (23:41 +0200)
committerGitHub <noreply@github.com>
Tue, 16 Apr 2024 21:41:15 +0000 (21:41 +0000)
---------

Co-authored-by: Dominik Bruhn <dominik@menlo79.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
src-ui/messages.xlf
src-ui/src/app/components/document-list/document-list.component.html
src-ui/src/app/components/document-list/document-list.component.spec.ts
src-ui/src/app/components/document-list/document-list.component.ts

index 0855a0dcf94970888616896bd9f8b7086261d7b8..7461baf9c9355ae16b78aeeec0cd3b75f132fbf9 100644 (file)
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/admin/users-groups/users-groups.component.html</context>
-          <context context-type="linenumber">94</context>
+          <context context-type="linenumber">92</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-account-edit-dialog/mail-account-edit-dialog.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">173</context>
+          <context context-type="linenumber">175</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/admin/users-groups/users-groups.component.html</context>
-          <context context-type="linenumber">59</context>
+          <context context-type="linenumber">58</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/admin/users-groups/users-groups.component.html</context>
-          <context context-type="linenumber">62</context>
+          <context context-type="linenumber">61</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/admin/users-groups/users-groups.component.html</context>
-          <context context-type="linenumber">77</context>
+          <context context-type="linenumber">76</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.ts</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">195</context>
+          <context context-type="linenumber">201</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/admin/users-groups/users-groups.component.html</context>
-          <context context-type="linenumber">74</context>
+          <context context-type="linenumber">73</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/input/permissions/permissions-form/permissions-form.component.html</context>
         <source>No groups defined</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/admin/users-groups/users-groups.component.html</context>
-          <context context-type="linenumber">85</context>
+          <context context-type="linenumber">84</context>
         </context-group>
       </trans-unit>
       <trans-unit id="4510369340305901516" datatype="html">
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.ts</context>
-          <context context-type="linenumber">97</context>
+          <context context-type="linenumber">103</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">158</context>
+          <context context-type="linenumber">160</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">150</context>
+          <context context-type="linenumber">151</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">181</context>
+          <context context-type="linenumber">184</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">188</context>
+          <context context-type="linenumber">193</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">218</context>
+          <context context-type="linenumber">225</context>
         </context-group>
       </trans-unit>
       <trans-unit id="2784168796433474565" datatype="html">
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">224</context>
+          <context context-type="linenumber">232</context>
         </context-group>
       </trans-unit>
       <trans-unit id="106713086593101376" datatype="html">
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">243</context>
+          <context context-type="linenumber">252</context>
         </context-group>
       </trans-unit>
       <trans-unit id="157572966557284263" datatype="html">
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">248</context>
+          <context context-type="linenumber">259</context>
         </context-group>
       </trans-unit>
       <trans-unit id="3727324658595204357" datatype="html">
         <source>Sort by correspondent</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">146</context>
+          <context context-type="linenumber">147</context>
         </context-group>
       </trans-unit>
       <trans-unit id="2066713941761361709" datatype="html">
         <source>Sort by title</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">153</context>
+          <context context-type="linenumber">155</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6232673011753681091" datatype="html">
         <source>Sort by owner</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">161</context>
+          <context context-type="linenumber">163</context>
         </context-group>
       </trans-unit>
       <trans-unit id="3715596725146409911" datatype="html">
         <source>Owner</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">165</context>
+          <context context-type="linenumber">167</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
         <source>Sort by notes</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">169</context>
+          <context context-type="linenumber">171</context>
         </context-group>
       </trans-unit>
       <trans-unit id="5499001829734502606" datatype="html">
         <source>Sort by document type</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">177</context>
+          <context context-type="linenumber">180</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6213829731736042759" datatype="html">
         <source>Sort by storage path</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">184</context>
+          <context context-type="linenumber">189</context>
         </context-group>
       </trans-unit>
       <trans-unit id="3406167410329973166" datatype="html">
         <source>Sort by created date</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">191</context>
+          <context context-type="linenumber">197</context>
         </context-group>
       </trans-unit>
       <trans-unit id="3769035778779263084" datatype="html">
         <source>Sort by added date</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">198</context>
+          <context context-type="linenumber">204</context>
         </context-group>
       </trans-unit>
       <trans-unit id="231679111972850796" datatype="html">
         <source>Added</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">202</context>
+          <context context-type="linenumber">208</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
         <source>Edit document</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
-          <context context-type="linenumber">222</context>
+          <context context-type="linenumber">230</context>
         </context-group>
       </trans-unit>
       <trans-unit id="2155249406916744630" datatype="html">
         <source>View &quot;<x id="PH" equiv-text="this.list.activeSavedViewTitle"/>&quot; saved successfully.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.ts</context>
-          <context context-type="linenumber">207</context>
+          <context context-type="linenumber">213</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6837554170707123455" datatype="html">
         <source>View &quot;<x id="PH" equiv-text="savedView.name"/>&quot; created successfully.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.ts</context>
-          <context context-type="linenumber">248</context>
+          <context context-type="linenumber">254</context>
         </context-group>
       </trans-unit>
       <trans-unit id="3100631071441658964" datatype="html">
index 1cfa4fff96b50eb8be8d0314265cc152eead2aa0..3cce1496bf2d04101840b73f7dad87ba879619b0 100644 (file)
             [currentSortReverse]="list.sortReverse"
             (sort)="onSort($event)"
           i18n>ASN</th>
-          <th class="d-none d-md-table-cell"
-            pngxSortable="correspondent__name"
-            title="Sort by correspondent" i18n-title
-            [currentSortField]="list.sortField"
-            [currentSortReverse]="list.sortReverse"
-            (sort)="onSort($event)"
-          i18n>Correspondent</th>
+          @if (permissionService.currentUserCan(PermissionAction.View, PermissionType.Correspondent)) {
+            <th class="d-none d-md-table-cell"
+              pngxSortable="correspondent__name"
+              title="Sort by correspondent" i18n-title
+              [currentSortField]="list.sortField"
+              [currentSortReverse]="list.sortReverse"
+              (sort)="onSort($event)"
+            i18n>Correspondent</th>
+          }
           <th
             pngxSortable="title"
             title="Sort by title" i18n-title
               (sort)="onSort($event)"
             i18n>Notes</th>
           }
-          <th class="d-none d-xl-table-cell"
-            pngxSortable="document_type__name"
-            title="Sort by document type" i18n-title
-            [currentSortField]="list.sortField"
-            [currentSortReverse]="list.sortReverse"
-            (sort)="onSort($event)"
-          i18n>Document type</th>
-          <th class="d-none d-xl-table-cell"
-            pngxSortable="storage_path__name"
-            title="Sort by storage path" i18n-title
-            [currentSortField]="list.sortField"
-            [currentSortReverse]="list.sortReverse"
-            (sort)="onSort($event)"
-          i18n>Storage path</th>
+          @if (permissionService.currentUserCan(PermissionAction.View, PermissionType.DocumentType)) {
+            <th class="d-none d-xl-table-cell"
+              pngxSortable="document_type__name"
+              title="Sort by document type" i18n-title
+              [currentSortField]="list.sortField"
+              [currentSortReverse]="list.sortReverse"
+              (sort)="onSort($event)"
+            i18n>Document type</th>
+          }
+          @if (permissionService.currentUserCan(PermissionAction.View, PermissionType.StoragePath)) {
+            <th class="d-none d-xl-table-cell"
+              pngxSortable="storage_path__name"
+              title="Sort by storage path" i18n-title
+              [currentSortField]="list.sortField"
+              [currentSortReverse]="list.sortReverse"
+              (sort)="onSort($event)"
+            i18n>Storage path</th>
+          }
           <th
             pngxSortable="created"
             title="Sort by created date" i18n-title
               <td class="d-none d-lg-table-cell">
                 {{d.archive_serial_number}}
               </td>
-              <td class="d-none d-md-table-cell">
-                @if (d.correspondent) {
-                  <a (click)="clickCorrespondent(d.correspondent);$event.stopPropagation()" title="Filter by correspondent" i18n-title>{{(d.correspondent$ | async)?.name}}</a>
-                }
-              </td>
+              @if (permissionService.currentUserCan(PermissionAction.View, PermissionType.Correspondent)) {
+                <td class="d-none d-md-table-cell">
+                  @if (d.correspondent) {
+                    <a (click)="clickCorrespondent(d.correspondent);$event.stopPropagation()" title="Filter by correspondent" i18n-title>{{(d.correspondent$ | async)?.name}}</a>
+                  }
+                </td>
+              }
               <td>
                 <a routerLink="/documents/{{d.id}}" title="Edit document" i18n-title style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a>
                 @for (t of d.tags$ | async; track t) {
                   }
                 </td>
               }
-              <td class="d-none d-xl-table-cell">
-                @if (d.document_type) {
-                  <a (click)="clickDocumentType(d.document_type);$event.stopPropagation()" title="Filter by document type" i18n-title>{{(d.document_type$ | async)?.name}}</a>
-                }
-              </td>
-              <td class="d-none d-xl-table-cell">
-                @if (d.storage_path) {
-                  <a (click)="clickStoragePath(d.storage_path);$event.stopPropagation()" title="Filter by storage path" i18n-title>{{(d.storage_path$ | async)?.name}}</a>
-                }
-              </td>
+              @if (permissionService.currentUserCan(PermissionAction.View, PermissionType.DocumentType)) {
+                <td class="d-none d-xl-table-cell">
+                  @if (d.document_type) {
+                    <a (click)="clickDocumentType(d.document_type);$event.stopPropagation()" title="Filter by document type" i18n-title>{{(d.document_type$ | async)?.name}}</a>
+                  }
+                </td>
+              }
+              @if (permissionService.currentUserCan(PermissionAction.View, PermissionType.StoragePath)) {
+                <td class="d-none d-xl-table-cell">
+                  @if (d.storage_path) {
+                    <a (click)="clickStoragePath(d.storage_path);$event.stopPropagation()" title="Filter by storage path" i18n-title>{{(d.storage_path$ | async)?.name}}</a>
+                  }
+                </td>
+              }
               <td>
                 {{d.created_date | customDate}}
               </td>
index bf21616e8a9b319b5cbe5f35f4e1fc976c31db1a..77dc03f84a5c4f049efcfe2fea7aca0f08aab16d 100644 (file)
@@ -64,6 +64,8 @@ import { SettingsService } from 'src/app/services/settings.service'
 import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
 import { IsNumberPipe } from 'src/app/pipes/is-number.pipe'
 import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
+import { PermissionsService } from 'src/app/services/permissions.service'
+import { NgSelectModule } from '@ng-select/ng-select'
 
 const docs: Document[] = [
   {
@@ -101,6 +103,7 @@ describe('DocumentListComponent', () => {
   let toastService: ToastService
   let modalService: NgbModal
   let settingsService: SettingsService
+  let permissionService: PermissionsService
 
   beforeEach(async () => {
     TestBed.configureTestingModule({
@@ -148,6 +151,7 @@ describe('DocumentListComponent', () => {
         NgbPopoverModule,
         NgbTooltipModule,
         NgxBootstrapIconsModule.pick(allIcons),
+        NgSelectModule,
       ],
     }).compileComponents()
 
@@ -160,6 +164,7 @@ describe('DocumentListComponent', () => {
     toastService = TestBed.inject(ToastService)
     modalService = TestBed.inject(NgbModal)
     settingsService = TestBed.inject(SettingsService)
+    permissionService = TestBed.inject(PermissionsService)
     fixture = TestBed.createComponent(DocumentListComponent)
     component = fixture.componentInstance
   })
@@ -548,18 +553,13 @@ describe('DocumentListComponent', () => {
     expect(routerSpy).toHaveBeenCalledWith(['documents', 99])
   })
 
-  it('should support checking if notes enabled to hide column', () => {
+  it('should hide columns if no perms or notes disabled', () => {
+    jest.spyOn(permissionService, 'currentUserCan').mockReturnValue(true)
     jest.spyOn(documentListService, 'documents', 'get').mockReturnValue(docs)
-    fixture.detectChanges()
     expect(documentListService.sortField).toEqual('created')
 
-    const detailsDisplayModeButton = fixture.debugElement.query(
-      By.css('input[type="radio"]')
-    )
-    detailsDisplayModeButton.nativeElement.checked = true
-    detailsDisplayModeButton.triggerEventHandler('change')
+    component.displayMode = 'details'
     fixture.detectChanges()
-    expect(component.displayMode).toEqual('details')
 
     expect(
       fixture.debugElement.queryAll(By.directive(SortableDirective))
@@ -572,6 +572,13 @@ describe('DocumentListComponent', () => {
     expect(
       fixture.debugElement.queryAll(By.directive(SortableDirective))
     ).toHaveLength(8)
+
+    // insufficient perms
+    jest.spyOn(permissionService, 'currentUserCan').mockReturnValue(false)
+    fixture.detectChanges()
+    expect(
+      fixture.debugElement.queryAll(By.directive(SortableDirective))
+    ).toHaveLength(5)
   })
 
   it('should support toggle on document objects', () => {
index 537e24601cf0de2c3d4886ff96d37da244b67357..7d27f4e3e0e8ec4e2d2f520c5935ba36edfac645 100644 (file)
@@ -29,6 +29,7 @@ import {
   DOCUMENT_SORT_FIELDS,
   DOCUMENT_SORT_FIELDS_FULLTEXT,
 } from 'src/app/services/rest/document.service'
+import { PermissionsService } from 'src/app/services/permissions.service'
 import { SavedViewService } from 'src/app/services/rest/saved-view.service'
 import { SettingsService } from 'src/app/services/settings.service'
 import { ToastService } from 'src/app/services/toast.service'
@@ -54,7 +55,8 @@ export class DocumentListComponent
     private modalService: NgbModal,
     private consumerStatusService: ConsumerStatusService,
     public openDocumentsService: OpenDocumentsService,
-    private settingsService: SettingsService
+    private settingsService: SettingsService,
+    public permissionService: PermissionsService
   ) {
     super()
   }