mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-31 02:27:10 -04:00 
			
		
		
		
	Unify API perm endpoint to set_permissions, initial frontend support for doc sharing
				
					
				
			This commit is contained in:
		
							parent
							
								
									2973e4672a
								
							
						
					
					
						commit
						79da613cb6
					
				| @ -12,7 +12,7 @@ | |||||||
|         i18n-addTagText="Used for both types, correspondents, storage paths" |         i18n-addTagText="Used for both types, correspondents, storage paths" | ||||||
|         [placeholder]="placeholder" |         [placeholder]="placeholder" | ||||||
|         [multiple]="multiple" |         [multiple]="multiple" | ||||||
|         bindLabel="name" |         [bindLabel]="bindLabel" | ||||||
|         bindValue="id" |         bindValue="id" | ||||||
|         (change)="onChange(value)" |         (change)="onChange(value)" | ||||||
|         (search)="onSearch($event)" |         (search)="onSearch($event)" | ||||||
|  | |||||||
| @ -47,6 +47,9 @@ export class SelectComponent extends AbstractInputComponent<number> { | |||||||
|   @Input() |   @Input() | ||||||
|   multiple: boolean = false |   multiple: boolean = false | ||||||
| 
 | 
 | ||||||
|  |   @Input() | ||||||
|  |   bindLabel: string = 'name' | ||||||
|  | 
 | ||||||
|   @Output() |   @Output() | ||||||
|   createNew = new EventEmitter<string>() |   createNew = new EventEmitter<string>() | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -170,12 +170,23 @@ | |||||||
|                         </div> |                         </div> | ||||||
|                     </ng-template> |                     </ng-template> | ||||||
|                 </li> |                 </li> | ||||||
|  | 
 | ||||||
|                 <li [ngbNavItem]="5" *ngIf="commentsEnabled"> |                 <li [ngbNavItem]="5" *ngIf="commentsEnabled"> | ||||||
|                     <a ngbNavLink i18n>Comments</a> |                     <a ngbNavLink i18n>Comments</a> | ||||||
|                     <ng-template ngbNavContent> |                     <ng-template ngbNavContent> | ||||||
|                         <app-document-comments [documentId]="documentId"></app-document-comments> |                         <app-document-comments [documentId]="documentId"></app-document-comments> | ||||||
|                     </ng-template> |                     </ng-template> | ||||||
|                 </li> |                 </li> | ||||||
|  | 
 | ||||||
|  |                 <li [ngbNavItem]="6"> | ||||||
|  |                     <a ngbNavLink i18n>Permissions</a> | ||||||
|  |                     <ng-template ngbNavContent> | ||||||
|  |                         <div formGroupName="set_permissions"> | ||||||
|  |                             <app-input-select i18n-title title="Users can view" [items]="users" [bindLabel]="'username'" multiple="true" formControlName="view"></app-input-select> | ||||||
|  |                             <app-input-select i18n-title title="Users can edit" [items]="users" [bindLabel]="'username'" multiple="true" formControlName="change"></app-input-select> | ||||||
|  |                         </div> | ||||||
|  |                     </ng-template> | ||||||
|  |                 </li> | ||||||
|             </ul> |             </ul> | ||||||
| 
 | 
 | ||||||
|             <div [ngbNavOutlet]="nav" class="mt-2"></div> |             <div [ngbNavOutlet]="nav" class="mt-2"></div> | ||||||
|  | |||||||
| @ -40,6 +40,8 @@ import { | |||||||
|   PermissionsService, |   PermissionsService, | ||||||
|   PermissionType, |   PermissionType, | ||||||
| } from 'src/app/services/permissions.service' | } from 'src/app/services/permissions.service' | ||||||
|  | import { UserService } from 'src/app/services/rest/user.service' | ||||||
|  | import { PaperlessUser } from 'src/app/data/paperless-user' | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-document-detail', |   selector: 'app-document-detail', | ||||||
| @ -73,6 +75,7 @@ export class DocumentDetailComponent | |||||||
|   correspondents: PaperlessCorrespondent[] |   correspondents: PaperlessCorrespondent[] | ||||||
|   documentTypes: PaperlessDocumentType[] |   documentTypes: PaperlessDocumentType[] | ||||||
|   storagePaths: PaperlessStoragePath[] |   storagePaths: PaperlessStoragePath[] | ||||||
|  |   users: PaperlessUser[] | ||||||
| 
 | 
 | ||||||
