Commits

Anonymous committed 448a791

move object permission backend to a separate app

Comments (0)

Files changed (6)

object_permission_backend_nonrel/__init__.py

Empty file added.

object_permission_backend_nonrel/admin.py

+import settings
+from django import forms
+from django.template import RequestContext
+from django.shortcuts import render_to_response
+from django.contrib import admin
+from django.contrib.auth.admin import UserAdmin
+from django.contrib.auth.models import User, Group, Permission
+from django.contrib.contenttypes.models import ContentType
+
+from models import PermissionType, ObjectPermission, GroupObjectPermission
+
+
+def create_user_permission_obj(modeladmin, request, queryset):
+    for obj in queryset:
+         ct = ContentType.objects.get_for_model(obj)
+         perm_obj = ObjectPermission.objects.create(content_type=ct,
+                                                    object_id=obj.id)
+
+def create_group_permission_obj(modeladmin, request, queryset):
+    for obj in queryset:
+         ct = ContentType.objects.get_for_model(obj)
+         perm_obj = GroupObjectPermission.objects.create(content_type=ct,
+                                                         object_id=obj.id)
+
+admin.site.add_action(create_user_permission_obj)
+admin.site.add_action(create_group_permission_obj)
+
+
+class ObjectPermissionForm(forms.ModelForm):
+
+    permission_list = forms.MultipleChoiceField(required=False)
+    
+    def __init__(self, *args, **kwargs):
+        super(ObjectPermissionForm, self).__init__(*args, **kwargs)
+
+        self.fields['permission_list'] = forms.MultipleChoiceField(required=False)
+        
+        permission_types = PermissionType.objects.filter(content_type=kwargs['instance'].content_type)
+
+        choices = []
+        cls_list = set()
+        for pt in permission_types:
+            choices.append([pt.permission_name,  '%s:%s' %( pt.content_type, pt.permission_name)])
+           
+        self.fields['permission_list'].choices = choices
+        
+    class Meta:
+        model = ObjectPermission
+   
+    
+class ObjectPermissionAdmin(admin.ModelAdmin):
+    form = ObjectPermissionForm
+
+class GroupObjectPermissionForm(forms.ModelForm):
+
+     permission_list = forms.MultipleChoiceField(required=False)
+
+     def __init__(self, *args, **kwargs):
+         super(GroupObjectPermissionForm, self).__init__(*args, **kwargs)
+
+         self.fields['permission_list'] = forms.MultipleChoiceField(required=False)
+
+         permission_types = PermissionType.objects.filter(content_type=kwargs['instance'].content_type)
+
+         choices = []
+         cls_list = set()
+         for pt in permission_types:
+             choices.append([pt.permission_name,  '%s:%s' %( pt.content_type, pt.permission_name)])
+
+         self.fields['permission_list'].choices = choices
+
+
+     class Meta:
+         model = GroupObjectPermission
+
+class GroupObjectPermissionAdmin(admin.ModelAdmin):
+    form = GroupObjectPermissionForm
+
+
+class GroupObjectPermissionAdmin(admin.ModelAdmin):
+     form = GroupObjectPermissionForm
+
+class PermissionTypeAdmin(admin.ModelAdmin):
+    pass
+
+admin.site.register(ObjectPermission, ObjectPermissionAdmin)
+admin.site.register(GroupObjectPermission, GroupObjectPermissionAdmin)
+admin.site.register(PermissionType, PermissionTypeAdmin)
+
+
+
+
+

object_permission_backend_nonrel/backends.py

