Package expedient :: Package clearinghouse :: Package roles :: Module models
[hide private]
[frames] | no frames]

Source Code for Module expedient.clearinghouse.roles.models

  1  ''' 
  2  Created on Aug 3, 2010 
  3   
  4  @author: jnaous 
  5  ''' 
  6  from django.db import models 
  7  from django.contrib.auth.models import User 
  8  from django.contrib.contenttypes.models import ContentType 
  9  from django.db.models import F, Count 
 10  from expedient.clearinghouse.project.models import Project 
 11  from expedient.common.permissions.models import ObjectPermission, Permittee,\ 
 12      PermissionOwnership 
 13  from expedient.common.messaging.models import DatedMessage 
 14   
15 -class ProjectRoleManager(models.Manager):
16 """Manager for L{ProjectRole} instances.""" 17
18 - def get_users_with_role(self, role_name, project):
19 """Get a C{User} query set for users that have role C{role_name} in 20 project C{project} 21 22 @param role_name: Name of the project role. 23 @type role_name: C{str}. 24 @param project: project instance. 25 @type project: L{Project}. 26 @return: all users with that role in the project 27 @rtype: C{QuerySet} of C{User} objects. 28 """ 29 user_ids = set(Permittee.objects.filter( 30 projectrole__name=role_name, 31 projectrole__project=project).values_list( 32 "pk", flat=True)) 33 return User.objects.filter(pk__in=user_ids)
34
35 - def filter_for_can_delegate(self, permittee, project):
36 """filter for all roles the permittee can fully delegate in a project 37 38 @param permittee: object to check for delegatable roles. 39 @type permittee: L{Permittee} or C{django.db.models.Model} 40 @param project: the project to filter roles for 41 @type project: L{Project} 42 @return: all project roles the permittee can delegate. 43 @rtype: C{QuerySet} of C{ProjectRole}s. 44 """ 45 permittee = Permittee.objects.get_as_permittee(permittee) 46 47 # get all the permissions the permittee cannot delegate 48 obj_perms_ids = list(ObjectPermission.objects.exclude( 49 permissionownership__can_delegate=True, 50 permissionownership__permittee=permittee, 51 ).filter(projectrole__project=project).values_list("pk", flat=True)) 52 53 # take out any roles that have a permission the 54 # permittee cannot delegate 55 return self.exclude( 56 obj_permissions__pk__in=obj_perms_ids).filter( 57 project=project)
58
59 - def filter_for_permission(self, perm_name, target):
60 """Filter roles that have the permission C{perm_name} for C{target}. 61 62 @param perm_name: The name of the permission to filter the roles for. 63 @type perm_name: C{str}. 64 @param target: The object that is the target of the permission. 65 @type target: instance of C{Model}. Note this cannot be a C{class}. 66 @return: Only project roles that have the permission for the target. 67 @rtype: C{QuerySet} for C{ProjectRole}. 68 69 """ 70 71 return self.filter( 72 obj_permissions__permission__name=perm_name, 73 obj_permissions__object_type=\ 74 ContentType.objects.get_for_model(target.__class__), 75 obj_permissions__object_id=target.pk, 76 ).distinct()
77
78 -class ProjectRole(models.Model):
79 """Groups object permissions together for easier fine-grained management. 80 This role is local to a project. 81 82 @cvar objects: a L{ProjectRoleManager}. 83 84 @ivar name: The name of the role. Doesn't needs to be unique within a 85 project. 86 @type name: str, max length=100 87 @ivar description: Information about the role. 88 @type description: TextField 89 @ivar project: The project for this role. 90 @type project: L{Project} 91 @ivar obj_permissions: object permissions that this roles groups. 92 @type obj_permissions: C{ManyToManyField} to L{ObjectPermission}. 93 @ivar permittees: Set of permittees that have this role. 94 @type permittees: C{ManyToManyField} to L{Permittee}. 95 """ 96 97 objects = ProjectRoleManager() 98 99 name = models.CharField( 100 max_length=100, 101 help_text="Enter the name of the role. This should be unique within " 102 "the project.") 103 description = models.TextField(blank=True, default="", 104 help_text="The role's description should help users know what the " 105 "role is meant for and what capabilities the role gives.") 106 project = models.ForeignKey(Project) 107 obj_permissions = models.ManyToManyField( 108 ObjectPermission, verbose_name="Role's permissions", 109 help_text="Select the permissions that users who have role " 110 "should have." 111 ) 112 permittees = models.ManyToManyField(Permittee) 113
114 - class Meta:
115 unique_together = ( 116 ("name", "project"), 117 )
118
119 - def __unicode__(self):
120 return self.name
121
122 - def give_to_permittee(self, permittee, giver=None, can_delegate=False):
123 """Give the role to a permittee. This combines the permittee's 124 permissions. 125 126 @param permittee: object to give the role to. 127 @type permittee: object or L{Permittee} instance. 128 @keyword giver: The giver of all the permissions in the roles. If 129 not C{None}, the giver will be checked for authorization to 130 delegate the permission. 131 @type giver: Model instance or L{Permittee} 132 @keyword can_delegate: Should the permittee be able to give the 133 permissions in the role to others? Default False. 134 @type can_delegate: C{bool}. 135 """ 136 137 permittee = Permittee.objects.get_as_permittee(permittee) 138 self.permittees.add(permittee) 139 for obj_perm in self.obj_permissions.all(): 140 obj_perm.give_to( 141 permittee, giver=giver, can_delegate=can_delegate)
142
143 - def delete(self):
144 for permittee in self.permittees.all(): 145 self.remove_from_permittee(permittee) 146 return super(ProjectRole, self).delete()
147
148 - def remove_from_permittee(self, permittee):
149 """Remove all the permissions in this role from the permittee except 150 for ones given by another role.""" 151 152 permittee = Permittee.objects.get_as_permittee(permittee) 153 self.permittees.remove(permittee) 154 155 # Get the IDs of the other permissions. 156 other_roles = ProjectRole.objects.filter(permittees=permittee) 157 other_perms_ids = [] 158 for r in other_roles: 159 other_perms_ids.extend( 160 r.obj_permissions.all().values_list("id", flat=True)) 161 162 # get the list of permissions to remove and remove all. 163 to_remove = list(self.obj_permissions.exclude(id__in=other_perms_ids)) 164 PermissionOwnership.objects.filter( 165 permittee=permittee, obj_permission__in=to_remove).delete()
166
167 - def add_permission(self, obj_permission, giver=None, can_delegate=False):
168 """Add the object permission to the role and to all permittees who 169 have this role. 170 171 @param obj_permission: The object permission to add. 172 @type obj_permission: L{ObjectPermission}. 173 @keyword giver: The giver of the permission in the roles. If 174 not C{None}, the giver will be checked for authorization to 175 delegate the permission. 176 @type giver: Model instance or L{Permittee} 177 @keyword can_delegate: Should the permittees with this role be able 178 to give the permission to others? 179 @type can_delegate: C{bool}. 180 """ 181 182 for p in self.permittees.all(): 183 obj_permission.give_to(p, giver=giver, can_delegate=can_delegate) 184 self.obj_permissions.add(obj_permission)
185
186 - def remove_permission(self, obj_permission):
187 """Opposite of L{add_permission} but does not remove the permission 188 from permittees with other roles that have the permission. 189 """ 190 191 self.obj_permissions.remove(obj_permission) 192 193 permittees = self.permittees.exclude( 194 projectrole__obj_permissions=obj_permission, 195 ) 196 197 PermissionOwnership.objects.filter( 198 permittee__id__in=list( 199 permittees.values_list("pk", flat=True)), 200 obj_permission=obj_permission, 201 ).delete()
202
203 -class ProjectRoleRequest(models.Model):
204 """A request for a project role""" 205 206 requester = models.ForeignKey( 207 User, help_text="User requesting the role.", 208 related_name="role_requests_made") 209 requested_role = models.ForeignKey( 210 ProjectRole, help_text="Choose a role to request.") 211 giver = models.ForeignKey( 212 User, help_text="Choose a user to make a request to.", 213 related_name="role_requests_received") 214 message = models.TextField( 215 blank=True, default="", 216 help_text="Add a personalized message to the request.") 217
218 - def approve(self, delegate):
219 self.requested_role.give_to_permittee( 220 self.requester, giver=self.giver, can_delegate=delegate) 221 DatedMessage.objects.post_message_to_users( 222 "'%s' '%s' role '%s' to '%s'" % ( 223 self.giver.username, 224 "delegated" if delegate else "gave", 225 self.requested_role.name, self.requester.username), 226 msg_type=DatedMessage.TYPE_SUCCESS, 227 username__in=[self.requester.username, self.giver.username]) 228 self.delete()
229
230 - def deny(self):
231 DatedMessage.objects.post_message_to_users( 232 "%s denied giving role %s to %s" % ( 233 self.giver.username, 234 self.requested_role.name, self.requester.username), 235 msg_type=DatedMessage.TYPE_WARNING, 236 username__in=[self.requester.username, self.giver.username]) 237 self.delete()
238