6

不可見的,我爲了每個對象的權限管理使用django-guardian分配權限。對象與Django的監護人管理

對於一個給定用戶本人允許的所有權限一個對象:

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) 

,我得到的,如預期:

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 

在admin.py我也會讓TaskAdmin從GuardedModelAdmin而不是繼承admin.ModelAdmin

現在,當我連接到我的網站與喬,在管理員我得到:

You don't have permission to edit anything 

我不是應該能夠編輯對象mytask?

我必須使用內置的基於模型的權限系統設置一些權限?

我錯過了什麼?

編輯

我嘗試添加選項user_can_access_owned_objects_only,這是爲了對付我的問題,但我仍然看不到任何東西在我的管理...

class TaskAdmin(GuardedModelAdmin): 

    user_can_access_owned_objects_only = True 

    pass 

admin.site.register(Task, TaskAdmin) 

謝謝你

回答

3

爲了只看到當前用戶擁有的實例,我給他所有權限

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) 

然後我設置少數情況下,允許使用guardian.shortcuts.assign,我篩選查詢集在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) 

它遠非完美,但我找不到任何其他的解決辦法。

2

Django管理,特別是它在處理瓦特/ change許可,有點粗粒度。內部方法ModelAdmin.has_change_permission()涵蓋實際上缺少的view權限的檢查。

其次,GuardedModelAdmin帶來了所有權檢查(通過user_can_access_owned_objects_only)和管理行級權限的表單。它沒有向Django Admin提供任何其他行級訪問策略。

對於Django管理典型的行級權限的場景,我想建議的代碼,在這裏我介紹了一個可選的「查看」的權限:

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)) 

通過這種方式,你可以實現更靈活的權限檢查,用戶權限現在是全球性的,用戶OBJ-權限基於行級:

  • joe.user_permissions.add(add_task)
    喬添加新的任務(沒有行級「加」許可)
  • joe.user_permissions.add(change_task)
    喬可以改變所有的任務
  • joe.user_permissions.add(delete_task)
    喬可以刪除所有的任務
  • assign(Task._meta.get_change_permission(), joe, obj)
    喬更改任務OBJ,看到包含變更列表的OBJ以及其他變化的任務。
  • assign(Task._meta.get_delete_permission(), joe, obj)
    喬刪除任務OBJ
  • assign('view_task', joe, obj)
    [可選]喬查看任務OBJ(你可能想在定製的管理視圖頁,以檢查此權限)
  • joe.user_permissions.add(Permission.objects.get(codename='view_task', ...))
    [可選] joe可以查看更改列表中的所有任務,只要更改列表不可內聯編輯。如果joe可以從沒有更改權限的raw_id_fields中拾取項目,這很有用。
  • ...

你可以忽略「查看」的權限安全,如果它是你沒用。

目前,django.contrib.admin.util.get_deleted_objects不許可的檢查過程中兌現obj的,如果你需要在刪除檢查行級權限,通過修改if not user.has_perm(p):if not user.has_perm(p, obj):修補get_deleted_objects。相對門票13539 & 16862

+0

你應該通過在self.has_view_permission – Don

+0

@Don是的「請求」,而不是「request.user」,感謝指出=) – okm

+0

可能是版本變化相關的問題,但運行到'選項'對象沒有屬性'get_change_permission' – Mutant