Commits

schacki committed 9ee661a

Added signal handlers to add and remove the permission check functions to the Model classes including test cases

  • Participants
  • Parent commits 9966729

Comments (0)

Files changed (4)

permissions/exceptions.py

     
 class MultiplePrincipalsAssigned(Exception):
     pass    
+    
+class PermissionNameExists(Exception):
+    pass    

permissions/models.py

 
 # permissions imports
 import permissions.utils
-from permissions.settings import ROLES_ENABLED
-from permissions.exceptions import RolesNotEnabled,MultiplePrincipalsAssigned
+from permissions.settings import ROLES_ENABLED, OBJECTS_PERM_CHECK, OBJECTS_GENERIC_CHECK, OBJECTS_PERM_STRING,OBJECTS_PERM_CHECK_OVERRIDE, OBJECTS_GENERIC_STRING
+from permissions.exceptions import RolesNotEnabled,MultiplePrincipalsAssigned,PermissionNameExists
 
 class Permission(models.Model):
     """A permission which can be granted to users/groups and objects.
     class Meta:
         unique_together = ['name','codename']
         verbose_name = _('permission')
-        verbose_name_plural = _('permissions')        
+        verbose_name_plural = _('permissions')  
+        
+from django.db.models.signals import pre_save,post_save,pre_delete
+from django.dispatch import receiver
+from django.utils.functional import curry
+
+if OBJECTS_PERM_CHECK:
+    @receiver(pre_delete,sender=Permission)
+    def remove_object_permission_checker_delete(sender,**kwargs):
+        instance=kwargs['instance']
+        print 'delete'
+        for content_type in instance.content_types.all():
+            model=content_type.model_class()    
+            name=OBJECTS_PERM_STRING %instance.codename
+            if hasattr(model,name):
+                delattr(model,name)
+
+    @receiver(pre_save,sender=Permission)
+    def remove_object_permission_checker_save(sender,**kwargs):
+        instance=kwargs['instance']
+        if not instance.id:
+            return None
+        for content_type in instance.content_types.all():
+            model=content_type.model_class()    
+            name=OBJECTS_PERM_STRING %instance.codename
+            if hasattr(model,name):
+                delattr(model,name)
+            
+    @receiver(post_save,sender=Permission)
+    def add_object_permission_checker(sender,**kwargs):
+        instance=kwargs['instance']
+        for content_type in instance.content_types.all():
+            model=content_type.model_class()   
+            name=OBJECTS_PERM_STRING %instance.codename
+            if hasattr(model,name):
+                raise PermissionNameExists()    
+            setattr(model,name,curry(permissions.utils.has_permission,codename=instance.codename))      
+
+if OBJECTS_GENERIC_CHECK:
+    @receiver(pre_delete,sender=Permission)
+    def remove_object_generic_checker_delete(sender,**kwargs):
+        instance=kwargs['instance']
+        for content_type in instance.content_types.all():
+            model=content_type.model_class()    
+            name='has_permission'
+            if hasattr(model,name):
+                delattr(model,name)
+
+    @receiver(pre_save,sender=Permission)
+    def remove_object_generic_checker_save(sender,**kwargs):
+        instance=kwargs['instance']
+        if not instance.id:
+            return None
+        for content_type in instance.content_types.all():
+            model=content_type.model_class()    
+            name=OBJECTS_GENERIC_STRING
+            if hasattr(model,name):
+                delattr(model,name)
+            
+    @receiver(post_save,sender=Permission)
+    def add_object_generic_checker(sender,**kwargs):
+        instance=kwargs['instance']
+        for content_type in instance.content_types.all():
+            model=content_type.model_class()   
+            name=OBJECTS_GENERIC_STRING
+            if hasattr(model,name):
+                raise PermissionNameExists()    
+            setattr(model,name,permissions.utils.has_permission)  
 
 class ObjectPermission(models.Model):
     """Grants permission for a role and an content object (optional).

permissions/tests.py

 from django.core.urlresolvers import reverse
 from django.test import TestCase
 from django.test.client import Client
+from django.contrib.contenttypes.models import ContentType
 
 # permissions imports
 from permissions.models import Permission
             self.assertEqual(result, False)
             
             # assign view permission to user
-            print permissions.utils.grant_permission(self.page_1, self.group, 'view_2')
+            permissions.utils.grant_permission(self.page_1, self.group, 'view_2')
 
             result = self.user_2.has_perm("view_2", self.page_1)
             self.assertEqual(result, True)                       
         self.user_2 = User.objects.create(username="marc")
         self.group=Group.objects.create(name='group 1')          
         self.user_2.groups.add(self.group)
