neues in Django-Tools: Dinge limitieren anhand User-Typ oder User-Gruppe

Sicherlich habt ihr schon mal das selbe Problem gehabt:

Man möchte z.B. die Sichtbarkeit eines Eintrags (z.B.: Blog-Eintrag, oder eine Seite) limitieren. Und das wahlweise anhand von User-Typ (Anonymous, staff- oder super-user) oder anhand einer existierenden User-Gruppe...

Entweder macht man es sich einfach, lässt die User-Typen weg und macht nur einen models.ForeignKey zu auth.models.Group.

Wenn man allerdings die User-Typen drin haben will, hat man ein Problem. Zusätzliche models.BooleanField() jeweils für Anonymous, staff- und super-user ist doch recht unpraktisch.

Ich hab nun was gebastelt, damit man mit nur einem Feld zwischen User-Typ und User-Gruppe gleichzeitig wählen kann:
https://github.com/jedie/django-tools/blob/master/django_tools/limit_to_usergroups.py

Im Grunde ist es ein models.IntegerField() welches choices Benutzt, welches dann ungefähr so aussieht:

1
2
3
4
5
6
7
8
CHOICES = [
        (0, _("anonymous users")),
        (-1, _("staff users")),
        (-2, _("superusers")),
        (1, _("Erste auth.models.Group")),
        (2, _("Zweite auth.models.Group")),
        ...
    ]

Dazu gibt es ein paar Hilfsfunktionen, damit man schneller auswerten kann, ob der User nun zugriff hat, oder nicht.

Ein Model kann Beispielsweise so aussehen:

1
2
3
4
5
from django_tools import limit_to_usergroups

class FooBar(models.Model):
    permit_edit = limit_to_usergroups.UsergroupsModelField()
    permit_view = limit_to_usergroups.UsergroupsModelField()

Die Rechte für ein Objekt kann man z.B. so abfragen, mit dabei noch ein Beispiel wie man eine Aussagekräftige Meldung erstellen kann:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def edit(request, id):
    foo = FooBar.objects.get(id=id)
    if not limit_to_usergroups.has_permission(poll, permit_edit=request.user):
        msg = _("You have no permission to edit this.")
        if settings.DEBUG:
            verbose_limit_name = limit_to_usergroups.get_verbose_limit_name(foo.permit_edit)
            msg += " (Limited to: %s)" % verbose_limit_name
            messages.error(request, msg)
        return HttpResponseRedirect("foobar)
    ...

Im view kann man z.B. ein Queryset Filtern anhand der Rechte des aktuellen Users:

1
2
3
4
5
6
from django_tools import limit_to_usergroups

def view(request):
    queryset = FooBar.objects.all()
    queryset = limit_to_usergroups.filter_permission(queryset, permit_view=request.user)
    ...

Und hier könnte man was erheblich verbessern: Wie kann man Dinge wie has_permission() und filter_permission() direkt an den QuerySet hängen?

Man muß wohl den Model-Manager erweitern. Hab ich versucht, aber mit wenig Erfolg.

(Crosspost: http://www.python-forum.de/viewtopic.php?f=7&t=26841 )

Sicherlich habt ihr schon mal das selbe Problem gehabt:

Man möchte z.B. die Sichtbarkeit eines Eintrags (z.B.: Blog-Eintrag, oder eine Seite) limitieren. Und das wahlweise anhand von User-Typ (Anonymous, staff- oder super-user) oder anhand einer existierenden User-Gruppe...

Entweder macht man es sich einfach, lässt die User-Typen weg und macht nur einen models.ForeignKey zu auth.models.Group.

Wenn man allerdings die User-Typen drin haben will, hat man ein Problem. Zusätzliche models.BooleanField() jeweils für Anonymous, staff- und super-user ist doch recht unpraktisch.

Ich hab nun was gebastelt, damit man mit nur einem Feld zwischen User-Typ und User-Gruppe gleichzeitig wählen kann:
https://github.com/jedie/django-tools/blob/master/django_tools/limit_to_usergroups.py

Im Grunde ist es ein models.IntegerField() welches choices Benutzt, welches dann ungefähr so aussieht:

1
2
3
4
5
6
7
8
CHOICES = [
        (0, _("anonymous users")),
        (-1, _("staff users")),
        (-2, _("superusers")),
        (1, _("Erste auth.models.Group")),
        (2, _("Zweite auth.models.Group")),
        ...
    ]

Dazu gibt es ein paar Hilfsfunktionen, damit man schneller auswerten kann, ob der User nun zugriff hat, oder nicht.

Ein Model kann Beispielsweise so aussehen:

1
2
3
4
5
from django_tools import limit_to_usergroups

class FooBar(models.Model):
    permit_edit = limit_to_usergroups.UsergroupsModelField()
    permit_view = limit_to_usergroups.UsergroupsModelField()

Die Rechte für ein Objekt kann man z.B. so abfragen, mit dabei noch ein Beispiel wie man eine Aussagekräftige Meldung erstellen kann:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def edit(request, id):
    foo = FooBar.objects.get(id=id)
    if not limit_to_usergroups.has_permission(poll, permit_edit=request.user):
        msg = _("You have no permission to edit this.")
        if settings.DEBUG:
            verbose_limit_name = limit_to_usergroups.get_verbose_limit_name(foo.permit_edit)
            msg += " (Limited to: %s)" % verbose_limit_name
            messages.error(request, msg)
        return HttpResponseRedirect("foobar)
    ...

Im view kann man z.B. ein Queryset Filtern anhand der Rechte des aktuellen Users:

1
2
3
4
5
6
from django_tools import limit_to_usergroups

def view(request):
    queryset = FooBar.objects.all()
    queryset = limit_to_usergroups.filter_permission(queryset, permit_view=request.user)
    ...

Und hier könnte man was erheblich verbessern: Wie kann man Dinge wie has_permission() und filter_permission() direkt an den QuerySet hängen?

Man muß wohl den Model-Manager erweitern. Hab ich versucht, aber mit wenig Erfolg.

(Crosspost: http://www.python-forum.de/viewtopic.php?f=7&t=26841 )