# -*- coding: utf-8 -*-
"""
Model backend that enables permissions for AnonymusUsers.
I wanted it to be as simple as possible so anonymous users just forward their permission checks
to some fixed user model. This instance can be edited via django admin, assigned to groups, etc.
To control which user will represent anonymous user you use ANONYMOUS_USER_NAME setting in
settings file.
To provide some sensible level of security i enforce following for user that represents
anonymous user:
* This user must have password equal to UNUSABLE_PASSWORD
* This user may not log in
* You cant cange password for this user via admin.
You need to enable this backend by setting AUTHENTICATION_BACKENDS. Please note that you
should not place this backend alongside django ModelBackend. This backend inherits from it.
"""
__author__ = 'jb'
from django.conf import settings
from django.contrib.auth.models import User, UNUSABLE_PASSWORD, Permission
from django.contrib.contenttypes.models import ContentType
from django.db.models.signals import pre_save
from django.dispatch.dispatcher import receiver
from django.contrib.auth.backends import ModelBackend
import logging
_LOGGER = logging.getLogger(__name__)
def get_anon_user_name():
return getattr(settings, "ANONYMOUS_USER_NAME", None)
class AnonymousUserBackend(ModelBackend):
def get_all_permissions(self, user_obj):
if user_obj.is_anonymous():
if not hasattr(user_obj, '_perm_cache'):
anon_user_name = get_anon_user_name()
anon_user, created = User.objects.get_or_create(username = anon_user_name, password = UNUSABLE_PASSWORD)
user_obj._perm_cache = self.get_all_permissions(anon_user)
return user_obj._perm_cache
return super(AnonymousUserBackend, self).get_all_permissions(user_obj)
def authenticate(self, username=None, password=None):
if username == get_anon_user_name():
return False
return super(AnonymousUserBackend, self).authenticate(username, password)
def has_perm(self, user_obj, perm):
if not user_obj.is_active and not user_obj.is_anonymous:
return False
return perm in self.get_all_permissions(user_obj)
@receiver(pre_save, sender=User)
def disable_anon_user_password_save(sender, **kwargs):
instance = kwargs['instance']
if instance.username == get_anon_user_name() and instance.password != UNUSABLE_PASSWORD:
raise ValueError("Can't set anonymous user password to something other than unusable password")
def register_custom_permissions(permissions, appname):
ct, created = ContentType.objects.get_or_create(model='', app_label=appname,
defaults={'name': appname})
for codename, name in permissions:
p, created = Permission.objects.get_or_create(codename=codename,
content_type__pk=ct.id,
defaults={'name': name, 'content_type': ct})
Comments
Please login first before commenting.