Security layer moved to middleware and ldt_utils __init__ file
authorverrierj
Fri, 04 Nov 2011 16:45:40 +0100
changeset 232 2878499a372b
parent 231 535ce952e51c
child 233 f6d009f83e38
Security layer moved to middleware and ldt_utils __init__ file
src/ldt/ldt/ldt_utils/__init__.py
src/ldt/ldt/ldt_utils/middleware/security.py
src/ldt/ldt/ldt_utils/models.py
src/ldt/ldt/ldt_utils/security.py
src/ldt/ldt/ldt_utils/views.py
src/ldt/ldt/user/models.py
web/ldtplatform/settings.py
--- a/src/ldt/ldt/ldt_utils/__init__.py	Fri Nov 04 10:31:47 2011 +0100
+++ b/src/ldt/ldt/ldt_utils/__init__.py	Fri Nov 04 16:45:40 2011 +0100
@@ -1,2 +1,70 @@
+from django.conf import settings
+from django.db.models import Manager
+from models import Project
+from guardian.core import ObjectPermissionChecker
+from guardian.shortcuts import get_objects_for_user, assign
+
 VERSION = (0, 1)
 VERSION_STR = unicode(".".join(map(lambda i:"%02d" % (i,), VERSION)))
+
+def protect_class(cls, user):
+    cls.base_objects = cls.objects
+    cls.objects = SafeManager(cls, user)
+    
+    cls.base_save = cls.save
+    cls.save = save_security(user)(cls.save)
+    
+def unprotect_class(cls):
+    
+    if hasattr(Project, 'base_objects'):
+        cls.objects = cls.base_objects
+        cls.save = cls.base_save
+        del cls.base_objects    
+        del cls.base_save
+
+class SafeManager(Manager):
+    
+    def __init__(self, cls, user=None):
+        super(SafeManager, self).__init__()
+        self.model_name = cls.__name__.lower()
+        self.model = cls  
+        if user:
+            self.check_perm_for(user)
+        else:
+            self.user = None
+            self.checker = None     
+    
+    def check_perm_for(self, user):
+        self.user = user
+        self.checker = ObjectPermissionChecker(self.user)
+        
+    def stop_checking(self):
+        self.user = None
+        self.checker = None
+      
+    def has_user(self):
+        return self.user != None        
+      
+    def get_query_set(self):
+        if not self.has_user():
+            raise AttributeError("A user has to be chosen to check permissions.")
+        
+        user_projects = get_objects_for_user(self.user, 'ldt_utils.view_%s' % self.model_name)
+            
+        return user_projects
+    
+    
+def save_security(user):
+    def wrapper(func):
+        def wrapped(self, *args, **kwargs):
+            
+            if not user.has_perm('change_project', self):
+                raise AttributeError('User %s does not have sufficient permissions to change object %s' % (user, self))
+            
+            return func(self, *args, **kwargs)
+        return wrapped
+    
+    return wrapper
+
+    
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/middleware/security.py	Fri Nov 04 16:45:40 2011 +0100
@@ -0,0 +1,29 @@
+from django.conf import settings
+from ldt.ldt_utils import protect_class, unprotect_class
+from ldt.ldt_utils.models import Project, Content
+from django.core.exceptions import MiddlewareNotUsed
+
+class SecurityMiddleware(object):
+    
+    def __init__(self):
+        if not hasattr(settings, 'USE_GROUP_PERMISSIONS') or not settings.USE_GROUP_PERMISSIONS:
+            raise MiddlewareNotUsed()           # Disable middleware
+
+    def process_request(self, request):
+        
+        if settings.USE_GROUP_PERMISSIONS == 'all':
+            protect_class(Project, request.user) # This is not thread-safe
+            protect_class(Content, request.user)
+            
+        for cls_name in settings.USE_GROUP_PERMISSIONS.split(' '):
+            if cls_name == 'Project':
+                protect_class(Project, request.user)
+            elif cls_name == 'Content':
+                protect_class(Content, request.user)
+        
+    
+    def process_response(self, request, response):
+        unprotect_class(Project)
+        unprotect_class(Content)
+        
+        return response
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/models.py	Fri Nov 04 10:31:47 2011 +0100
+++ b/src/ldt/ldt/ldt_utils/models.py	Fri Nov 04 16:45:40 2011 +0100
@@ -1,11 +1,10 @@
 from django.conf import settings
-from django.contrib.auth.models import User
+from django.contrib.auth.models import User, Group
 from django.db import models
 from django.utils.translation import ugettext_lazy as _
 #from ldt.core.models import Document, Owner
 from ldt.core.models import Document
-from guardian.core import ObjectPermissionChecker
-from guardian.shortcuts import get_objects_for_user, assign
+from guardian.shortcuts import assign, remove_perm
 import ldt.indexation
 from utils import (create_ldt, copy_ldt, create_empty_iri, update_iri, 
     generate_uuid)
