Models in ldt_utils derived from SafeModel instead of django.db.model
authorverrierj
Tue, 15 Nov 2011 12:47:13 +0100
changeset 240 a46cb257d8ee
parent 239 352be36c9fd7
child 241 8649bd4f2443
Models in ldt_utils derived from SafeModel instead of django.db.model
src/ldt/ldt/ldt_utils/models.py
src/ldt/ldt/ldt_utils/security.py
src/ldt/ldt/ldt_utils/views.py
src/ldt/ldt/security/manager.py
src/ldt/ldt/security/middleware.py
src/ldt/ldt/security/models.py
src/ldt/ldt/security/utils.py
--- a/src/ldt/ldt/ldt_utils/models.py	Tue Nov 15 12:01:16 2011 +0100
+++ b/src/ldt/ldt/ldt_utils/models.py	Tue Nov 15 12:47:13 2011 +0100
@@ -6,6 +6,8 @@
 from ldt.core.models import Document
 from guardian.shortcuts import assign, remove_perm
 import ldt.indexation
+from ldt.security.models import SafeModel
+from ldt.security.manager import SafeManager
 from utils import (create_ldt, copy_ldt, create_empty_iri, update_iri, 
     generate_uuid)
 import lucene
@@ -15,7 +17,7 @@
 import tagging.fields
 import uuid
 
-class Author(models.Model):
+class Author(SafeModel):
 
     handle = models.CharField(max_length=512, unique=True, blank=True, null=True)
     email = models.EmailField(unique=False, blank=True, null=True)
@@ -25,7 +27,7 @@
     def __unicode__(self):
         return unicode(self.id) + " - " + self.handle + ", " + self.email + ", " + self.firstname + " " + self.lastname
 
-class Media(models.Model):
+class Media(SafeModel):
     external_id = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_id'))
     external_permalink = models.URLField(max_length=1024, verify_exists=False, null=True, blank=True, verbose_name=_('media.external_permalink'))
     external_publication_url = models.URLField(max_length=1024, verify_exists=True, null=True, blank=True, verbose_name=_('media.external_publication_url'))
@@ -95,7 +97,7 @@
     def get_by_natural_key(self, iri_id):
         return self.get(iri_id=iri_id)
 
-class Content(models.Model):
+class Content(SafeModel):
     objects = ContentManager()
     
     iri_id = models.CharField(max_length=1024, unique=True, default=generate_uuid, verbose_name=_('content.iri_id'))
@@ -291,7 +293,7 @@
        
     external_id = property(**external_id())
     