+from django.conf import settings
+from django.contrib.contenttypes.models import ContentType
+
+from django.contrib.auth.models import User
+from django.contrib.auth.backends import ModelBackend
+
+from google.appengine.api import users
+
+from permission_backend_nonrel.models import UserPermissionList
+
+from models import ObjectPermission, GroupObjectPermission
+
+
+class ObjectPermBackend(object):
+    supports_object_permissions = True
+    supports_anonymous_user = True
+    
+    def authenticate(self, username, password):
+        return None
+
+    def has_perm(self, user_obj, perm, obj=None):
+        return perm in self.get_all_permissions(user_obj, obj)
+    
+    def get_all_permissions(self, user_obj, obj=None):
+        if not user_obj.is_authenticated():
+            try:
+                user_obj = User.objects.get(pk=settings.ANONYMOUS_USER_ID)
+            except User.DoesNotExist:
+                user_obj = User(username='AnonymousUser', email='ano@nymous.xfz')
+                user_obj.set_unusable_password()
+                
+        if obj is None:
+            return set()
+                
+        ct = ContentType.objects.get_for_model(obj)
+        
+        current_permission_objs = ObjectPermission.objects.filter(content_type=ct,
+                                                                  object_id=obj.id,
+                                                                  user=user_obj)
+        perms = set()
+        
+        for p in current_permission_objs:
+            perms.update(p.permission_list)
+
+        perms.update(self.get_group_permissions(user_obj, obj))
+        return perms
+            
+    def get_group_permissions(self, user_obj, obj=None):
+        if obj is None:
+            return set()
+
+        if not user_obj.is_authenticated():
+            return set()
+
+
+        ct = ContentType.objects.get_for_model(obj)
+
+        try:
+            group_list = UserPermissionList.objects.get(user=user_obj)
+            
+            current_permission_objs = GroupObjectPermission.objects.filter(content_type=ct,
+                                                                           object_id=obj.id,
+                                                                           group__in=group_list.group_fk_list)
+            perms = set()
+            for p in current_permission_objs:
+                perms.update(p.permission_list)
+
+            return perms
+        except UserPermissionList.DoesNotExist:
+            return set()

object_permission_backend_nonrel/models.py

+"""
+Models for object-level permissions
+"""
+
+from django.db import models
+from django.contrib.auth.models import User, Group
+from django.contrib.contenttypes.models import ContentType
+
+from djangotoolbox.fields import ListField
+
+class ObjectPermission(models.Model):
+    user = models.ForeignKey(User, null=True)
+
+    permission_list = ListField(models.CharField(max_length=64))
+                            
+    content_type = models.ForeignKey(ContentType)
+    object_id = models.PositiveIntegerField()
+
+
+class GroupObjectPermission(models.Model):
+    group = models.ForeignKey(Group, null=True)
+
+    permission_list = ListField(models.CharField(max_length=64))
+                            
+    content_type = models.ForeignKey(ContentType)
+    object_id = models.PositiveIntegerField()
+
+
+class PermissionType(models.Model):
+    content_type = models.ForeignKey(ContentType, null=True)
+    permission_name = models.CharField(max_length=64, null=True)

object_permission_backend_nonrel/tests.py