|   documentForm: FormGroup = new FormGroup({ |   documentForm: FormGroup = new FormGroup({ | ||||||
|     title: new FormControl(''), |     title: new FormControl(''), | ||||||
| @ -83,6 +86,10 @@ export class DocumentDetailComponent | |||||||
|     storage_path: new FormControl(), |     storage_path: new FormControl(), | ||||||
|     archive_serial_number: new FormControl(), |     archive_serial_number: new FormControl(), | ||||||
|     tags: new FormControl([]), |     tags: new FormControl([]), | ||||||
|  |     set_permissions: new FormGroup({ | ||||||
|  |       view: new FormControl(null), | ||||||
|  |       change: new FormControl(null), | ||||||
|  |     }), | ||||||
|   }) |   }) | ||||||
| 
 | 
 | ||||||
|   previewCurrentPage: number = 1 |   previewCurrentPage: number = 1 | ||||||
| @ -127,7 +134,8 @@ export class DocumentDetailComponent | |||||||
|     private toastService: ToastService, |     private toastService: ToastService, | ||||||
|     private settings: SettingsService, |     private settings: SettingsService, | ||||||
|     private storagePathService: StoragePathService, |     private storagePathService: StoragePathService, | ||||||
|     private permissionsService: PermissionsService |     private permissionsService: PermissionsService, | ||||||
|  |     private userService: UserService | ||||||
|   ) {} |   ) {} | ||||||
| 
 | 
 | ||||||
|   titleKeyUp(event) { |   titleKeyUp(event) { | ||||||
| @ -167,6 +175,11 @@ export class DocumentDetailComponent | |||||||
|       .pipe(first()) |       .pipe(first()) | ||||||
|       .subscribe((result) => (this.storagePaths = result.results)) |       .subscribe((result) => (this.storagePaths = result.results)) | ||||||
| 
 | 
 | ||||||
|  |     this.userService | ||||||
|  |       .listAll() | ||||||
|  |       .pipe(first()) | ||||||
|  |       .subscribe((result) => (this.users = result.results)) | ||||||
|  | 
 | ||||||
|     this.route.paramMap |     this.route.paramMap | ||||||
|       .pipe( |       .pipe( | ||||||
|         takeUntil(this.unsubscribeNotifier), |         takeUntil(this.unsubscribeNotifier), | ||||||
| @ -230,6 +243,14 @@ export class DocumentDetailComponent | |||||||
|             storage_path: doc.storage_path, |             storage_path: doc.storage_path, | ||||||
|             archive_serial_number: doc.archive_serial_number, |             archive_serial_number: doc.archive_serial_number, | ||||||
|             tags: [...doc.tags], |             tags: [...doc.tags], | ||||||
|  |             set_permissions: { | ||||||
|  |               view: doc.permissions | ||||||
|  |                 .filter((p) => (p[1] as string).includes('view')) | ||||||
|  |                 .map((p) => p[0]), | ||||||
|  |               change: doc.permissions | ||||||
|  |                 .filter((p) => (p[1] as string).includes('change')) | ||||||
|  |                 .map((p) => p[0]), | ||||||
|  |             }, | ||||||
|           }) |           }) | ||||||
| 
 | 
 | ||||||