@@ -186,7 +185,7 @@
         self.sync_iri_file()        
         # update it 
         super(Content, self).save(*args, **kwargs)
-    
+            
     def __unicode__(self):
         return str(self.id) + ": " + self.iri_id
         
@@ -292,38 +291,6 @@
        
     external_id = property(**external_id())
     
-class MyManager(models.Manager):
-    
-    def get_query_set(self, *args, **kwargs):
-        return super(MyManager, self).get_query_set(*args, **kwargs)
-
-class SafeManager(models.Manager):
-    
-    def __init__(self, model_name):
-        super(SafeManager, self).__init__()
-        self.user = None
-        self.checker = None 
-        self.model_name = model_name       
-    
-    def check_perm_for(self, user):
-        self.user = user
-        self.checker = ObjectPermissionChecker(self.user)
-        
-    def stop_checking(self):
-        self.user = None
-        self.checker = None
-      
-    def has_user(self):
-        return self.user != None        
-      
-    def get_query_set(self):
-        if not self.has_user():
-            raise AttributeError("A user has to be chosen to check permissions.")
-        
-        res = get_objects_for_user(self.user, 'ldt_utils.view_%s' % self.model_name)
-            
-        return res
-
 class Project(Document):  
     STATE_CHOICES = (
     (1, 'edition'),
@@ -343,7 +310,6 @@
     state = models.IntegerField(choices=STATE_CHOICES, default=1)
     description = models.TextField(null=True, blank=True)
     objects = models.Manager()
-    objects_safe = SafeManager('project')
     
     class Meta:
         ordering = ["title"]
@@ -365,6 +331,18 @@
             return res[0].get(u'abstract')
         else:
             return None
+        
+    def publish(self):
+        self.state = 2 
+        self.save()
+        public_group = Group.objects.get(name=settings.PUBLIC_GROUP_NAME)
+        assign('view_project', public_group, self)
+        
+    def unpublish(self):
+        self.state = 1
+        self.save()
+        public_group = Group.objects.get(name=settings.PUBLIC_GROUP_NAME)
+        remove_perm('view_project', public_group, self)
 
     def stream_mode(): #@NoSelf
         def fget(self):
@@ -403,6 +381,9 @@
         project.save()
         assign('view_project', user, project)
         assign('change_project', user, project)
+        for g in user.groups.all():
+            assign('view_project', g, project)
+            assign('change_project', g, project)
         for content in contents:
             project.contents.add(content)
         project.save()
--- a/src/ldt/ldt/ldt_utils/security.py	Fri Nov 04 10:31:47 2011 +0100
+++ b/src/ldt/ldt/ldt_utils/security.py	Fri Nov 04 16:45:40 2011 +0100
@@ -1,42 +1,42 @@
-from django.conf import settings
-from ldt.ldt_utils.models import Project
-
-
-def group_security(func):
-    def wrapper(request, *args, **kwargs):
-        if settings.USE_GROUP_PERMISSIONS:
-            if not request.user:
-                raise AttributeError("A user should be set in the request.")
-            
-            if Project.objects_safe.has_user():
-                response = func(request, *args, **kwargs)
-            else:                    
-                Project.objects_safe.check_perm_for(request.user)
-                
-                old_project_manager = Project.objects                         
-                old_save_method = Project.save
-                Project.save = save_security(request.user)(Project.save)
-                Project.objects = Project.objects_safe
-                
-                response = func(request, *args, **kwargs)
-                
-                Project.objects = old_project_manager 
-                Project.save = old_save_method     
-                Project.objects_safe.stop_checking()
-            
-        else:
-            response = func(request, *args, **kwargs)
-        return response
-    return wrapper
-
- 
-def save_security(user):
-    def wrapper(func):
-        def wrapped(self, *args, **kwargs):
-            
-            if not user.has_perm('change_project', self):
-                raise AttributeError('User %s does not have sufficient permissions to change object %s' % (user, self))
-            
-            return func(self, *args, **kwargs)
-        return wrapped
-    return wrapper
\ No newline at end of file
+#from django.conf import settings
+#from ldt.ldt_utils.models import Project
+#
+#
+#def group_security(func):
+#    def wrapper(request, *args, **kwargs):
+#        if settings.USE_GROUP_PERMISSIONS:
+#            if not request.user:
+#                raise AttributeError("A user should be set in the request.")
+#            
+#            if Project.objects_safe.has_user():
+#                response = func(request, *args, **kwargs)
+#            else:                    
+#                Project.objects_safe.check_perm_for(request.user)
+#                
+#                old_project_manager = Project.objects                         
+#                old_save_method = Project.save
+#                Project.save = save_security(request.user)(Project.save)
+#                Project.objects = Project.objects_safe
+#                
+#                response = func(request, *args, **kwargs)
+#                
+#                Project.objects = old_project_manager 
+#                Project.save = old_save_method     
+#                Project.objects_safe.stop_checking()
+#            
+#        else:
+#            response = func(request, *args, **kwargs)
+#        return response
+#    return wrapper
+#
+# 
+#def save_security(user):
+#    def wrapper(func):
+#        def wrapped(self, *args, **kwargs):
+#            
+#            if not user.has_perm('change_project', self):
+#                raise AttributeError('User %s does not have sufficient permissions to change object %s' % (user, self))
+#            
+#            return func(self, *args, **kwargs)
+#        return wrapped
+#    return wrapper
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/views.py	Fri Nov 04 10:31:47 2011 +0100
+++ b/src/ldt/ldt/ldt_utils/views.py	Fri Nov 04 16:45:40 2011 +0100
@@ -21,7 +21,6 @@
 from guardian.shortcuts import assign, remove_perm
 from ldt.ldt_utils.models import Content
 from ldt.ldt_utils.utils import boolean_convert, LdtUtils, LdtSearch
-from ldt.ldt_utils.security import group_security
 from lxml.html import fragment_fromstring
 from models import Media, Project
 from projectserializer import ProjectSerializer
@@ -42,7 +41,6 @@
 import datetime
 
 @login_required
-@group_security
 def workspace(request):
     
     # list of contents
@@ -61,7 +59,6 @@
 
 
 @login_required
-@group_security
 def groups(request):
 
     # get list of all published projects
@@ -77,7 +74,6 @@
 
 
 @login_required
-@group_security
 def published_project(request):
 
     # get list of all published projects
@@ -201,7 +197,6 @@
 
 
 @login_required
-@group_security
 def search_index(request):
         
     sform = SearchForm(request.POST)
@@ -697,11 +692,9 @@
     return render_to_response('ldt/ldt_utils/save_done.html', {'ldt': ldt, 'id':id, 'title':ldtproject.title, 'contents': new_contents}, context_instance=RequestContext(request))
 
 @login_required
-@group_security
 def publish(request, id, redirect=True):
     ldt = get_object_or_404(Project, ldt_id=id)
-    ldt.state = 2 #published
-    ldt.save()
+    ldt.publish()
     redirect = boolean_convert(redirect)
     if redirect:
         return HttpResponseRedirect(reverse("ldt.ldt_utils.views.list_ldt"))
@@ -709,11 +702,9 @@
         return HttpResponse(simplejson.dumps({'res':True, 'ldt': {'id': ldt.id, 'state':ldt.state, 'ldt_id': ldt.ldt_id}}, ensure_ascii=False), mimetype='application/json')
 
 @login_required
-@group_security
 def unpublish(request, id, redirect=True):
     ldt = get_object_or_404(Project, ldt_id=id)
-    ldt.state = 1 #edition
-    ldt.save()
+    ldt.unpublish()
     redirect = boolean_convert(redirect)
     if redirect:
         return HttpResponseRedirect(reverse("ldt.ldt_utils.views.list_ldt"))
@@ -770,7 +761,6 @@
     return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'contents':contents, 'create_project_action':reverse("ldt.ldt_utils.views.create_project", args=[iri_id]), 'target_parent':target_parent}, context_instance=RequestContext(request))
 
 @login_required
