- filtering a queryset based on a user object and eventually a permission
name
- returning if a user has a permission on an object instance
Currently, permission backend allows developers to implement the first
mechanism: you can allow a specific permission on an object with the
permission backend.
This works extremely well even for complex use cases: you get an model
object, a user, a permission name and you can return True.
Exemple:
{{{
def has_perm(self, user_obj, perm, obj=None):
if not user_obj.is_authenticated or not isinstance(obj,
MRSRequest):
return False
return (
user_obj.profile == 'admin'
or obj.caisse in user_obj.caisses.all()
)
}}}
However, permission framework does not include a the first security
feature mentioned: getting a filtered queryset with objects a user should
be able to see, eventually for a given permission. Such implementation
could look like:
{{{
def filter_queryset(self, user_obj, perm, queryset=None):
if not queryset.model == MRSRequest:
return queryset
if not user_obj.is_authenticated:
return queryset.none()
return queryset.filter(caisse__in=user_obj.caisses.all())
}}}
The admin views could use this, and django.contrib.auth could provide
generic views extensions which do check permissions.
--
Ticket URL: <https://code.djangoproject.com/ticket/31093>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
Old description:
New description:
Permissions on objects are based on two mechanisms that developers have to
implement:
- returning if a user has a permission on an object instance
- filtering a queryset based on a user object and eventually a permission
name
Currently, permission backend allows developers to implement the first
mechanism: you can allow a specific permission on an object with the
permission backend.
This works extremely well even for complex use cases: you get an model
object, a user, a permission name and you can return True.
Exemple:
{{{
def has_perm(self, user_obj, perm, obj=None):
if not user_obj.is_authenticated or not isinstance(obj,
MRSRequest):
return False
return (
user_obj.profile == 'admin'
or obj.caisse in user_obj.caisses.all()
)
}}}
However, permission framework should also allow developers to implement
the second security mechanism: getting a filtered queryset with objects a
user should be able to see, eventually for a given permission. Such
implementation could look like:
{{{
def filter_queryset(self, user_obj, perm, queryset=None):
if not queryset.model == MRSRequest:
return queryset
if not user_obj.is_authenticated:
return queryset.none()
return queryset.filter(caisse__in=user_obj.caisses.all())
}}}
The admin views could use this, and django.contrib.auth could provide
generic views extensions which do check permissions.
--
--
Ticket URL: <https://code.djangoproject.com/ticket/31093#comment:1>
Old description:
> Permissions on objects are based on two mechanisms that developers have
> to implement:
>
> - returning if a user has a permission on an object instance
> - filtering a queryset based on a user object and eventually a permission
> name
>
> Currently, permission backend allows developers to implement the first
> mechanism: you can allow a specific permission on an object with the
> permission backend.
>
> This works extremely well even for complex use cases: you get an model
> object, a user, a permission name and you can return True.
>
> Exemple:
>
> {{{
> def has_perm(self, user_obj, perm, obj=None):
> if not user_obj.is_authenticated or not isinstance(obj,
> MRSRequest):
> return False
>
> return (
> user_obj.profile == 'admin'
> or obj.caisse in user_obj.caisses.all()
> )
> }}}
>
> However, permission framework should also allow developers to implement
> the second security mechanism: getting a filtered queryset with objects a
> user should be able to see, eventually for a given permission. Such
> implementation could look like:
>
> {{{
> def filter_queryset(self, user_obj, perm, queryset=None):
> if not queryset.model == MRSRequest:
> return queryset
>
> if not user_obj.is_authenticated:
> return queryset.none()
>
> return queryset.filter(caisse__in=user_obj.caisses.all())
> }}}
>
> The admin views could use this, and django.contrib.auth could provide
> generic views extensions which do check permissions.
New description:
Permissions on objects are based on two mechanisms that developers have to
implement:
- returning if a user has a permission on an object instance
- filtering a queryset based on a user object and eventually a permission
name
Currently, permission backend allows developers to implement the first
mechanism: you can allow a specific permission on an object with the
permission backend.
This works extremely well even for complex use cases: you get an model
object, a user, a permission name and you can return True.
Exemple:
{{{
def has_perm(self, user_obj, perm, obj=None):
if not user_obj.is_authenticated or not isinstance(obj,
MRSRequest):
return False
return (
user_obj.profile == 'admin'
or obj.caisse in user_obj.caisses.all()
)
}}}
However, permission framework should also allow developers to implement
the second security mechanism: getting a filtered queryset with objects a
user should be able to see, eventually for a given permission. Such
implementation could look like:
{{{
def filter_queryset(self, user_obj, perm, queryset=None):
if not queryset.model == MRSRequest:
return queryset
if not user_obj.is_authenticated:
return queryset.none()
return queryset.filter(caisse__in=user_obj.caisses.all())
}}}
The admin views could use this, and django.contrib.auth could provide
generic views extensions which do check permissions, removing the need to
share a mixin that just does return a Mixin with a get_queryset method to
complement the code that they have in the permission backend. It would
reduce chances to make a mistake when updating permission code if it's all
at the same place, an opinion that I consider suited for a framework like
Django.
--
--
Ticket URL: <https://code.djangoproject.com/ticket/31093#comment:2>
Old description:
> Permissions on objects are based on two mechanisms that developers have
> to implement:
>
> - returning if a user has a permission on an object instance
> - filtering a queryset based on a user object and eventually a permission
> name
>
> Currently, permission backend allows developers to implement the first
> mechanism: you can allow a specific permission on an object with the
> permission backend.
>
> This works extremely well even for complex use cases: you get an model
> object, a user, a permission name and you can return True.
>
> Exemple:
>
> {{{
> def has_perm(self, user_obj, perm, obj=None):
> if not user_obj.is_authenticated or not isinstance(obj,
> MRSRequest):
> return False
>
> return (
> user_obj.profile == 'admin'
> or obj.caisse in user_obj.caisses.all()
> )
> }}}
>
> However, permission framework should also allow developers to implement
> the second security mechanism: getting a filtered queryset with objects a
> user should be able to see, eventually for a given permission. Such
> implementation could look like:
>
> {{{
> def filter_queryset(self, user_obj, perm, queryset=None):
> if not queryset.model == MRSRequest:
> return queryset
>
> if not user_obj.is_authenticated:
> return queryset.none()
>
> return queryset.filter(caisse__in=user_obj.caisses.all())
> }}}
>
> The admin views could use this, and django.contrib.auth could provide
> generic views extensions which do check permissions, removing the need to
> share a mixin that just does return a Mixin with a get_queryset method to
> complement the code that they have in the permission backend. It would
> reduce chances to make a mistake when updating permission code if it's
> all at the same place, an opinion that I consider suited for a framework
> like Django.
New description:
Permissions on objects are based on two mechanisms that developers have to
implement:
- returning if a user has a permission on an object instance
- filtering a queryset based on a user object and eventually a permission
name
Currently, permission backend allows developers to implement the first
mechanism: you can allow a specific permission on an object with the
permission backend.
This works extremely well even for complex use cases: you get an model
object, a user, a permission name and you can return True.
Exemple:
{{{
def has_perm(self, user_obj, perm, obj=None):
if not user_obj.is_authenticated or not isinstance(obj,
SomeModel):
return False
return (
user_obj.profile == 'admin'
or obj.related_model_fk in user_obj.related_model_m2m.all()
)
}}}
However, permission framework should also allow developers to implement
the second security mechanism: getting a filtered queryset with objects a
user should be able to see, eventually for a given permission. Such
implementation could look like:
{{{
def filter_queryset(self, user_obj, perm, queryset=None):
if not queryset.model == SomeModel:
return queryset
if not user_obj.is_authenticated:
return queryset.none()
return
queryset.filter(related_model_fk__in=user_obj.related_model_m2m.all())
}}}
The admin views could use this, and django.contrib.auth could provide
generic views extensions which do check permissions, removing the need to
share a mixin that just does return a Mixin with a get_queryset method to
complement the code that they have in the permission backend. It would
reduce chances to make a mistake when updating permission code if it's all
at the same place, an opinion that I consider suited for a framework like
Django.
--
--
Ticket URL: <https://code.djangoproject.com/ticket/31093#comment:3>
Old description:
> Permissions on objects are based on two mechanisms that developers have
> to implement:
>
> - returning if a user has a permission on an object instance
> - filtering a queryset based on a user object and eventually a permission
> name
>
> Currently, permission backend allows developers to implement the first
> mechanism: you can allow a specific permission on an object with the
> permission backend.
>
> This works extremely well even for complex use cases: you get an model
> object, a user, a permission name and you can return True.
>
> Exemple:
>
> {{{
> def has_perm(self, user_obj, perm, obj=None):
> if not user_obj.is_authenticated or not isinstance(obj,
> SomeModel):
> return False
>
> return (
> user_obj.profile == 'admin'
> or obj.related_model_fk in user_obj.related_model_m2m.all()
> )
> }}}
>
> However, permission framework should also allow developers to implement
> the second security mechanism: getting a filtered queryset with objects a
> user should be able to see, eventually for a given permission. Such
> implementation could look like:
>
> {{{
> def filter_queryset(self, user_obj, perm, queryset=None):
> if not queryset.model == SomeModel:
> return queryset
>
> if not user_obj.is_authenticated:
> return queryset.none()
>
> return
> queryset.filter(related_model_fk__in=user_obj.related_model_m2m.all())
> }}}
>
> The admin views could use this, and django.contrib.auth could provide
> generic views extensions which do check permissions, removing the need to
> share a mixin that just does return a Mixin with a get_queryset method to
> complement the code that they have in the permission backend. It would
> reduce chances to make a mistake when updating permission code if it's
> all at the same place, an opinion that I consider suited for a framework
> like Django.
New description:
Permissions on objects are based on two mechanisms that developers have to
implement:
- returning if a user has a permission on an object instance
- filtering a queryset based on a user object and eventually a permission
name
Currently, permission backend allows developers to implement the first
mechanism: you can allow a specific permission on an object with the
permission backend.
This works extremely well even for complex use cases: you get an model
object, a user, a permission name and you can return True.
Exemple:
{{{
def has_perm(self, user_obj, perm, obj=None):
if not user_obj.is_authenticated or not isinstance(obj,
SomeModel):
return False
return user_obj.is_superuser or obj.related_model_fk in
user_obj.related_model_m2m.all()
}}}
However, permission framework should also allow developers to implement
the second security mechanism: getting a filtered queryset with objects a
user should be able to see, eventually for a given permission. Such
implementation could look like:
{{{
def filter_queryset(self, user_obj, perm, queryset=None):
if not queryset.model == SomeModel:
return queryset
if not user_obj.is_authenticated:
return queryset.none()
return
queryset.filter(related_model_fk__in=user_obj.related_model_m2m.all())
}}}
The admin views could use this, and django.contrib.auth could provide
generic views extensions which do check permissions, removing the need to
share a mixin that just does return a Mixin with a get_queryset method to
complement the code that they have in the permission backend. It would
reduce chances to make a mistake when updating permission code if it's all
at the same place, an opinion that I consider suited for a framework like
Django.
--
--
Ticket URL: <https://code.djangoproject.com/ticket/31093#comment:4>
Old description:
> Permissions on objects are based on two mechanisms that developers have
> to implement:
>
> - returning if a user has a permission on an object instance
> - filtering a queryset based on a user object and eventually a permission
> name
>
> Currently, permission backend allows developers to implement the first
> mechanism: you can allow a specific permission on an object with the
> permission backend.
>
> This works extremely well even for complex use cases: you get an model
> object, a user, a permission name and you can return True.
>
> Exemple:
>
> {{{
> def has_perm(self, user_obj, perm, obj=None):
> if not user_obj.is_authenticated or not isinstance(obj,
> SomeModel):
> return False
>
> return user_obj.is_superuser or obj.related_model_fk in
> user_obj.related_model_m2m.all()
> }}}
>
> However, permission framework should also allow developers to implement
> the second security mechanism: getting a filtered queryset with objects a
> user should be able to see, eventually for a given permission. Such
> implementation could look like:
>
> {{{
> def filter_queryset(self, user_obj, perm, queryset=None):
> if not queryset.model == SomeModel:
> return queryset
>
> if not user_obj.is_authenticated:
> return queryset.none()
>
> return
> queryset.filter(related_model_fk__in=user_obj.related_model_m2m.all())
> }}}
>
> The admin views could use this, and django.contrib.auth could provide
> generic views extensions which do check permissions, removing the need to
> share a mixin that just does return a Mixin with a get_queryset method to
> complement the code that they have in the permission backend. It would
> reduce chances to make a mistake when updating permission code if it's
> all at the same place, an opinion that I consider suited for a framework
> like Django.
New description:
Permissions on objects are based on two mechanisms that developers have to
implement:
- returning if a user has a permission on an object instance
- filtering a queryset based on a user object and eventually a permission
name
Currently, permission backend allows developers to implement the first
mechanism: you can allow a specific permission on an object with the
permission backend.
This works extremely well even for complex use cases: you get an model
object, a user, a permission name and you can return True.
Exemple:
{{{
def has_perm(self, user_obj, perm, obj=None):
if not user_obj.is_authenticated or not isinstance(obj,
SomeModel):
return False
return user_obj.is_superuser or obj.related_model_fk in
user_obj.related_model_m2m.all()
}}}
However, permission framework should also allow developers to implement
the second security mechanism: getting a filtered queryset with objects a
user should be able to see, eventually for a given permission. Such
implementation could look like:
{{{
def filter_queryset(self, user_obj, perm, queryset=None):
if not queryset.model == SomeModel:
return queryset
if not user_obj.is_authenticated:
return queryset.none()
return
queryset.filter(related_model_fk__in=user_obj.related_model_m2m.all())
}}}
The admin views could use this, and django.contrib.auth could provide
generic views extensions which do check permissions, removing the need to
share a mixin that just does return a Mixin with a get_queryset method to
complement the code that they have in the permission backend. It would
reduce chances to make a mistake when updating permission code if it's all
at the same place, an opinion that I consider suited for a framework like
Django.
I consider that the subject of making ModelChoiceFields to be able to
benefit from this is out of the scope of this ticket, but I could bring it
up for discussion if this feature is implemented.
--
--
Ticket URL: <https://code.djangoproject.com/ticket/31093#comment:5>
Old description:
> Permissions on objects are based on two mechanisms that developers have
> to implement:
>
> - returning if a user has a permission on an object instance
> - filtering a queryset based on a user object and eventually a permission
> name
>
> Currently, permission backend allows developers to implement the first
> mechanism: you can allow a specific permission on an object with the
> permission backend.
>
> This works extremely well even for complex use cases: you get an model
> object, a user, a permission name and you can return True.
>
> Exemple:
>
> {{{
> def has_perm(self, user_obj, perm, obj=None):
> if not user_obj.is_authenticated or not isinstance(obj,
> SomeModel):
> return False
>
> return user_obj.is_superuser or obj.related_model_fk in
> user_obj.related_model_m2m.all()
> }}}
>
> However, permission framework should also allow developers to implement
> the second security mechanism: getting a filtered queryset with objects a
> user should be able to see, eventually for a given permission. Such
> implementation could look like:
>
> {{{
> def filter_queryset(self, user_obj, perm, queryset=None):
> if not queryset.model == SomeModel:
> return queryset
>
> if not user_obj.is_authenticated:
> return queryset.none()
>
> return
> queryset.filter(related_model_fk__in=user_obj.related_model_m2m.all())
> }}}
>
> The admin views could use this, and django.contrib.auth could provide
> generic views extensions which do check permissions, removing the need to
> share a mixin that just does return a Mixin with a get_queryset method to
> complement the code that they have in the permission backend. It would
> reduce chances to make a mistake when updating permission code if it's
> all at the same place, an opinion that I consider suited for a framework
> like Django.
>
> I consider that the subject of making ModelChoiceFields to be able to
> benefit from this is out of the scope of this ticket, but I could bring
> it up for discussion if this feature is implemented.
New description:
Permissions on objects are based on two mechanisms that developers have to
implement:
- returning if a user has a permission on an object instance
- filtering a queryset based on a user object and eventually a permission
name
Currently, permission backend allows developers to implement the first
mechanism: you can allow a specific permission on an object with the
permission backend.
This works extremely well even for complex use cases: you get an model
object, a user, a permission name and you can return True.
Exemple:
{{{
def has_perm(self, user_obj, perm, obj=None):
if not user_obj.is_authenticated or not isinstance(obj,
SomeModel):
return False
return user_obj.is_superuser or obj.related_model_fk in
user_obj.related_model_m2m.all()
}}}
However, permission framework should also allow developers to implement
the second security mechanism: getting a filtered queryset with objects a
user should be able to see, eventually for a given permission. Such
implementation could look like:
{{{
def filter_queryset(self, user_obj, perm, queryset=None):
if not queryset.model == SomeModel:
return queryset
if not user_obj.is_authenticated:
return queryset.none()
return
queryset.filter(related_model_fk__in=user_obj.related_model_m2m.all())
}}}
The admin views could use this, and django.contrib.auth could provide
generic views extensions which do check permissions, removing the need to
share a mixin that just does return a Mixin with a get_queryset method to
complement the code that they have in the permission backend. It would
reduce chances to make a mistake when updating permission code if it's all
at the same place, an opinion that I consider suited for a framework like
Django.
I consider that the subject of making ModelChoiceFields to be able to
benefit from this is out of the scope of this ticket, but I could bring it
up for discussion if this feature is implemented (ie. DRF serializers have
a "context" variables where the request object is set by default, which
allows to do user-based validation: a pretty standard requirement).
--
--
Ticket URL: <https://code.djangoproject.com/ticket/31093#comment:6>
* status: new => closed
* version: 3.0 => master
* resolution: => wontfix
Comment:
Django's Admin already handles permissions properly. IMO a generic method
for filtering a queryset based on an user object (and/or a permission
name) shouldn't be added to the builtin authentication back-ends. You can
start a discussion on DevelopersMailingList if you don't agree.
--
Ticket URL: <https://code.djangoproject.com/ticket/31093#comment:7>
Comment (by James Pic):
Thank you for your feedback, discussion open on new forum :
https://forum.djangoproject.com/t/extend-permission-backend-with-get-
queryset-user-model/819
--
Ticket URL: <https://code.djangoproject.com/ticket/31093#comment:8>