Package expedient :: Package common :: Package permissions :: Module utils
[hide private]
[frames] | no frames]

Source Code for Module expedient.common.permissions.utils

  1  ''' 
  2  Created on Jun 1, 2010 
  3   
  4  @author: jnaous 
  5  ''' 
  6  from django.contrib.contenttypes.models import ContentType 
  7  from django.http import Http404 
  8  from expedient.common.permissions.shortcuts import must_have_permission,\ 
  9      give_permission_to 
 10  from expedient.common.middleware import threadlocals 
 11  from expedient.common.permissions.models import ObjectPermission 
 12   
13 -def get_user_from_req(request, *args, **kwargs):
14 ''' 15 Get the user from the request. This function is helpful when 16 using the require_*_permission_for_view decorators. 17 18 For example:: 19 20 @require_objs_permissions_for_view( 21 ["can_view_obj_detail"], 22 get_user_from_req, 23 get_objects_from_filter_func(Obj, 1), 24 ["GET"], 25 ) 26 def view_obj_detail(request, obj_id): 27 ... 28 29 @param request: the request object 30 @type request: C{HttpRequest} 31 ''' 32 return request.user
33
34 -def get_queryset(klass, index, filter="pk"):
35 """ 36 Returns a function that can be used for the require_*_permission_for_view 37 decorators to get a queryset from some argument. 38 39 The returned function has a signature (*args, **kwargs) and mainly does 40 the following:: 41 42 klass.objects.filter(**{filter: arg}) 43 44 where C{arg} is obtained from the arguments. If C{index} is an 45 C{int}, C{arg} is assumed to be positional. Otherwise, it is assumed to be 46 a keyword. 47 48 For example:: 49 50 @require_obj_permission_for_view( 51 ["can_view_obj_detail"], 52 get_user_from_req, 53 get_queryset(Obj, 1), 54 ["GET"], 55 ) 56 def view_obj_detail(request, obj_id): 57 ... 58 59 @param klass: The class of the object to be returned. 60 @type klass: class 61 @param index: location of the id in the arguments when the arguments are 62 given as (*args, **kwargs). 63 @type index: C{int} for positional, hashable for keyword. 64 @keyword filter: a filter to be used for obtaining the object. 65 @type filter: C{str} 66 67 @return: A callable that returns an object from (*args, **kwargs) 68 """ 69 70 def wrapper(*args, **kwargs): 71 if type(index) == int: 72 arg = args[index] 73 else: 74 arg = kwargs[index] 75 return klass.objects.filter(**{filter: arg})
76 77 return wrapper 78
79 -def get_leaf_queryset(parent_klass, index, filter="pk"):
80 """ 81 Same as L{get_queryset} but also calls the C{as_leaf_class} function 82 on the first element in the queryset and returns a queryset with the 83 returned object's class. 84 """ 85 def wrapper(*args, **kwargs): 86 if type(index) == int: 87 arg = args[index] 88 else: 89 arg = kwargs[index] 90 91 parent_qs = parent_klass.objects.filter(**{filter: arg}) 92 parents = list(parent_qs) 93 if parents: 94 ids = [p.id for p in parents] 95 return parents[0].as_leaf_class().\ 96 __class__.objects.filter(id__in=ids) 97 return parent_qs
98 return wrapper 99
100 -def get_queryset_from_class(klass):
101 """ 102 Returns a function usable as the C{target_func} of the 103 L{require_objs_permissions_for_view} decorator. The returned function 104 returns the C{ContentType} queryset for a class. This can be used to 105 enforce class level permissions on views. 106 107 @param klass: the model class for which we want the queryset. 108 """ 109 def target_func(*args, **kwargs): 110 ct = ContentType.objects.get_for_model(klass) 111 return ContentType.objects.filter(pk=ct.pk)
112 return target_func 113
114 -def get_queryset_from_id(klass, id):
115 """ 116 Returns a function usable as a C{target_func} parameter. The returned 117 function returns a C{QuerySet} containing one object with the given C{id}. 118 119 @param klass: the class of the queryset's model. 120 @param id: the object's id. 121 """ 122 def target_func(*args, **kwargs): 123 return klass.objects.filter(id=id)
124 return target_func 125
126 -def get_object_from_ids(ct_id, id):
127 """ 128 Get an object from the ContentType id and from the object's id. 129 130 @param ct_id: ContentType's id for the object class. 131 @param id: object's id. 132 """ 133 try: 134 ct = ContentType.objects.get_for_id(ct_id) 135 except ContentType.DoesNotExist: 136 raise Http404() 137 try: 138 return ct.get_object_for_this_type(pk=id) 139 except ct.model_class().DoesNotExist: 140 raise Http404()
141
142 -def permissions_save_override(permittee_kw, model_func, create_perm, edit_perm, delete_perm):
143 """Get a save function that can be used to enforce create, edit, and 144 delete permissions. 145 146 For example:: 147 148 class ModelX(models.Model): 149 ... 150 save = permissions_save_override( 151 "user", lambda: ModelX, "can_create", "can_edit", "can_delete") 152 153 @param permittee_kw: the keyword used to store the permittee in 154 threadlocals 155 @type permittee_kw: C{str}. 156 @param model_func: A callable that returns the the class. 157 @type model_func: C{Model} subclass 158 @param create_perm: The name of the creation permission for the class. 159 @type create_perm: C{str} 160 @param edit_perm: The name of the edit permission for the instance. 161 @type edit_perm: C{str} 162 @param delete_perm: the name of the delete permission for the instance. 163 @type delete_perm: C{str} 164 @return: a save function that can be used to enforce permissions. 165 @rtype: a callable. 166 """ 167 def save(self, *args, **kwargs): 168 """ 169 Override the default save method to enforce permissions. 170 """ 171 pk = getattr(self, "pk", None) 172 if not pk: 173 # it's a new instance being created 174 must_have_permission(permittee_kw, model_func(), create_perm) 175 else: 176 must_have_permission(permittee_kw, self, edit_perm) 177 178 super(model_func(), self).save(*args, **kwargs) 179 180 if not pk: 181 # it was just created so give creator edit permissions 182 d = threadlocals.get_thread_locals() 183 give_permission_to( 184 edit_perm, self, d[permittee_kw], can_delegate=True) 185 give_permission_to( 186 delete_perm, self, d[permittee_kw], can_delegate=True)
187 return save 188
189 -def permissions_delete_override(permittee_kw, model_func, delete_perm):
190 """Get a delete function that can be used to enforce 191 delete permissions. 192 193 For example:: 194 195 class ModelX(models.Model): 196 ... 197 delete = permissions_delete_override( 198 "user", lambda: ModelX, "can_delete") 199 200 @param permittee_kw: the keyword used to store the permittee in 201 threadlocals 202 @type permittee_kw: C{str}. 203 @param model_func: A callable that returns the class. 204 @type model_func: C{Model} subclass 205 @param delete_perm: the name of the delete permission for the instance. 206 @type delete_perm: C{str} 207 """ 208 def delete(self, *args, **kwargs): 209 """ 210 Override the default delete method to enforce permissions. 211 """ 212 must_have_permission(permittee_kw, self, delete_perm) 213 # delete all permissions for the object 214 ObjectPermission.objects.filter_from_instance(self).delete() 215 super(model_func(), self).delete(*args, **kwargs)
216 return delete 217