6

Estoy usando django-guardian para administrar permisos por objeto.Objetos con permisos asignados por django-guardian no visibles en admin

Para un usuario dado Doy permiso todos los permisos en un objeto:

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) 

y consigo, como se esperaba:

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 

En admin.py que también hacen TaskAdmin hereda de GuardedModelAdmin vez de admin.ModelAdmin

Ahora cuando me conecto a mi sitio con joe, en el administrador obtengo:

You don't have permission to edit anything 

¿Se supone que no puedo editar el objeto mytask?

¿Debo configurar algunos permisos con el sistema de permisos basado en modelos integrado?

¿E-mail perdiendo cualquier cosa?

EDITAR

He intentado añadir la opción user_can_access_owned_objects_only, que se supone que lidiar con mi problema, pero todavía no puedo ver nada en mi administración ...

class TaskAdmin(GuardedModelAdmin): 

    user_can_access_owned_objects_only = True 

    pass 

admin.site.register(Task, TaskAdmin) 

Gracias que

Respuesta

3

para ver solo los casos de propiedad del usuario actual, le da todos los permisos

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) 

entonces establecer el permiso en algunos casos el uso de guardian.shortcuts.assign, y filtrar el conjunto de consultas en el 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) 

Está lejos de ser perfecta, pero no puedo encontrar ninguna otra solución .

2

El administrador de Django, especialmente está tratando con permiso de change, es un poco grueso. El método interno ModelAdmin.has_change_permission() cubre la comprobación del permiso view que realmente falta.

En segundo lugar, GuardedModelAdmin trae comprobación de propiedad (a través de user_can_access_owned_objects_only) y formularios para administrar los permisos de nivel de fila. No proporciona ninguna otra política de acceso a filas al administrador de Django.

Para la escena permiso de nivel de fila típico en la administración de Django, me gustaría sugerir el código, aquí he introducido una opción 'vista' permiso:

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

De esta manera, se podría lograr la comprobación de permisos más flexibles, fáciles de permisos ahora son globales,-obj usuario en permisos están a nivel de fila en base:

  • joe.user_permissions.add(add_task)
    Joe podría añadir nuevas tareas (no existe a nivel de fila 'añadir' permiso)
  • joe.user_permissions.add(change_task)
    Joe podría cambiar todas las tareas
  • joe.user_permissions.add(delete_task)
    Joe podría eliminar todas las tareas
  • assign(Task._meta.get_change_permission(), joe, obj)
    Joe podría cambiar el Grupo de obj, ver la lista de cambios que contiene el obj, así como otras tareas cambiantes .
  • assign(Task._meta.get_delete_permission(), joe, obj)
    Joe podría eliminar la tarea obj
  • assign('view_task', joe, obj)
    [opcional] Joe pudo ver la tarea obj (es posible que desee comprobar este permiso en personalizado página de vista de administración)
  • joe.user_permissions.add(Permission.objects.get(codename='view_task', ...))
    [opcional] joe podría ver Todas las tareas en la lista de cambios, siempre que la lista de cambios no sea editable en línea. Esto es útil si Joe puede recoger elementos de raw_id_fields sin permiso de cambio.
  • ...

Se podía ignorar el permiso 'vista' con seguridad si es inútil para usted.

Actualmente, django.contrib.admin.util.get_deleted_objects no honra al obj durante la comprobación de autorización, si es necesario comprobar el permiso de nivel de fila durante el borrado, parchear el get_deleted_objects mediante la modificación de la línea a if not user.has_perm(p):if not user.has_perm(p, obj):. Las entradas relativas son 13539 & 16862

+0

Debe pasar 'solicitud' y no 'request.user' en self.has_view_permission – Don

+0

@Don Sí, gracias por señalar que =) – okm

+0

podría ser de versiones cuestión relacionada con el cambio, pero el funcionamiento en El objeto 'Opciones' no tiene ningún atributo 'get_change_permission' – Mutant

Cuestiones relacionadas