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
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
251
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
     3
from guardian.core import ObjectPermissionChecker
268
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
     4
from guardian.shortcuts import assign, remove_perm, get_users_with_perms, get_groups_with_perms
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
     5
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
     6
try:
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
     7
    from threading import local
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
     8
except ImportError:
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
     9
    from django.utils._threading_local import local
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    10
    
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    11
_thread_locals = local()
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    12
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    13
def get_current_user():
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    14
    return getattr(_thread_locals, 'user', None)
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    15
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    16
def protect_models():
264
47c83e79e3c4 Improve css + fix minor bugs
verrierj
parents: 263
diff changeset
    17
    cls_list = ToProtect.get_models()
47c83e79e3c4 Improve css + fix minor bugs
verrierj
parents: 263
diff changeset
    18
    if cls_list:
47c83e79e3c4 Improve css + fix minor bugs
verrierj
parents: 263
diff changeset
    19
        user = get_current_user()
47c83e79e3c4 Improve css + fix minor bugs
verrierj
parents: 263
diff changeset
    20
        for cls in ToProtect.get_models():
47c83e79e3c4 Improve css + fix minor bugs
verrierj
parents: 263
diff changeset
    21
                protect_model(cls, user)
47c83e79e3c4 Improve css + fix minor bugs
verrierj
parents: 263
diff changeset
    22
    
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    23
    
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    24
def unprotect_models():
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    25
    for cls in ToProtect.get_models():
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    26
            unprotect_model(cls)
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    27
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    28
class ToProtect(object):
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    29
    
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    30
    @staticmethod
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    31
    def get_models():
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    32
        if hasattr(ToProtect, 'cls_list'):
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    33
            return ToProtect.cls_list
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    34
        
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    35
        cls_list = []
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    36
        for cls_name in settings.USE_GROUP_PERMISSIONS:
242
bee98775a8e8 Clean code of SafeManager
verrierj
parents: 241
diff changeset
    37
            cls_type = ContentType.objects.get(model=cls_name.lower())
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    38
            cls_list.append(cls_type.model_class())
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    39
        ToProtect.cls_list = cls_list
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    40
        
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    41
        return cls_list
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    42
240
a46cb257d8ee Models in ldt_utils derived from SafeModel instead of django.db.model
verrierj
parents: 239
diff changeset
    43
def protect_model(cls, user):   
242
bee98775a8e8 Clean code of SafeManager
verrierj
parents: 241
diff changeset
    44
    cls.safe_objects.user = user
265
491d057cbfd2 Fix bug when selecting media in content creation window
verrierj
parents: 264
diff changeset
    45
    cls.safe_objects.check_perm = True
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    46
    
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    47
    cls.old_save = cls.save
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    48
    cls.old_delete = cls.delete
240
a46cb257d8ee Models in ldt_utils derived from SafeModel instead of django.db.model
verrierj
parents: 239
diff changeset
    49
    class_name = cls.__name__.lower()
264
47c83e79e3c4 Improve css + fix minor bugs
verrierj
parents: 263
diff changeset
    50
    cls.save = change_security(class_name)(cls.save)
47c83e79e3c4 Improve css + fix minor bugs
verrierj
parents: 263
diff changeset
    51
    cls.delete = change_security(class_name)(cls.delete)    
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    52
    
245
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    53
def unprotect_model(cls): 
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    54
    if hasattr(cls, 'old_save'):
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    55
        cls.save = cls.old_save 
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    56
        cls.delete = cls.old_delete 
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    57
        del cls.old_save    
245
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    58
        del cls.old_delete
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    59
        cls.safe_objects.user = None 
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    60
        
264
47c83e79e3c4 Improve css + fix minor bugs
verrierj
parents: 263
diff changeset
    61
def change_security(cls_name):
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    62
    def wrapper(func):
242
bee98775a8e8 Clean code of SafeManager
verrierj
parents: 241
diff changeset
    63
        def wrapped(self, *args, **kwargs):                      
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    64
                        