-@group_security
 def update_project(request, ldt_id):
 
     project = get_object_or_404(Project, ldt_id=ldt_id)
@@ -1139,7 +1129,6 @@
 
 
 @login_required
-@group_security
 def get_group_projects(request):
 
     # Get group, user and project_list
--- a/src/ldt/ldt/user/models.py	Fri Nov 04 10:31:47 2011 +0100
+++ b/src/ldt/ldt/user/models.py	Fri Nov 04 16:45:40 2011 +0100
@@ -27,6 +27,8 @@
         else:
             new_user.set_unusable_password()
         new_user.save()
+        public_group = Group.objects.get(name=settings.PUBLIC_GROUP_NAME)
+        new_user.groups.add(public_group)
         return new_user  
     
     
--- a/web/ldtplatform/settings.py	Fri Nov 04 10:31:47 2011 +0100
+++ b/web/ldtplatform/settings.py	Fri Nov 04 16:45:40 2011 +0100
@@ -88,6 +88,7 @@
     'django.contrib.messages.middleware.MessageMiddleware',
     'django_openid_consumer.middleware.OpenIDMiddleware',
     'ldt.ldt_utils.middleware.userprofile.LanguageMiddleware',
+    'ldt.ldt_utils.middleware.security.SecurityMiddleware',
 )
 
 TEMPLATE_CONTEXT_PROCESSORS = (