# HG changeset patch # User verrierj # Date 1320421540 -3600 # Node ID 2878499a372bedce6fcfc726177d6ceb7dd7b271 # Parent 535ce952e51cda588038658aeb11ecfec539ef1f Security layer moved to middleware and ldt_utils __init__ file diff -r 535ce952e51c -r 2878499a372b src/ldt/ldt/ldt_utils/__init__.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 diff -r 535ce952e51c -r 2878499a372b src/ldt/ldt/ldt_utils/middleware/security.py --- /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 diff -r 535ce952e51c -r 2878499a372b src/ldt/ldt/ldt_utils/models.py --- 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() diff -r 535ce952e51c -r 2878499a372b src/ldt/ldt/ldt_utils/security.py --- 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 diff -r 535ce952e51c -r 2878499a372b src/ldt/ldt/ldt_utils/views.py --- 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 diff -r 535ce952e51c -r 2878499a372b src/ldt/ldt/user/models.py --- 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 diff -r 535ce952e51c -r 2878499a372b web/ldtplatform/settings.py --- 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 = (