arcologies
arcologies

Reputation: 752

Django - Anonymous user group

I need to allow administrators to manage permissions for models on my site. Groups, Users, and Permissions are doing a great job of this right now. However, I also need to allow the administrators to manage the permissions of non-authenticated users - Anonymous Users. The docs say that anonymous user's group is always empty, so how can I allow administration of their permissions?

Upvotes: 4

Views: 4196

Answers (2)

Tisho
Tisho

Reputation: 8482

It is strange to add permissions to anonymous users. Docs say:

Django's permission framework does not have a place to store permissions for anonymous users. However, it has a foundation that allows custom authentication backends to specify authorization for anonymous users. This is especially useful for the authors of re-usable apps, who can delegate all questions of authorization to the auth backend, rather than needing settings, for example, to control anonymous access.

So you can set permissions to anon yuser, but with custom auth backend. It is sometimes better to use declarative permission check, using decorators on the views with the needed permissions, like:

@permission_required('somemodel.can_add')
def add_model(request):

or leave it unrestricted for everyone(incl. anonymous user). Or some custom permission check..

Or if you want to have permissions anyway, you can always create a dummy user, let's say "AnonUser", to give it permissions, and then checking permissions to have something like:

if not user.is_authenticated():
    dummy_user = User.objects.get(name="AnonUser")
    if dummy_user.has_perm("somepermission"):
        # bla bla bla

but this is something I'd never use..

Upvotes: 5

jozxyqk
jozxyqk

Reputation: 17258

I've gone with a custom backend to provide an anonymous group (as @Tisho suggests), which can easily be edited from the admin interface. Add the following class to AUTHENTICATION_BACKENDS in settings.py (e.g. 'appname.auth_backend.AnonymousPermissions').

Note that it's common to require a login before checking permissions (e.g. with login_required), which will have to be replaced with permission only checks.

from django.contrib.auth.models import Group

class AnonymousPermissions(object):

    def get_anonymous_permissions(self):
        #largely from django.contrib.auth.backends
        group, group_created = Group.objects.get_or_create(name='Anonymous')
        perms = group.permissions.all()
        perms = perms.values_list('content_type__app_label', 'codename').order_by()
        perms = set("%s.%s" % (ct, name) for ct, name in perms)
        return perms

    def get_group_permissions(self, user_obj, obj=None):
        if user_obj.is_anonymous:
            perm_cache_name = '_anonymous_perm_cache'
            if not hasattr(user_obj, perm_cache_name):
                setattr(user_obj, perm_cache_name, self.get_anonymous_permissions())
            return getattr(user_obj, perm_cache_name)
        return set()

    def get_all_permissions(self, user_obj, obj=None):
        return self.get_group_permissions(user_obj, obj)

    def has_perm(self, user_obj, perm, obj=None):
        return perm in self.get_group_permissions(user_obj, obj)

Upvotes: 1

Related Questions