|           this.isDirty$ = dirtyCheck( |           this.isDirty$ = dirtyCheck( | ||||||
| @ -284,6 +305,14 @@ export class DocumentDetailComponent | |||||||
|         }, |         }, | ||||||
|       }) |       }) | ||||||
|     this.title = this.documentTitlePipe.transform(doc.title) |     this.title = this.documentTitlePipe.transform(doc.title) | ||||||
|  |     doc['set_permissions'] = { | ||||||
|  |       view: doc.permissions | ||||||
|  |         .filter((p) => (p[1] as string).includes('view')) | ||||||
|  |         .map((p) => p[0]), | ||||||
|  |       change: doc.permissions | ||||||
|  |         .filter((p) => (p[1] as string).includes('change')) | ||||||
|  |         .map((p) => p[0]), | ||||||
|  |     } | ||||||
|     this.documentForm.patchValue(doc) |     this.documentForm.patchValue(doc) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -376,7 +405,7 @@ export class DocumentDetailComponent | |||||||
|       .update(this.document) |       .update(this.document) | ||||||
|       .pipe(first()) |       .pipe(first()) | ||||||
|       .subscribe({ |       .subscribe({ | ||||||
|         next: (result) => { |         next: () => { | ||||||
|           this.close() |           this.close() | ||||||
|           this.networkActive = false |           this.networkActive = false | ||||||
|           this.error = null |           this.error = null | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import { ObjectWithId } from './object-with-id' | import { ObjectWithPermissions } from './object-with-permissions' | ||||||
| 
 | 
 | ||||||
| export const MATCH_ANY = 1 | export const MATCH_ANY = 1 | ||||||
| export const MATCH_ALL = 2 | export const MATCH_ALL = 2 | ||||||
| @ -41,7 +41,7 @@ export const MATCHING_ALGORITHMS = [ | |||||||
|   }, |   }, | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| export interface MatchingModel extends ObjectWithId { | export interface MatchingModel extends ObjectWithPermissions { | ||||||
|   name?: string |   name?: string | ||||||
| 
 | 
 | ||||||
|   slug?: string |   slug?: string | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								src-ui/src/app/data/object-with-permissions.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src-ui/src/app/data/object-with-permissions.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | import { ObjectWithId } from './object-with-id' | ||||||
|  | import { PaperlessUser } from './paperless-user' | ||||||
|  | 
 | ||||||
|  | export interface ObjectWithPermissions extends ObjectWithId { | ||||||
|  |   user?: PaperlessUser | ||||||
|  | 
 | ||||||
|  |   permissions?: Array<[number, string]> | ||||||
|  | } | ||||||
| @ -1,9 +1,9 @@ | |||||||
| import { PaperlessCorrespondent } from './paperless-correspondent' | import { PaperlessCorrespondent } from './paperless-correspondent' | ||||||
| import { ObjectWithId } from './object-with-id' |  | ||||||
| import { PaperlessTag } from './paperless-tag' | import { PaperlessTag } from './paperless-tag' | ||||||
| import { PaperlessDocumentType } from './paperless-document-type' | import { PaperlessDocumentType } from './paperless-document-type' | ||||||
| import { Observable } from 'rxjs' | import { Observable } from 'rxjs' | ||||||
| import { PaperlessStoragePath } from './paperless-storage-path' | import { PaperlessStoragePath } from './paperless-storage-path' | ||||||
|  | import { ObjectWithPermissions } from './object-with-permissions' | ||||||
| 
 | 
 | ||||||
| export interface SearchHit { | export interface SearchHit { | ||||||
|   score?: number |   score?: number | ||||||
| @ -12,7 +12,7 @@ export interface SearchHit { | |||||||
|   highlights?: string |   highlights?: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface PaperlessDocument extends ObjectWithId { | export interface PaperlessDocument extends ObjectWithPermissions { | ||||||
|   correspondent$?: Observable<PaperlessCorrespondent> |   correspondent$?: Observable<PaperlessCorrespondent> | ||||||
| 
 | 
 | ||||||
|   correspondent?: number |   correspondent?: number | ||||||
|  | |||||||
| @ -2,8 +2,10 @@ import { HttpClient, HttpParams } from '@angular/common/http' | |||||||
| import { Observable } from 'rxjs' | import { Observable } from 'rxjs' | ||||||
| import { map, publishReplay, refCount } from 'rxjs/operators' | import { map, publishReplay, refCount } from 'rxjs/operators' | ||||||
| import { ObjectWithId } from 'src/app/data/object-with-id' | import { ObjectWithId } from 'src/app/data/object-with-id' | ||||||
|  | import { PaperlessUser } from 'src/app/data/paperless-user' | ||||||
| import { Results } from 'src/app/data/results' | import { Results } from 'src/app/data/results' | ||||||
| import { environment } from 'src/environments/environment' | import { environment } from 'src/environments/environment' | ||||||
|  | import { PermissionAction, PermissionType } from '../permissions.service' | ||||||
| 
 | 
 | ||||||
| export abstract class AbstractPaperlessService<T extends ObjectWithId> { | export abstract class AbstractPaperlessService<T extends ObjectWithId> { | ||||||
|   protected baseUrl: string = environment.apiBaseUrl |   protected baseUrl: string = environment.apiBaseUrl | ||||||
|  | |||||||
| @ -31,6 +31,7 @@ from .parsers import is_mime_type_supported | |||||||
| from guardian.models import UserObjectPermission | from guardian.models import UserObjectPermission | ||||||
| from guardian.shortcuts import assign_perm | from guardian.shortcuts import assign_perm | ||||||
| from guardian.shortcuts import remove_perm | from guardian.shortcuts import remove_perm | ||||||
|  | from guardian.shortcuts import get_users_with_perms | ||||||
| 
 | 
 | ||||||
| from django.contrib.contenttypes.models import ContentType | from django.contrib.contenttypes.models import ContentType | ||||||
| 
 | 
 | ||||||
| @ -91,55 +92,36 @@ class OwnedObjectSerializer(serializers.ModelSerializer): | |||||||
|         ).values_list("user", "permission__codename") |         ).values_list("user", "permission__codename") | ||||||
|         return list(user_object_perms) |         return list(user_object_perms) | ||||||
| 
 | 
 | ||||||
|     permissions = SerializerMethodField() |     permissions = SerializerMethodField(read_only=True) | ||||||
| 
 | 
 | ||||||
|     grant_permissions = serializers.DictField( |     set_permissions = serializers.DictField( | ||||||
|         label="Grant permissions", |         label="Set permissions", | ||||||
|         allow_empty=True, |         allow_empty=True, | ||||||
|         required=False, |         required=False, | ||||||
|         write_only=True, |         write_only=True, | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     def _validate_user_ids(self, user_ids): |     def _validate_user_ids(self, user_ids): | ||||||
|  |         users = User.objects.none() | ||||||
|  |         if user_ids is not None: | ||||||
|             users = User.objects.filter(id__in=user_ids) |             users = User.objects.filter(id__in=user_ids) | ||||||
|         if not users.count() == len(users): |             if not users.count() == len(user_ids): | ||||||
|                 raise serializers.ValidationError( |                 raise serializers.ValidationError( | ||||||
|                     "Some users in don't exist or were specified twice.", |                     "Some users in don't exist or were specified twice.", | ||||||
|                 ) |                 ) | ||||||
|         return users |         return users | ||||||
| 
 | 
 | ||||||
|     def validate_grant_permissions(self, grant_permissions): |     def validate_set_permissions(self, set_permissions): | ||||||
|         user_dict = { |         user_dict = { | ||||||
|             "view": User.objects.none(), |             "view": User.objects.none(), | ||||||
|             "change": User.objects.none(), |             "change": User.objects.none(), | ||||||
|         } |         } | ||||||
|         if grant_permissions is not None: |         if set_permissions is not None: | ||||||
|             if "view" in grant_permissions: |             if "view" in set_permissions: | ||||||
|                 view_list = grant_permissions["view"] |                 view_list = set_permissions["view"] | ||||||
|                 user_dict["view"] = self._validate_user_ids(view_list) |                 user_dict["view"] = self._validate_user_ids(view_list) | ||||||
|             if "change" in grant_permissions: |             if "change" in set_permissions: | ||||||
|                 change_list = grant_permissions["change"] |                 change_list = set_permissions["change"] | ||||||
|                 user_dict["change"] = self._validate_user_ids(change_list) |  | ||||||
|         return user_dict |  | ||||||
| 
 |  | ||||||
|     revoke_permissions = serializers.DictField( |  | ||||||
|         label="Revoke permissions", |  | ||||||
|         allow_empty=True, |  | ||||||
|         required=False, |  | ||||||
|         write_only=True, |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     def validate_revoke_permissions(self, revoke_permissions): |  | ||||||
|         user_dict = { |  | ||||||
|             "view": User.objects.none(), |  | ||||||
|             "change": User.objects.none(), |  | ||||||
|         } |  | ||||||
|         if revoke_permissions is not None: |  | ||||||
|             if "view" in revoke_permissions: |  | ||||||
|                 view_list = revoke_permissions["view"] |  | ||||||
|                 user_dict["view"] = self._validate_user_ids(view_list) |  | ||||||
|             if "change" in revoke_permissions: |  | ||||||
|                 change_list = revoke_permissions["change"] |  | ||||||
|                 user_dict["change"] = self._validate_user_ids(change_list) |                 user_dict["change"] = self._validate_user_ids(change_list) | ||||||
|         return user_dict |         return user_dict | ||||||
| 
 | 
 | ||||||
| @ -147,18 +129,22 @@ class OwnedObjectSerializer(serializers.ModelSerializer): | |||||||
|         self.user = kwargs.pop("user", None) |         self.user = kwargs.pop("user", None) | ||||||
|         return super().__init__(*args, **kwargs) |         return super().__init__(*args, **kwargs) | ||||||
| 
 | 
 | ||||||
|     def _adjust_permissions(self, users, object, type="view", grant=True): |     def _set_permissions(self, permissions, object): | ||||||
|         if grant: |         for action in permissions: | ||||||
|             for user in users: |             permission = f"{action}_{object.__class__.__name__.lower()}" | ||||||
|                 assign_perm( |             users_to_add = permissions[action] | ||||||
|                     f"{type}_{object.__class__.__name__.lower()}", |             users_to_remove = get_users_with_perms( | ||||||
|                     user, |  | ||||||
|                 object, |                 object, | ||||||
|                 ) |                 only_with_perms_in=[permission], | ||||||
|         else: |             ).difference(users_to_add) | ||||||
|             for user in users: |             for user in users_to_remove: | ||||||
|                 remove_perm( |                 remove_perm(permission, user, object) | ||||||
|                     f"{type}_{object.__class__.__name__.lower()}", |             for user in users_to_add: | ||||||
|  |                 assign_perm(permission, user, object) | ||||||
|  |                 if action == "change": | ||||||
|  |                     # change gives view too | ||||||
|  |                     assign_perm( | ||||||
|  |                         f"view_{object.__class__.__name__.lower()}", | ||||||
|                         user, |                         user, | ||||||
|                         object, |                         object, | ||||||
|                     ) |                     ) | ||||||
| @ -169,55 +155,13 @@ class OwnedObjectSerializer(serializers.ModelSerializer): | |||||||
|         ): |         ): | ||||||
|             validated_data["owner"] = self.user |             validated_data["owner"] = self.user | ||||||
|         instance = super().create(validated_data) |         instance = super().create(validated_data) | ||||||
|         if "grant_permissions" in validated_data: |         if "set_permissions" in validated_data: | ||||||
|             self._adjust_permissions( |             self._set_permissions(validated_data["set_permissions"], instance) | ||||||
|                 validated_data["grant_permissions"]["view"], |  | ||||||
|                 instance, |  | ||||||
|             ) |  | ||||||
|             self._adjust_permissions( |  | ||||||
|                 validated_data["grant_permissions"]["change"], |  | ||||||
|                 instance, |  | ||||||
|                 "change", |  | ||||||
|             ) |  | ||||||
|         if "revoke_permissions" in validated_data: |  | ||||||
|             self._adjust_permissions( |  | ||||||
|                 validated_data["revoke_permissions"]["view"], |  | ||||||
|                 instance, |  | ||||||
|                 "view", |  | ||||||
|                 False, |  | ||||||
|             ) |  | ||||||
|             self._adjust_permissions( |  | ||||||
|                 validated_data["revoke_permissions"]["change"], |  | ||||||
|                 instance, |  | ||||||
|                 "change", |  | ||||||
|                 False, |  | ||||||
|             ) |  | ||||||
|         return instance |         return instance | ||||||
| 
 | 
 | ||||||
|     def update(self, instance, validated_data): |     def update(self, instance, validated_data): | ||||||
|         if "grant_permissions" in validated_data: |         if "set_permissions" in validated_data: | ||||||
|             self._adjust_permissions( |             self._set_permissions(validated_data["set_permissions"], instance) | ||||||
|                 validated_data["grant_permissions"]["view"], |  | ||||||
|                 instance, |  | ||||||
|             ) |  | ||||||
|             self._adjust_permissions( |  | ||||||
|                 validated_data["grant_permissions"]["change"], |  | ||||||
|                 instance, |  | ||||||
|                 "change", |  | ||||||
|             ) |  | ||||||
|         if "revoke_permissions" in validated_data: |  | ||||||
|             self._adjust_permissions( |  | ||||||
|                 validated_data["revoke_permissions"]["view"], |  | ||||||
|                 instance, |  | ||||||
|                 "view", |  | ||||||
|                 False, |  | ||||||
|             ) |  | ||||||
|             self._adjust_permissions( |  | ||||||
|                 validated_data["revoke_permissions"]["change"], |  | ||||||
|                 instance, |  | ||||||
|                 "change", |  | ||||||
|                 False, |  | ||||||
|             ) |  | ||||||
|         return super().update(instance, validated_data) |         return super().update(instance, validated_data) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -238,8 +182,7 @@ class CorrespondentSerializer(MatchingModelSerializer, OwnedObjectSerializer): | |||||||
|             "last_correspondence", |             "last_correspondence", | ||||||
|             "owner", |             "owner", | ||||||
|             "permissions", |             "permissions", | ||||||
|             "grant_permissions", |             "set_permissions", | ||||||
|             "revoke_permissions", |  | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -256,8 +199,7 @@ class DocumentTypeSerializer(MatchingModelSerializer, OwnedObjectSerializer): | |||||||
|             "document_count", |             "document_count", | ||||||
|             "owner", |             "owner", | ||||||
|             "permissions", |             "permissions", | ||||||
|             "grant_permissions", |             "set_permissions", | ||||||
|             "revoke_permissions", |  | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -342,8 +284,7 @@ class TagSerializer(MatchingModelSerializer, OwnedObjectSerializer): | |||||||
|             "document_count", |             "document_count", | ||||||
|             "owner", |             "owner", | ||||||
|             "permissions", |             "permissions", | ||||||
|             "grant_permissions", |             "set_permissions", | ||||||
|             "revoke_permissions", |  | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     def validate_color(self, color): |     def validate_color(self, color): | ||||||
| @ -426,8 +367,7 @@ class DocumentSerializer(DynamicFieldsModelSerializer, OwnedObjectSerializer): | |||||||
|             "archived_file_name", |             "archived_file_name", | ||||||
|             "owner", |             "owner", | ||||||
|             "permissions", |             "permissions", | ||||||
|             "grant_permissions", |             "set_permissions", | ||||||
|             "revoke_permissions", |  | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -454,8 +394,7 @@ class SavedViewSerializer(OwnedObjectSerializer): | |||||||
|             "filter_rules", |             "filter_rules", | ||||||
|             "owner", |             "owner", | ||||||
|             "permissions", |             "permissions", | ||||||
|             "grant_permissions", |             "set_permissions", | ||||||
|             "revoke_permissions", |  | ||||||
|         ] |         ] | ||||||
| 
 | 
 | ||||||
|     def update(self, instance, validated_data): |     def update(self, instance, validated_data): | ||||||
| @ -749,8 +688,7 @@ class StoragePathSerializer(MatchingModelSerializer, OwnedObjectSerializer): | |||||||
|             "document_count", |             "document_count", | ||||||
|             "owner", |             "owner", | ||||||
|             "permissions", |             "permissions", | ||||||
|             "grant_permissions", |             "set_permissions", | ||||||
|             "revoke_permissions", |  | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     def validate_path(self, path): |     def validate_path(self, path): | ||||||
|  | |||||||
| @ -3015,7 +3015,7 @@ class TestApiUser(APITestCase): | |||||||
|         response = self.client.get(self.ENDPOINT) |         response = self.client.get(self.ENDPOINT) | ||||||
| 
 | 
 | ||||||
|         self.assertEqual(response.status_code, 200) |         self.assertEqual(response.status_code, 200) | ||||||
|         self.assertEqual(response.data["count"], 3)  # AnonymousUser |         self.assertEqual(response.data["count"], 2) | ||||||
|         returned_user2 = response.data["results"][2] |         returned_user2 = response.data["results"][2] | ||||||
| 
 | 
 | ||||||
|         self.assertEqual(returned_user2["username"], user1.username) |         self.assertEqual(returned_user2["username"], user1.username) | ||||||
|  | |||||||
| @ -256,6 +256,7 @@ class DocumentViewSet( | |||||||
|         else: |         else: | ||||||
|             fields = None |             fields = None | ||||||
|         serializer_class = self.get_serializer_class() |         serializer_class = self.get_serializer_class() | ||||||
|  |         kwargs.setdefault("user", self.request.user)  # PassUserMixin | ||||||
|         kwargs.setdefault("context", self.get_serializer_context()) |         kwargs.setdefault("context", self.get_serializer_context()) | ||||||
|         kwargs.setdefault("fields", fields) |         kwargs.setdefault("fields", fields) | ||||||
|         return serializer_class(*args, **kwargs) |         return serializer_class(*args, **kwargs) | ||||||
|  | |||||||
| @ -39,7 +39,9 @@ class FaviconView(View): | |||||||
| class UserViewSet(ModelViewSet): | class UserViewSet(ModelViewSet): | ||||||
|     model = User |     model = User | ||||||
| 
 | 
 | ||||||
|     queryset = User.objects.exclude(username="consumer").order_by(Lower("username")) |     queryset = User.objects.exclude( | ||||||
|  |         username__in=["consumer", "AnonymousUser"], | ||||||
|  |     ).order_by(Lower("username")) | ||||||
| 
 | 
 | ||||||
|     serializer_class = UserSerializer |     serializer_class = UserSerializer | ||||||
|     pagination_class = StandardPagination |     pagination_class = StandardPagination | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user