Django-guardian: Permisos globales frente a permisos de objeto

Creado en 22 dic. 2015  ·  16Comentarios  ·  Fuente: django-guardian/django-guardian

Parece haber una serie de errores debido a que algunas rutinas usan permisos globales y otras solo usan permisos de objetos. Cerrará los errores relacionados y hará referencia a ellos aquí.

API change Enhancement

Todos 16 comentarios

¡Sí a esto!

allow_required_or_403 tiene el parámetro accept_global_perms, pero no hay forma en una vista de hacer lo mismo con get_obj_perms

Propongo una etiqueta get_obj_perms_with_global que incluye permisos globales.

No sé si ya has empezado por este camino, pero empezaré a trabajar en un parche para hacerlo; si ya has comenzado, no dudes en detenerme :)

PD: Creo que se puede argumentar que el comportamiento predeterminado debería ser incluir permisos globales, me parece que cuando preguntas "¿puede el usuario X hacer Y al objeto Z", eso implica verificar todo el usuario / objeto, grupo / objeto , usuario / global, grupo / permisos globales. Pero eso podría deberse a la forma en que lo uso.

Habiendo dicho todo eso, es bastante sencillo verificar los permisos globales por separado ... Hrmmm.

Pesticles: hay suficientes problemas en guardian como testimonio de lo confuso que es esto. Nos muerde cada seis meses ... si request.user.has_access ('foo', obj) debería ser verdadero si tienen permisos globales pero no permisos a nivel de objeto. Escribir el cheque dos veces es asqueroso.

¿Qué debe suceder para que esto cambie?

Creo que alguien necesita escribir una solicitud de extracción ... Idealmente de tal manera que no rompa el código existente (si esto es sensato y factible o no, no lo sé).

Problema antiguo, pero todavía no veo una solicitud de extracción. ¿Alguna noticia sobre este? Me encuentro con el mismo comportamiento, que creo que no es muy predecible. ¡Gracias un montón!

Agregué algunos comentarios al n. ° 49, ya que tenía más información sobre la cuestión de si, y cómo, recurrir a los globales cuando falla el nivel de objeto. No estoy seguro de si los problemas cerrados generan una notificación, por lo que agrego esto aquí.

Dependiendo de las decisiones de diseño que se tomen, tengo la intención de trabajar en algunos de estos temas.

Estaré encantado de ayudar con estos problemas.

327 me parece fijo.

''
brandon = Person.objects.get (first_name = 'BRANDON')
brandon.is_superuser
Falso

escuela = School.objects.get (pk = 1)

get_users_with_perms (escuela, attach_perms = True, with_superusers = False, with_group_users = False)
{}

asignar_perm ('agregar_escuela', brandon, escuela)

get_users_with_perms (escuela, attach_perms = True, with_superusers = False, with_group_users = False)
{: ['add_school']}

mehmet = Person.objects.get (first_name = 'Mehmet')
mehmet.is_superuser
Cierto

get_users_with_perms (escuela, attach_perms = True, with_superusers = True, with_group_users = False)
{: [],: ['add_school', 'change_school', 'delete_school']}

asignar_perm ('agregar_escuela', mehmet, escuela)

get_users_with_perms (escuela, attach_perms = True, with_superusers = True, with_group_users = False)
{: [],: ['add_school', 'change_school', 'delete_school']}

get_users_with_perms (escuela, attach_perms = True, with_superusers = False, with_group_users = False)
{: ['add_school'],: ['add_school']}

En el n. ° 155:

Se solicita la adición de las siguientes dos líneas a get_obj_perms_field_choices (self) :

        if self.exclude_default:
            choices = list(set(choices).intersection(self.obj._meta.permissions))

para excluir los permisos predeterminados del modelo. Primero, no tengo claro cómo intersection haría eso. En segundo lugar, eso no parece estar relacionado con los permisos de objeto frente a modelo. Por favor corríjame si me falta algo.

Pero, mientras investigaba eso, noté que debe haber una separación entre los permisos de objeto y modelo en:

    def save_obj_perms(self):
        """
        Saves selected object permissions by creating new ones and removing
        those which were not selected but already exists.

        Should be called *after* form is validated.
        """
        perms = self.cleaned_data[self.get_obj_perms_field_name()]
        model_perms = [c[0] for c in self.get_obj_perms_field_choices()]

        to_remove = set(model_perms) - set(perms)
        for perm in to_remove:
            remove_perm(perm, self.user, self.obj)

        for perm in perms:
            assign_perm(perm, self.user, self.obj)

Parece que está guardando a nivel de objeto cualquier permiso que falte, mientras que en mi opinión, cualquier permiso disponible a nivel de modelo debe omitirse, o debe proporcionarse una opción para ese fin.

Creo que se necesita una configuración global como GUARDIAN_FALLBACK_TO_MODEL=False y un argumento para los métodos aplicables como fallback_to_model=False para delinear correctamente los permisos de los objetos y los permisos del modelo. El valor predeterminado de False garantiza la compatibilidad con versiones anteriores. Si la configuración global o del argumento es Verdadero, se debe realizar una reserva.

+1 para GUARDIAN_FALLBACK_TO_MODEL.

Según la discusión sobre el n. ° 49, creo que la configuración también funcionaría bien para controlar si ObjectPermissionBackend era explícito o no.

Creé una solicitud de extracción (# 546). Permite que las funciones de verificación en la opción core.py recurran a (o incluyan) permisos de nivel de modelo. También es necesario revisar otros módulos. Planeo revisarlos mientras los uso. Si alguien quisiera participar, será bienvenido.

Parece que el número 327 ya no existe. # 332 se corrige mediante la solicitud de extracción anterior si se acepta. Solo queda un problema secundario relacionado con el n. ° 155 (mencionado anteriormente). Si eso también se solucionó (o se trasladó a un tema separado), creo que este problema podría cerrarse.

Los permisos globales todavía no se respetan para el permiso de nivel de objeto si se establecen, ¿me equivoco aquí?

u = User.objects.get(id=1)
c = Client.objects.get(id=1)
assign_perm('core.change_client', u)
u = User.objects.get(id=1)  # reloading user for perm refresh
u.has_perm('core.change_client')  # True
u.has_perm('core.change_client', c)  # False
u.has_perm('change_client', c)  # False
get_perms(u, c)  # []

¿Y qué hace el ajuste GUARDIAN_GLOBAL_PERMISSIONS_CARRY_OVER o FALLBACK_TO_MODEL ? Ninguno parece estar documentado.

¿No sería suficiente agregar esto a core.py ?

get_user_perms:126 que parece ser el centro de todas las comprobaciones de permisos de los usuarios; alternativamente activable usando una bandera booleana

def get_user_perms(self, obj):
    # ....
    user_global_perms = Permission.objects.filter(content_type=ctype)\
                                        .filter(user=self.user)\
                                        .values_list('codename', flat=True)
    user_object_perms = user_perms_qs.values_list("codename", flat=True)
    user_perms = list(chain(user_global_perms, user_object_perms))
    return user_perms
¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

g-as picture g-as  ·  10Comentarios

Allan-Nava picture Allan-Nava  ·  35Comentarios

Allan-Nava picture Allan-Nava  ·  4Comentarios

Dzejkob picture Dzejkob  ·  28Comentarios

ad-m picture ad-m  ·  13Comentarios