Django-guardian: Permissões globais vs permissões de objeto

Criado em 22 dez. 2015  ·  16Comentários  ·  Fonte: django-guardian/django-guardian

Parece haver uma série de bugs devido a algumas rotinas que usam permissões globais e outras apenas que usam permissões de objeto. Fechará os bugs relacionados e fará referência a eles aqui.

API change Enhancement

Todos 16 comentários

Sim para isso!

permission_required_or_403 tem o parâmetro accept_global_perms, mas não há como em uma visão fazer a mesma coisa com get_obj_perms

Proponho uma tag get_obj_perms_with_global que inclui permanências globais.

Não sei se você já começou a trilhar esse caminho, mas vou começar a trabalhar em um patch para fazer isso; se você já começou, sinta-se à vontade para me impedir :)

PS Acho que há um argumento a ser feito de que o comportamento padrão deve ser incluir permissões globais, parece-me que quando você pergunta "o usuário X pode fazer Y para o objeto Z", isso implica verificar todos os usuários / objetos, grupos / objetos , usuário / global, grupo / permissões globais. Mas isso pode ser apenas devido à maneira como eu o uso.

Dito tudo isso, é bastante simples verificar as permissões globais separadamente ... Hrmmm.

Pesticles: há questões suficientes sobre o guardião como prova de como isso é confuso. Nós o pegamos a cada seis meses ... se request.user.has_access ('foo', obj) deveria ser verdadeiro se eles tivessem permissões globais, mas não permissões de nível de objeto. Escrever o cheque duas vezes é nojento.

O que precisa acontecer para mudar isso?

Acho que alguém precisa escrever uma solicitação de pull ... Idealmente, de forma que não quebre o código existente (se isso é lógico e viável ou não, não sei).

Problema antigo, mas ainda não vejo uma solicitação de pull. Algumas notícias sobre este? Estou tendo o mesmo comportamento, o que não acho muito previsível. Muitíssimo obrigado!

Eu adicionei alguns comentários ao nº 49, uma vez que tinha mais insights sobre a questão de se e como fazer fallback para os globais quando o nível do objeto falha. Não tenho certeza se os problemas encerrados geram notificações, portanto, estou adicionando isso aqui.

Dependendo das decisões de design que estão sendo feitas, tenho a intenção de trabalhar em algumas dessas questões.

Eu ficaria feliz em ajudar com esses problemas.

327 parece fixo para mim.

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

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

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

assign_perm ('add_school', brandon, school)

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

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

get_users_with_perms (escola, attach_perms = True, with_superusers = True, with_group_users = False)
{: [],: ['adicionar_escola', 'alterar_escola', 'excluir_escola']}

assign_perm ('add_school', mehmet, school)

get_users_with_perms (escola, attach_perms = True, with_superusers = True, with_group_users = False)
{: [],: ['adicionar_escola', 'alterar_escola', 'excluir_escola']}

get_users_with_perms (escola, attach_perms = True, with_superusers = False, with_group_users = False)
{: ['adicionar_school'],: ['adicionar_escola']}

No # 155:

A adição das duas linhas a seguir é solicitada a get_obj_perms_field_choices (self) :

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

para excluir as permissões padrão do modelo. Em primeiro lugar, não estou certo de como intersection faria isso. Em segundo lugar, isso não parece estar relacionado às permissões de objeto versus modelo. Por favor, me corrija se eu estiver faltando alguma coisa.

Mas, ao examinar isso, percebi que é necessário haver uma separação entre as permissões de objeto e modelo em:

    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á salvando no nível do objeto qualquer permissão que esteja faltando, enquanto na minha opinião, qualquer permissão disponível no nível do modelo deve ser ignorada ou uma opção para esse fim deve ser fornecida.

Eu acho que uma configuração global como GUARDIAN_FALLBACK_TO_MODEL=False e um argumento para métodos aplicáveis ​​como fallback_to_model=False necessários para delinear adequadamente as permissões de objeto e permissões de modelo. O valor padrão de False garante compatibilidade com versões anteriores. Se qualquer uma das configurações global ou do argumento for True, o fallback deverá ocorrer.

1 para GUARDIAN_FALLBACK_TO_MODEL.

De acordo com a discussão em # 49, acho que a configuração também funcionaria bem para controlar se ObjectPermissionBackend era explícito ou não.

Criei uma solicitação de pull (# 546). Ele permite que as funções de verificador na opção core.py façam fallback para (ou incluam) permissões de nível de modelo. Outros módulos também precisam ser revistos. Estou pensando em revê-los à medida que os uso. Se alguém quiser entrar, seja bem-vindo.

Parece que o nº 327 não existe mais. # 332 é corrigido pela solicitação pull acima, se aceita. Resta apenas um problema secundário relacionado ao nº 155 (mencionado acima). Se isso também fosse resolvido (ou movido para um problema separado), esse problema poderia ser encerrado, eu acho.

As permissões globais ainda não são respeitadas para a permissão de nível de objeto se configurada. Estou errado aqui?

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)  # []

E o que a configuração GUARDIAN_GLOBAL_PERMISSIONS_CARRY_OVER ou FALLBACK_TO_MODEL faz? Nenhum dos dois parece estar documentado.

Não seria suficiente adicionar isso a core.py ?

get_user_perms:126 que parece ser o centro de todas as verificações de permissão do usuário; alternativamente acionável usando um sinalizador booleano

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
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

Allan-Nava picture Allan-Nava  ·  4Comentários

Dzejkob picture Dzejkob  ·  28Comentários

lukaszb picture lukaszb  ·  14Comentários

johnthagen picture johnthagen  ·  9Comentários

Allan-Nava picture Allan-Nava  ·  35Comentários