+from django.test import TestCase
+from django.db import models
+from django.contrib.auth.models import User, Group
+from django.contrib.contenttypes.models import ContentType
+
+from permission_backend_nonrel.utils import add_user_to_group
+
+from .models import ObjectPermission,PermissionType, GroupObjectPermission
+from .utils import grant_permissions, register, add_permission_to_group
+
+class TestObj(models.Model):
+    pass
+
+class ObjPermBackendTests(TestCase):
+    """
+    Tests for the object permission app
+    """
+
+    def setUp(self):
+        self.user1 = User.objects.create_user('test1', 'test1@test.com', 'test')
+        self.user2 = User.objects.create_user('test2', 'test2@test.com', 'test')
+
+        self.obj1 = TestObj()
+        self.obj1.id = 1 # add id manually to avoid problem with app engine
+        self.obj1.save()
+
+    def test_permission_creation(self):
+        ct = ContentType.objects.get_for_model(self.obj1)
+        # add permission types
+        pt = PermissionType(content_type=ct, permission_name='view')
+        pt.save()
+        pt = PermissionType(content_type=ct, permission_name='change')
+        pt.save()
+        pt = PermissionType(content_type=ct, permission_name='delete')
+        pt.save()
+        
+        # create permission object for user1
+        
+        perm_obj = ObjectPermission.objects.create(user=self.user1,
+                                                   content_type=ct, object_id=self.obj1.id)
+        perm_obj.permission_list.append('view')
+        perm_obj.permission_list.append('change')
+        perm_obj.permission_list.append('delete')
+        
+        perm_obj.save()
+
+        # a ObjectPermission object has to be created
+        self.assertEquals(ObjectPermission.objects.count(), 1)
+        
+        # check if user1 has view, change and delete permission
+        self.assertEquals(self.user1.has_perm('view', self.obj1), True)
+        self.assertEquals(self.user1.has_perm('change', self.obj1), True)
+        self.assertEquals(self.user1.has_perm('delete', self.obj1), True)
+
+        # user2 doesn't have any permissions
+        self.assertNotEquals(self.user2.has_perm('view', self.obj1), True)
+        self.assertNotEquals(self.user2.has_perm('change', self.obj1), True)
+        self.assertNotEquals(self.user2.has_perm('delete', self.obj1), True)
+        
+    """
+    def test_duplicated_permission_object(self):
+        # create permission object for user1
+        ct = ContentType.objects.get_for_model(self.obj1)
+        perm_obj = ObjectPermission.objects.create(user=self.user1,
+                                                   content_type=ct, object_id=self.obj1.id,
+                                                   can_view=True, can_change=True,
+                                                   can_delete=True)
+        perm_obj.save()
+        
+        # a ObjectPermission object has to be created
+        self.assertEquals(ObjectPermission.objects.count(), 1)
+        
+        # check if user1 has view, change and delete permission
+        self.assertEquals(self.user1.has_perm('view', self.obj1), True)
+        self.assertEquals(self.user1.has_perm('change', self.obj1), True)
+        self.assertEquals(self.user1.has_perm('delete', self.obj1), True)
+
+        # create second permission object for the same user and object with different
+        # permissions
+        # creates an undefined state, use methods from utils to avoid!
+        ct = ContentType.objects.get_for_model(self.obj1)
+        perm_obj = ObjectPermission.objects.create(user=self.user1,
+                                                   content_type=ct, object_id=self.obj1.id,
+                                                   can_view=True, can_change=True,
+                                                   can_delete=False)
+        perm_obj.save()
+
+        # object shouldn't been created
+        self.assertEquals(ObjectPermission.objects.count(), 2)
+    """
+    def test_register_permission(self):
+        self.assertEquals(grant_permissions(self.obj1, self.user1, ['view']), False)
+        self.assertEquals(ObjectPermission.objects.count(), 0)
+        self.assertEquals(PermissionType.objects.count(), 0)
+        
+        register(TestObj, 'view')
+        self.assertEquals(PermissionType.objects.count(), 1)
+        
+        # create permissions with the add_permissions function
+        self.assertEquals(grant_permissions(self.obj1, self.user1, ['view', 'change']), False)
+
+        self.assertEquals(ObjectPermission.objects.count(), 0)
+        self.assertEquals(self.user1.has_perm('view', self.obj1), False)
+        self.assertEquals(self.user1.has_perm('change', self.obj1), False)
+
+
+        self.assertEquals(grant_permissions(self.obj1, self.user1, ['view']), True)
+        
+        self.assertEquals(ObjectPermission.objects.count(), 1)
+        self.assertEquals(self.user1.has_perm('view', self.obj1), True)
+        self.assertEquals(self.user1.has_perm('change', self.obj1), False)
+
+    def test_add_permission(self):
+        register(TestObj, 'view')
+        register(TestObj, 'change')
+        register(TestObj, 'delete')
+        
+        # create permissions with the add_permissions function
+        grant_permissions(self.obj1, self.user1, ['view'])
+
+        self.assertEquals(ObjectPermission.objects.count(), 1)
+        self.assertEquals(self.user1.has_perm('view', self.obj1), True)
+        self.assertEquals(self.user1.has_perm('change', self.obj1), False)
+        
+        grant_permissions(self.obj1, self.user1, ['change'])
+        
+        self.assertEquals(ObjectPermission.objects.count(), 1)
+        self.assertEquals(self.user1.has_perm('view', self.obj1), True)
+        self.assertEquals(self.user1.has_perm('change', self.obj1), True)
+
+        self.assertNotEquals(self.user1.has_perm('delete', self.obj1), True)
+
+
+        self.assertNotEquals(self.user2.has_perm('view', self.obj1), True)
+        self.assertNotEquals(self.user2.has_perm('change', self.obj1), True)
+        self.assertNotEquals(self.user2.has_perm('delete', self.obj1), True)
+
+    def test_add_permission_to_group(self):
+        register(TestObj, 'view')
+        register(TestObj, 'change')
+        register(TestObj, 'delete')
+        
+        group = Group.objects.create(name='Group1')
+        
+        add_permission_to_group('view', group, self.obj1)
+        add_user_to_group(self.user1, group)
+        self.assertEquals(GroupObjectPermission.objects.count(), 1)
+        self.assertEquals(self.user1.has_perm('view', self.obj1), True)
+        self.assertEquals(self.user1.has_perm('invalid', self.obj1), False)

