src/ldt/ldt/security/utils.py
author verrierj
Wed, 30 Nov 2011 14:15:17 +0100
changeset 263 eba92ea32281
parent 260 3d9cb9b6ff8d
child 264 47c83e79e3c4
permissions -rw-r--r--
Ask confirmation when user leaves a group
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
     1
from django.conf import settings
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
     2
from django.contrib.contenttypes.models import ContentType
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
     3
from django.contrib.auth.models import Group
251
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
     4
from guardian.core import ObjectPermissionChecker
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
     5
from guardian.shortcuts import assign, remove_perm
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
     6
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
     7
try:
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
     8
    from threading import local
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
     9
except ImportError:
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    10
    from django.utils._threading_local import local
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    11
    
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    12
_thread_locals = local()
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    13
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    14
def get_current_user():
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    15
    return getattr(_thread_locals, 'user', None)
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    16
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    17
def protect_models():
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    18
    user = get_current_user()
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    19
    for cls in ToProtect.get_models():
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    20
            protect_model(cls, user)
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    21
    
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    22
def unprotect_models():
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    23
    for cls in ToProtect.get_models():
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    24
            unprotect_model(cls)
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    25
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    26
class ToProtect(object):
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    27
    
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    28
    @staticmethod
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    29
    def get_models():
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    30
        if hasattr(ToProtect, 'cls_list'):
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    31
            return ToProtect.cls_list
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    32
        
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    33
        cls_list = []
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    34
        for cls_name in settings.USE_GROUP_PERMISSIONS:
242
bee98775a8e8 Clean code of SafeManager
verrierj
parents: 241
diff changeset
    35
            cls_type = ContentType.objects.get(model=cls_name.lower())
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    36
            cls_list.append(cls_type.model_class())
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    37
        ToProtect.cls_list = cls_list
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    38
        
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    39
        return cls_list
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    40
240
a46cb257d8ee Models in ldt_utils derived from SafeModel instead of django.db.model
verrierj
parents: 239
diff changeset
    41
def protect_model(cls, user):   
242
bee98775a8e8 Clean code of SafeManager
verrierj
parents: 241
diff changeset
    42
    cls.safe_objects.user = user
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    43
    
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    44
    cls.old_save = cls.save
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    45
    cls.old_delete = cls.delete
240
a46cb257d8ee Models in ldt_utils derived from SafeModel instead of django.db.model
verrierj
parents: 239
diff changeset
    46
    class_name = cls.__name__.lower()
242
bee98775a8e8 Clean code of SafeManager
verrierj
parents: 241
diff changeset
    47
    cls.save = change_security(user, class_name)(cls.save)
bee98775a8e8 Clean code of SafeManager
verrierj
parents: 241
diff changeset
    48
    cls.delete = change_security(user, class_name)(cls.delete)    
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    49
    
245
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    50
def unprotect_model(cls): 
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    51
    if hasattr(cls, 'old_save'):
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    52
        cls.save = cls.old_save 
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    53
        cls.delete = cls.old_delete 
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    54
        del cls.old_save    
245
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    55
        del cls.old_delete
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    56
        cls.safe_objects.user = None 
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    57
        
242
bee98775a8e8 Clean code of SafeManager
verrierj
parents: 241
diff changeset
    58
def change_security(user, cls_name):
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    59
    def wrapper(func):
242
bee98775a8e8 Clean code of SafeManager
verrierj
parents: 241
diff changeset
    60
        def wrapped(self, *args, **kwargs):                      
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    61
                        
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    62
            if self.pk and not user.has_perm('change_%s' % cls_name, self):
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    63
                raise AttributeError('User %s is not allowed to change object %s' % (user, self))
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    64
      
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    65
            return func(self, *args, **kwargs)
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    66
        return wrapped    
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    67
    return wrapper
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    68
245
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    69
def set_forbidden_stream(xml, user):
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    70
    cls = ContentType.objects.get(model='content')
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    71
    cls = cls.model_class()
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    72
    
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    73
    old_user = cls.safe_objects.user
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    74
    obj_list = cls.safe_objects.all()
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    75
    
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    76
    for elem in xml.xpath('/iri/medias/media'):
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    77
        if not obj_list.filter(iri_id=elem.get('id')):
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    78
            elem.set('video', settings.FORBIDDEN_STREAM_URL)
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    79
    
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    80
    cls.safe_objects.user = old_user 
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    81
    
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    82
    return xml
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    83
251
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    84
def add_change_attr(user, obj_list):
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    85
    if len(obj_list) == 0:
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    86
        return []
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    87
    
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    88
    model_name = obj_list[0].__class__.__name__.lower()
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    89
    ctype = ContentType.objects.get(model=model_name)
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    90
    cls = ctype.model_class()
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    91
    
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    92
    checker = ObjectPermissionChecker(user)
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    93
    perm_name = "%s.change_%s" % (cls._meta.app_label, model_name)
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    94
        
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    95
    for obj in obj_list:
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    96
        if checker.has_perm(perm_name, obj):
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    97
            obj.change = True
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    98
        else:
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    99
            obj.change = False
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
   100
            
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
   101
    return obj_list
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
   102
        
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
   103
260
3d9cb9b6ff8d Add permission form to content
verrierj
parents: 251
diff changeset
   104
def assign_object_to_groups(object, permissions):
3d9cb9b6ff8d Add permission form to content
verrierj
parents: 251
diff changeset
   105
    name = object.__class__.__name__.lower()
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
   106
    for elem in permissions:
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
   107
        group = Group.objects.get(id=elem['group'])
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
   108
        if elem['share']:
260
3d9cb9b6ff8d Add permission form to content
verrierj
parents: 251
diff changeset
   109
            assign('view_%s' % name, group, object)
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
   110
            if elem['perms'] == 'write':
260
3d9cb9b6ff8d Add permission form to content
verrierj
parents: 251
diff changeset
   111
                assign('change_%s' % name, group, object)
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
   112
        else:
260
3d9cb9b6ff8d Add permission form to content
verrierj
parents: 251
diff changeset
   113
            remove_perm('view_%s' % name, group, object)
263
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   114
            remove_perm('change_%s' % name, group, object)
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   115
            
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   116
def get_perm_form(groups, formset):
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   117
    perm_list = [] 
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   118
    for group in groups:
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   119
        perm_list.append({'share': False, 'perms': 'read', 'group': group.id })
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   120
    permission = formset(initial=perm_list)
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   121
            
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   122
    management_form = permission.management_form
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   123
    group_form = zip(permission, groups)
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   124
    
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   125
    return (management_form, group_form)  
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
   126