264
47c83e79e3c4 Improve css + fix minor bugs
verrierj
parents: 263
diff changeset
    65
            if self.pk and not get_current_user().has_perm('change_%s' % cls_name, self):
47c83e79e3c4 Improve css + fix minor bugs
verrierj
parents: 263
diff changeset
    66
                raise AttributeError('User %s is not allowed to change object %s' % (get_current_user(), self))
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
    67
      
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    68
            return func(self, *args, **kwargs)
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    69
        return wrapped    
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    70
    return wrapper
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
    71
245
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    72
def set_forbidden_stream(xml, user):
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    73
    cls = ContentType.objects.get(model='content')
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    74
    cls = cls.model_class()
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
    old_user = cls.safe_objects.user
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    77
    obj_list = cls.safe_objects.all()
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    78
    
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    79
    for elem in xml.xpath('/iri/medias/media'):
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    80
        if not obj_list.filter(iri_id=elem.get('id')):
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    81
            elem.set('video', settings.FORBIDDEN_STREAM_URL)
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    82
    
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    83
    cls.safe_objects.user = old_user 
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    84
    
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    85
    return xml
953228fcbb56 Permissions are checked in search results
verrierj
parents: 242
diff changeset
    86
251
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    87
def add_change_attr(user, obj_list):
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    88
    if len(obj_list) == 0:
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    89
        return []
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    90
    
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    91
    model_name = obj_list[0].__class__.__name__.lower()
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    92
    ctype = ContentType.objects.get(model=model_name)
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    93
    cls = ctype.model_class()
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
    checker = ObjectPermissionChecker(user)
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    96
    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
    97
        
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    98
    for obj in obj_list:
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
    99
        if checker.has_perm(perm_name, obj):
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
   100
            obj.change = True
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
   101
        else:
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
   102
            obj.change = False
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
   103
            
264
47c83e79e3c4 Improve css + fix minor bugs
verrierj
parents: 263
diff changeset
   104
    return obj_list      
251
81417fd477b0 Display specific tooltip when project edition is not allowed
verrierj
parents: 245
diff changeset
   105
268
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   106
def assign_object_to_groups(object, read_list, write_list, owner):
260
3d9cb9b6ff8d Add permission form to content
verrierj
parents: 251
diff changeset
   107
    name = object.__class__.__name__.lower()
268
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   108
    
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   109
    old_users = get_users_with_perms(object).exclude(id=owner.id)
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   110
    old_groups = get_groups_with_perms(object)
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   111
    
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   112
    for elem in read_list:
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   113
        assign('view_%s' % name, elem, object)
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   114
        if elem in write_list:
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   115
            assign('change_%s' % name, elem, object)
239
352be36c9fd7 Moved code about group security into a separate module
verrierj
parents:
diff changeset
   116
        else:
268
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   117
            remove_perm('change_%s' % name, elem, object)            
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   118
                
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   119
    def remove_perms(new_list, old_list, obj, name):
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   120
        for e in old_list:
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   121
            if e not in new_list:
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   122
                remove_perm('view_%s' % name, e, obj)
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   123
                remove_perm('change_%s' % name, e, obj)
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   124
                
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   125
    remove_perms(read_list, old_users, object, name)
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   126
    remove_perms(read_list, old_groups, object, name)
c0c161736794 Projects can be shared with users and groups. Does not work with contents yet, still some bugs in templates
verrierj
parents: 265
diff changeset
   127
            
263
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   128
            
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   129
def get_perm_form(groups, formset):
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   130
    perm_list = [] 
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   131
    for group in groups:
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   132
        perm_list.append({'share': False, 'perms': 'read', 'group': group.id })
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   133
    permission = formset(initial=perm_list)
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   134
            
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   135
    management_form = permission.management_form
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   136
    group_form = zip(permission, groups)
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   137
    
eba92ea32281 Ask confirmation when user leaves a group
verrierj
parents: 260
diff changeset
   138
    return (management_form, group_form)  
241
8649bd4f2443 Moved threadlocals to utils
verrierj
parents: 240
diff changeset
   139