-class Project(Document):  
+class Project(Document, SafeModel):  
     STATE_CHOICES = (
     (1, 'edition'),
     (2, 'published'),
@@ -309,7 +311,6 @@
     changed_by = models.CharField(_("changed by"), max_length=70)
     state = models.IntegerField(choices=STATE_CHOICES, default=1)
     description = models.TextField(null=True, blank=True)
-    objects = models.Manager()
     
     class Meta:
         ordering = ["title"]
@@ -406,7 +407,7 @@
             return False
         
 
-class Segment(models.Model):
+class Segment(SafeModel):
     
     project_obj = models.ForeignKey(Project, null=True)
     content = models.ForeignKey(Content)
--- a/src/ldt/ldt/ldt_utils/security.py	Tue Nov 15 12:01:16 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-from django.conf import settings
-from django.db.models import Manager
-from django.contrib.auth.models import Group
-from django.contrib.contenttypes.models import ContentType
-from guardian.shortcuts import assign, remove_perm, get_objects_for_user
-from guardian.core import ObjectPermissionChecker
-
-def protect_models(user):
-    for cls in get_models_to_protect():
-            protect_model(cls, user)
-    
-def unprotect_models():
-    for cls in get_models_to_protect():
-            unprotect_model(cls)
-
-def get_models_to_protect():        
-    to_protect = []
-        
-    for cls_name in settings.USE_GROUP_PERMISSIONS:
-        cls_type = ContentType.objects.get(app_label="ldt_utils", model=cls_name.lower())
-        to_protect.append(cls_type.model_class())
-    return to_protect
-
-def protect_model(cls, user):
-    cls.base_objects = cls.objects
-    cls.objects = SafeManager(cls, user)
-    
-    cls.base_save = cls.save
-    cls.save = save_security(user, cls.__name__.lower())(cls.save)
-    
-def unprotect_model(cls):    
-    if hasattr(cls, '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_objects = get_objects_for_user(self.user, 'ldt_utils.view_%s' % self.model_name)
-            
-        return user_objects    
-    
-def save_security(user, cls_name):
-    def wrapper(func):
-        def wrapped(self, *args, **kwargs):
-            
-            if self.pk and not user.has_perm('change_%s' % cls_name, self):
-                raise AttributeError('User %s is not allowed to change object %s' % (user, self))
-            
-            return func(self, *args, **kwargs)
-        return wrapped
-    
-    return wrapper
-
-def assign_project_to_groups(project, permissions):
-    for elem in permissions:
-        group = Group.objects.get(id=elem['group'])
-        if elem['share']:
-            assign('view_project', group, project)
-            if elem['perms'] == 'write':
-                assign('change_project', group, project)
-        else:
-            remove_perm('view_project', group, project)
-            remove_perm('change_project', group, project) 
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/views.py	Tue Nov 15 12:01:16 2011 +0100
+++ b/src/ldt/ldt/ldt_utils/views.py	Tue Nov 15 12:47:13 2011 +0100
@@ -23,7 +23,7 @@
 from guardian.core import ObjectPermissionChecker
 from ldt.ldt_utils.models import Content
 from ldt.ldt_utils.utils import boolean_convert, LdtUtils, LdtSearch
-from ldt.ldt_utils.security import assign_project_to_groups
+from ldt.security.utils import assign_project_to_groups
 from lxml.html import fragment_fromstring
 from models import Media, Project
 from projectserializer import ProjectSerializer
--- a/src/ldt/ldt/security/manager.py	Tue Nov 15 12:01:16 2011 +0100
+++ b/src/ldt/ldt/security/manager.py	Tue Nov 15 12:47:13 2011 +0100
@@ -4,15 +4,12 @@
 
 class SafeManager(Manager):
     
-    def __init__(self, cls, user=None):
-        super(SafeManager, self).__init__()
-        self.model_name = cls.__name__.lower()
-        self.model = cls  
+    def __init__(self, user=None):
+        super(SafeManager, self).__init__() 
         if user:
             self.check_perm_for(user)
         else:
-            self.user = None
-            self.checker = None     
+            self.user = None   
     
     def check_perm_for(self, user):
         self.user = user
@@ -20,12 +17,11 @@
         
     def stop_checking(self):
         self.user = None
-        self.checker = None
       
     def has_user(self):
-        return self.user != None        
-      
-    def get_query_set(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.")
         
--- a/src/ldt/ldt/security/middleware.py	Tue Nov 15 12:01:16 2011 +0100
+++ b/src/ldt/ldt/security/middleware.py	Tue Nov 15 12:47:13 2011 +0100
@@ -2,13 +2,19 @@
 from django.core.exceptions import MiddlewareNotUsed
 from ldt.security.utils import protect_models, unprotect_models
 
+try:
+    from threading import local
+except ImportError:
+    from django.utils._threading_local import local
+    
+_thread_locals = local()
+    
 class SecurityMiddleware(object):
     
     def __init__(self):
         if not hasattr(settings, 'USE_GROUP_PERMISSIONS') or not settings.USE_GROUP_PERMISSIONS:
             raise MiddlewareNotUsed()
 
-    # !! Will not work with concurrent requests
     def process_request(self, request):    
         protect_models(request.user)      
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/security/models.py	Tue Nov 15 12:47:13 2011 +0100
@@ -0,0 +1,9 @@
+from django.db import models
+from manager import SafeManager
+
+class SafeModel(models.Model):
+    objects = models.Manager()
+    safe_objects = SafeManager()
+    
+    class Meta:
+        abstract = True
\ No newline at end of file
--- a/src/ldt/ldt/security/utils.py	Tue Nov 15 12:01:16 2011 +0100
+++ b/src/ldt/ldt/security/utils.py	Tue Nov 15 12:47:13 2011 +0100
@@ -2,7 +2,6 @@
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.auth.models import Group
 from guardian.shortcuts import assign, remove_perm
-from manager import SafeManager
 
 def protect_models(user):
     for cls in get_models_to_protect():
@@ -20,20 +19,21 @@
         to_protect.append(cls_type.model_class())
     return to_protect
 
-def protect_model(cls, user):
-    cls.base_objects = cls.objects
-    cls.objects = SafeManager(cls, user)
-    
+def protect_model(cls, user):   
+    cls.safe_objects.check_perm_for(user)
+     
     cls.base_save = cls.save
-    cls.save = change_security(user, cls.__name__.lower())(cls.save)
-    
+    cls.base_delete = cls.delete
+    class_name = cls.__name__.lower()
+    cls.save = change_security(user, class_name)(cls.save)
+    cls.delete = change_security(user, class_name)(cls.delete)    
     
 def unprotect_model(cls):    
-    if hasattr(cls, 'base_objects'):
-        cls.objects = cls.base_objects
-        cls.save = cls.base_save
-        del cls.base_objects    
-        del cls.base_save
+    if hasattr(cls, 'base_save'):
+        cls.save = cls.base_save 
+        cls.delete = cls.base_delete
+        del cls.base_save    
+        del cls.base_delete
         
 def change_security(user, cls_name):
     def wrapper(func):