src/ldt/ldt/security/utils.py
author verrierj
Tue, 06 Dec 2011 17:45:35 +0100
changeset 268 c0c161736794
parent 265 491d057cbfd2
child 269 4b8042fc3d33
permissions -rw-r--r--
Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates

from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from guardian.core import ObjectPermissionChecker
from guardian.shortcuts import assign, remove_perm, get_users_with_perms, get_groups_with_perms

try:
    from threading import local
except ImportError:
    from django.utils._threading_local import local
    
_thread_locals = local()

def get_current_user():
    return getattr(_thread_locals, 'user', None)

def protect_models():
    cls_list = ToProtect.get_models()
    if cls_list:
        user = get_current_user()
        for cls in ToProtect.get_models():
                protect_model(cls, user)
    
    
def unprotect_models():
    for cls in ToProtect.get_models():
            unprotect_model(cls)

class ToProtect(object):
    
    @staticmethod
    def get_models():
        if hasattr(ToProtect, 'cls_list'):
            return ToProtect.cls_list
        
        cls_list = []
        for cls_name in settings.USE_GROUP_PERMISSIONS:
            cls_type = ContentType.objects.get(model=cls_name.lower())
            cls_list.append(cls_type.model_class())
        ToProtect.cls_list = cls_list
        
        return cls_list

def protect_model(cls, user):   
    cls.safe_objects.user = user
    cls.safe_objects.check_perm = True
    
    cls.old_save = cls.save
    cls.old_delete = cls.delete
    class_name = cls.__name__.lower()
    cls.save = change_security(class_name)(cls.save)
    cls.delete = change_security(class_name)(cls.delete)    
    
def unprotect_model(cls): 
    if hasattr(cls, 'old_save'):
        cls.save = cls.old_save 
        cls.delete = cls.old_delete 
        del cls.old_save    
        del cls.old_delete
        cls.safe_objects.user = None 
        
def change_security(cls_name):
    def wrapper(func):
        def wrapped(self, *args, **kwargs):                      
                        
            if self.pk and not get_current_user().has_perm('change_%s' % cls_name, self):
                raise AttributeError('User %s is not allowed to change object %s' % (get_current_user(), self))
      
            return func(self, *args, **kwargs)
        return wrapped    
    return wrapper

def set_forbidden_stream(xml, user):
    cls = ContentType.objects.get(model='content')
    cls = cls.model_class()
    
    old_user = cls.safe_objects.user
    obj_list = cls.safe_objects.all()
    
    for elem in xml.xpath('/iri/medias/media'):
        if not obj_list.filter(iri_id=elem.get('id')):
            elem.set('video', settings.FORBIDDEN_STREAM_URL)
    
    cls.safe_objects.user = old_user 
    
    return xml

def add_change_attr(user, obj_list):
    if len(obj_list) == 0:
        return []
    
    model_name = obj_list[0].__class__.__name__.lower()
    ctype = ContentType.objects.get(model=model_name)
    cls = ctype.model_class()
    
    checker = ObjectPermissionChecker(user)
    perm_name = "%s.change_%s" % (cls._meta.app_label, model_name)
        
    for obj in obj_list:
        if checker.has_perm(perm_name, obj):
            obj.change = True
        else:
            obj.change = False
            
    return obj_list      

def assign_object_to_groups(object, read_list, write_list, owner):
    name = object.__class__.__name__.lower()
    
    old_users = get_users_with_perms(object).exclude(id=owner.id)
    old_groups = get_groups_with_perms(object)
    
    for elem in read_list:
        assign('view_%s' % name, elem, object)
        if elem in write_list:
            assign('change_%s' % name, elem, object)
        else:
            remove_perm('change_%s' % name, elem, object)            
                
    def remove_perms(new_list, old_list, obj, name):
        for e in old_list:
            if e not in new_list:
                remove_perm('view_%s' % name, e, obj)
                remove_perm('change_%s' % name, e, obj)
                
    remove_perms(read_list, old_users, object, name)
    remove_perms(read_list, old_groups, object, name)
            
            
def get_perm_form(groups, formset):
    perm_list = [] 
    for group in groups:
        perm_list.append({'share': False, 'perms': 'read', 'group': group.id })
    permission = formset(initial=perm_list)
            
    management_form = permission.management_form
    group_form = zip(permission, groups)
    
    return (management_form, group_form)