-        self.view_2 = permissions.utils.register_permission("View_2", "view_2")        
-        self.view_3 = permissions.utils.register_permission("View_3", "view_3")            
+        self.view_2 = permissions.utils.register_permission("View_2", "view_2", FlatPage)        
+        self.view_3 = permissions.utils.register_permission("View_3", "view_3", FlatPage)            
 
     def test_add_permissions(self):
         """
             # Add ermission which does not exist
             result = permissions.utils.grant_permission(self.page_1, self.role_1, "hurz")
             self.assertEqual(result, False)
+            
+            
         else:            
             # Add per object
             result = permissions.utils.grant_permission(self.page_1, self.user, self.permission)
             # Remove again
             result = permissions.utils.remove_permission(self.page_1, self.user, "view_2")
             self.assertEqual(result, False)
-            
-            
+                      
 
             # Add
             result = permissions.utils.grant_permission(self.page_1, self.group, "view_2")
 
             result = permissions.utils.has_permission(self.page_1, self.user, "view")
             self.assertEqual(result, True)
-
+            
             result = permissions.utils.remove_permission(self.page_1, self.role_1, "view")
             self.assertEqual(result, True)
 
             result = permissions.utils.has_permission(self.page_1, self.user_2, "view_3")
             self.assertEqual(result, True)                      
 
-    def test_ineritance(self):
+    def test_inheritance(self):
         """
         """
         result = permissions.utils.is_inherited(self.page_1, "view")
     def test_permission(self):
         """Tests registering/unregistering of a permission.
         """
+            
         # Register a permission
         result = permissions.utils.register_permission("Change", "change")
         self.failUnless(isinstance(result, Permission))
         result = permissions.utils.unregister_permission("change")
         self.assertEqual(result, False)
 
+    def test_permission_with_content_type(self):
+        """Tests registering/unregistering of a permission.
+        """
+        
+        self.assertEqual(hasattr(FlatPage(),'change'),False)
+        #self.assertEqual(hasattr(FlatPage(),'has_permission'),False)
+         
+        # Register a permission
+        result = permissions.utils.register_permission("Change", "change",FlatPage)
+        self.failUnless(isinstance(result, Permission))
+
+        # Is it there?
+        p = Permission.objects.get(codename="change")
+        self.assertEqual(p.name, "Change")
+
+        self.assertEqual(hasattr(FlatPage(),'change'),True)
+        self.assertEqual(hasattr(FlatPage(),'has_permission'),True)
+
+        # Register a permission with the same codename
+        result = permissions.utils.register_permission("Change2", "change",FlatPage)
+        self.assertEqual(result, False)
+
+        # Is it there?
+        p = Permission.objects.get(codename="change")
+        self.assertEqual(p.name, "Change")
+
+        # Register a permission with the same name
+        result = permissions.utils.register_permission("Change", "change2",FlatPage)
+        self.assertEqual(result, False)
+
+        # Is it there?
+        p = Permission.objects.get(codename="change")
+        self.assertEqual(p.name, "Change")
+
+        # Unregister the permission
+        result = permissions.utils.unregister_permission("change")
+        self.assertEqual(result, True)
+
+        # Is it not there anymore?
+        self.assertRaises(Permission.DoesNotExist, Permission.objects.get, codename="change")
+        
+        self.assertEqual(hasattr(FlatPage(),'change'),False)
+        self.assertEqual(hasattr(FlatPage(),'has_permission'),False)        
+
+        # Unregister the permission again
+        result = permissions.utils.unregister_permission("change")
+        self.assertEqual(result, False)
+
 # django imports
 from django.core.handlers.wsgi import WSGIRequest
 from django.contrib.auth.models import User

permissions/utils.py

 # django imports
 from django.db import IntegrityError
 from django.db import connection
-from django.db.models import Q
+from django.db.models import Q,Model
 from django.contrib.auth.models import User
 from django.contrib.auth.models import Group
 from django.contrib.contenttypes.models import ContentType
         used to display only reasonable permissions for an object. This
         must be a Django ContentType
     """
-    if ctypes is None:
-        ctypes = []
 
     # Permission with same codename and/or name must not exist.
     if Permission.objects.filter(Q(name=name) | Q(codename=codename)):
         return False
 
+    if ctypes is None:
+        ctypes = []
+    elif issubclass(ctypes,Model):
+        ctypes=[ctypes]
+
     p = Permission.objects.create(name=name, codename=codename)
-
     ctypes = [ContentType.objects.get_for_model(ctype) for ctype in ctypes]
     if ctypes:
         p.content_types = ctypes