6

Tôi đang sử dụng django-guardian để quản lý quyền đối với mỗi đối tượng.Đối tượng có quyền được chỉ định bởi django-guardian không hiển thị trong quản trị

Đối với một người dùng nào đó Tôi cho phép tất cả các phép trên một đối tượng:

joe = User.objects.get(username="joe") 

mytask = Task.objects.get(pk=1) 

assign('add_task', joe, mytask) 
assign('change_task', joe, mytask) 
assign('delete_task', joe, mytask) 

và tôi nhận được, như mong đợi:

In [57]: joe.has_perm("add_task", mytask) 
Out[57]: True 

In [58]: joe.has_perm("change_task", mytask) 
Out[58]: True 

In [59]: joe.has_perm("delete_task", mytask) 
Out[59]: True 

Trong admin.py tôi cũng làm cho TaskAdmin kế thừa từ GuardedModelAdmin thay của admin.ModelAdmin

Bây giờ khi tôi kết nối với trang web của mình với joe, trên quản trị viên tôi nhận được:

You don't have permission to edit anything 

Tôi không được phép chỉnh sửa đối tượng mytask?

Tôi có phải đặt một số quyền bằng cách sử dụng hệ thống cấp phép dựa trên mô hình tích hợp không?

Tôi có thiếu gì không?

EDIT

Tôi cố gắng để thêm tùy chọn user_can_access_owned_objects_only, mà là vụ để đối phó với vấn đề của tôi, nhưng tôi vẫn không thể nhìn thấy bất cứ điều gì trong quản trị của tôi ...

class TaskAdmin(GuardedModelAdmin): 

    user_can_access_owned_objects_only = True 

    pass 

admin.site.register(Task, TaskAdmin) 

Thank bạn

Trả lời

3

Để chỉ xem các trường hợp thuộc sở hữu của người dùng hiện tại, tôi cấp cho anh ấy tất cả sự cho phép

add_task=Permission.objects.get(codename="add_task") 
change_task=Permission.objects.get(codename="change_task") 
delete_task=Permission.objects.get(codename="delete_task") 

joe.user_permissions.add(add_task) 
joe.user_permissions.add(change_task) 
joe.user_permissions.add(delete_task) 

sau đó tôi đặt cho phép trên một số ít trường hợp sử dụng guardian.shortcuts.assign, và tôi lọc queryset trong admin:

class TaskAdmin(admin.ModelAdmin): 

    def queryset(self, request): 
      if request.user.is_superuser: 
       return super(TaskAdmin, self).queryset(request) 
      return get_objects_for_user(user=request.user, perms=['add_task', 'change_task', 'delete_task'], klass=Task) 

Đó là xa hoàn hảo, nhưng tôi không thể tìm thấy bất kỳ giải pháp khác .

2

Quản trị viên Django, đặc biệt là giao dịch với quyền hạn w/change, hơi thô sơ. Phương thức nội bộ ModelAdmin.has_change_permission() bao gồm việc kiểm tra quyền của view thiếu thực tế.

Thứ hai, GuardedModelAdmin mang quyền sở hữu kiểm tra (thông qua user_can_access_owned_objects_only) và biểu mẫu để quản lý quyền cấp hàng. Nó không cung cấp bất kỳ chính sách truy cập cấp hàng nào khác cho Quản trị Django.

Đối với cảnh phép cấp hàng tiêu biểu trong Django Admin, tôi muốn đề nghị mã, ở đây tôi đã giới thiệu một tùy chọn 'xem' phép:

class ExtendedGuardedModelAdmin(GuardedModelAdmin): 
    def queryset(self, request): 
     qs = super(ExtendedGuardedModelAdmin, self).queryset(request) 
     # Check global permission 
     if super(ExtendedGuardedModelAdmin, self).has_change_permission(request) \ 
      or (not self.list_editable and self.has_view_permission(request)): 
       return qs 
     # No global, filter by row-level permissions. also use view permission if the changelist is not editable 
     if self.list_editable: 
      return get_objects_for_user(request.user, [self.opts.get_change_permission()], qs) 
     else: 
      return get_objects_for_user(request.user, [self.opts.get_change_permission(), self.get_view_permission(
)], qs, any_perm=True) 

    def has_change_permission(self, request, obj=None): 
     if super(ExtendedGuardedModelAdmin, self).has_change_permission(request, obj): 
      return True 
     if obj is None: 
      # Here check global 'view' permission or if there is any changeable items 
      return self.has_view_permission(request) or self.queryset(request).exists() 
     else: 
      # Row-level checking 
      return request.user.has_perm(self.opts.get_change_permission(), obj) 

    def get_view_permission(self): 
     return 'view_%s' % self.opts.object_name.lower() 

    def has_view_permission(self, request, obj=None): 
     return request.user.has_perm(self.opts.app_label + '.' + self.get_view_permission(), obj) 

    def has_delete_permission(self, request, obj=None): 
     return super(ExtendedGuardedModelAdmin, self).has_delete_permission(request, obj) \ 
       or (obj is not None and request.user.has_perm(self.opts.get_delete_permission(), obj)) 

Bằng cách này, bạn có thể đạt được kiểm tra sự cho phép nhiều-linh hoạt, dễ sử dụng cho phép hiện nay là toàn cầu, sử dụng obj-quyền được cấp hàng dựa trên:

  • joe.user_permissions.add(add_task)
    joe có thể thêm nhiệm vụ mới (không có row-level 'thêm' phép)
  • joe.user_permissions.add(change_task)
    joe có thể thay đổi tất cả các nhiệm vụ
  • joe.user_permissions.add(delete_task)
    joe có thể xóa tất cả các nhiệm vụ
  • assign(Task._meta.get_change_permission(), joe, obj)
    joe có thể thay đổi công tác obj, xem danh sách thay đổi chứa obj cũng như nhiệm vụ thay đổi khác .
  • assign(Task._meta.get_delete_permission(), joe, obj)
    joe thể xóa Task obj
  • assign('view_task', joe, obj)
    [tùy chọn] joe có thể xem Task obj (bạn có thể muốn kiểm tra sự cho phép này tại tùy chỉnh xem trang quản trị)
  • joe.user_permissions.add(Permission.objects.get(codename='view_task', ...))
    [tùy chọn] joe có thể xem Tất cả các tác vụ trong danh sách thay đổi, miễn là danh sách thay đổi không thể chỉnh sửa nội dòng. Điều này rất hữu ích nếu joe có thể nhận các vật phẩm từ raw_id_fields với quyền thay đổi.
  • ...

Bạn có thể bỏ qua quyền 'xem' an toàn nếu nó vô ích cho bạn.

Hiện nay, django.contrib.admin.util.get_deleted_objects không tôn vinh những obj trong việc kiểm tra sự cho phép, nếu bạn cần phải kiểm tra sự cho phép row-level trong xóa, vá các get_deleted_objects bằng cách thay đổi dòng if not user.has_perm(p):-if not user.has_perm(p, obj):. Vé tương đối là 13539 & 16862

+0

Bạn nên vượt qua 'yêu cầu' và không 'request.user' trong self.has_view_permission – Don

+0

@Don Yep, nhờ chỉ ra rằng =) – okm

+0

Có thể được versioning thay đổi liên quan đến vấn đề, nhưng chạy vào Đối tượng 'Tùy chọn' không có thuộc tính 'get_change_permission' – Mutant

Các vấn đề liên quan