object_permission_backend_nonrel/utils.py

+from django.contrib.auth.models import User
+from django.db import models
+from django.contrib.contenttypes.models import ContentType
+
+from models import ObjectPermission, PermissionType, GroupObjectPermission
+
+def register(model_class, perm):
+    """
+    creates a PermissionType object with permission perm for the model model_class
+    """
+
+    ct = ContentType.objects.get_for_model(model_class)
+    pt = PermissionType.objects.filter(content_type=ct,
+                                       permission_name=perm)
+
+    if pt.count() != 0:
+        return False # already registered
+    else:
+        pt = PermissionType(content_type=ct, permission_name=perm)
+        pt.save()
+        return True
+    
+def grant_permissions(model, user, permission_list):
+    """
+    add permission_list for user to model
+
+    returns False if permission_list contains unregistered permissions
+    or model is no instance of models.Model or user is no instance of
+    django.contrib.auth.models.User
+
+    returns True if permission_list is saved
+    """
+    
+    if isinstance(user, User) and isinstance(model, models.Model):
+        ct = ContentType.objects.get_for_model(model)
+        try:
+            perm_obj = ObjectPermission.objects.get(user=user,
+                                                    content_type=ct,
+                                                   object_id=model.id)
+
+        except ObjectPermission.DoesNotExist:
+            perm_obj = ObjectPermission(user=user, 
+                                         content_type=ct, object_id=model.id)
+        current_permission_list = perm_obj.permission_list
+        registered_permissions = PermissionType.objects.filter(content_type=
+                                                               ct)
+
+        registerd_permission_list = list()
+        
+        for perm in registered_permissions:
+            registerd_permission_list.append(perm.permission_name)
+        
+        
+        # remove already existing entries from permission_list
+        for perm in current_permission_list:
+            try:
+                dup = permission_list.index(perm)
+                permission_list.remove(dup)
+            except ValueError:
+                pass
+            
+        for perm in permission_list:
+            try:
+                perm_obj.permission_list.append(registerd_permission_list.pop(registerd_permission_list.index(perm)))
+            except ValueError:
+                return False
+            
+        perm_obj.save()
+        return True
+
+    else:
+        return False
+
+
+def add_permission_to_group(perm, group, obj):
+    ct = ContentType.objects.get_for_model(obj)
+    perm_obj, created = GroupObjectPermission.objects.get_or_create(group=group,
+                                                                    content_type=ct,
+                                                                    object_id=obj.id)
+        
+    
+
+    perm_obj.permission_list.append(perm)
+
+    perm_obj.save()
+    
+