Package expedient :: Package clearinghouse :: Package project :: Module views
[hide private]
[frames] | no frames]

Source Code for Module expedient.clearinghouse.project.views

  1  ''' 
  2  @author: jnaous 
  3  ''' 
  4   
  5  from django.views.generic import list_detail, create_update, simple 
  6  from models import Project 
  7  from forms import ProjectCreateForm 
  8  from django.http import HttpResponseRedirect, HttpResponseNotAllowed, Http404 
  9  from django.core.urlresolvers import reverse 
 10  from django.shortcuts import get_object_or_404 
 11  from expedient.clearinghouse.aggregate.models import Aggregate 
 12  import logging 
 13  from expedient.common.utils.views import generic_crud 
 14  from expedient.common.messaging.models import DatedMessage 
 15  from django.db.models import Q 
 16  from expedient.common.permissions.decorators import require_objs_permissions_for_view 
 17  from expedient.common.permissions.utils import get_queryset, get_user_from_req,\ 
 18      get_queryset_from_class 
 19  from expedient.clearinghouse.roles.models import ProjectRole,\ 
 20      ProjectRoleRequest 
 21  from expedient.common.permissions.models import ObjectPermission,\ 
 22      PermissionOwnership, Permittee 
 23  from expedient.clearinghouse.project.forms import AddMemberForm, MemberForm 
 24  from django.contrib.auth.models import User 
 25  from django.contrib.contenttypes.models import ContentType 
 26       
 27  logger = logging.getLogger("project.views") 
 28   
 29  TEMPLATE_PATH = "project" 
 30   
 31  DEFAULT_OWNER_PERMISSIONS = [ 
 32      "can_edit_project", "can_delete_project", "can_view_project", 
 33      "can_add_members", "can_remove_members", 
 34      "can_create_slices", "can_edit_slices", "can_delete_slices", 
 35      "can_start_slices", "can_stop_slices", 
 36      "can_add_aggregates", "can_remove_aggregates", 
 37      "can_create_roles", "can_edit_roles", 
 38  ] 
 39   
 40  DEFAULT_RESEARCHER_PERMISSIONS = [ 
 41      "can_view_project", 
 42      "can_create_slices", "can_edit_slices", "can_delete_slices", 
 43      "can_start_slices", "can_stop_slices", 
 44  ] 
45 46 -def list(request):
47 '''Show list of projects''' 48 49 qs = Project.objects.get_for_user(request.user) 50 51 return list_detail.object_list( 52 request, 53 queryset=qs, 54 template_name=TEMPLATE_PATH+"/list.html", 55 template_object_name="project", 56 )
57 58 @require_objs_permissions_for_view( 59 perm_names=["can_delete_slices"], 60 permittee_func=get_user_from_req, 61 target_func=get_queryset(Project, "proj_id"), 62 methods=["GET", "POST"], 63 ) 64 @require_objs_permissions_for_view( 65 perm_names=["can_delete_project"], 66 permittee_func=get_user_from_req, 67 target_func=get_queryset(Project, "proj_id"), 68 methods=["GET", "POST"], 69 )
70 -def delete(request, proj_id):
71 '''Delete the project''' 72 project = get_object_or_404(Project, id=proj_id) 73 if request.method == "POST": 74 for s in project.slice_set.all(): 75 s.stop(request.user) 76 project.delete() 77 DatedMessage.objects.post_message_to_user( 78 "Successfully deleted project %s" % project.name, 79 request.user, msg_type=DatedMessage.TYPE_SUCCESS) 80 return HttpResponseRedirect(reverse("home")) 81 else: 82 return simple.direct_to_template( 83 request, 84 template=TEMPLATE_PATH+"/confirm_delete.html", 85 extra_context={"object": project}, 86 )
87 88 @require_objs_permissions_for_view( 89 perm_names=["can_view_project"], 90 permittee_func=get_user_from_req, 91 target_func=get_queryset(Project, "proj_id"), 92 )
93 -def detail(request, proj_id):
94 '''Show information about the project''' 95 project = get_object_or_404(Project, id=proj_id) 96 role_reqs = ProjectRoleRequest.objects.filter( 97 giver=request.user, requested_role__project=project) 98 return list_detail.object_detail( 99 request, 100 Project.objects.all(), 101 object_id=proj_id, 102 template_name=TEMPLATE_PATH+"/detail.html", 103 template_object_name="project", 104 extra_context={ 105 "role_requests": role_reqs, 106 "breadcrumbs": ( 107 ("Home", reverse("home")), 108 ("Project %s" % project.name, reverse("project_detail", args=[project.id])), 109 ) 110 } 111 )
112
113 -def create_project_roles(project, user):
114 """Create the default roles in a project.""" 115 owner_role = ProjectRole.objects.create( 116 name="owner", 117 description=\ 118 "The 'owner' role is a special role that has permission to " 119 "do everything " 120 "in the project and can give the permissions to everyone. " 121 "In addition every time a slice is created, users with " 122 "the 'owner' role get full permissions over those.", 123 project=project, 124 ) 125 for permission in DEFAULT_OWNER_PERMISSIONS: 126 obj_perm = ObjectPermission.objects.\ 127 get_or_create_for_object_or_class( 128 permission, project)[0] 129 owner_role.obj_permissions.add(obj_perm) 130 131 researcher_role = ProjectRole.objects.create( 132 name="researcher", 133 description=\ 134 "By default users with the 'researcher' role can only " 135 "create slices and " 136 "delete slices they created. They have full permissions over " 137 "their created slices.", 138 project=project, 139 ) 140 for permission in DEFAULT_RESEARCHER_PERMISSIONS: 141 obj_perm = ObjectPermission.objects.\ 142 get_or_create_for_object_or_class( 143 permission, project)[0] 144 researcher_role.obj_permissions.add(obj_perm) 145 146 # give the creator of the project an owner role 147 owner_role.give_to_permittee( 148 user, 149 can_delegate=True, 150 )
151 152 @require_objs_permissions_for_view( 153 perm_names=["can_create_project"], 154 permittee_func=get_user_from_req, 155 target_func=get_queryset_from_class(Project), 156 )
157 -def create(request):
158 '''Create a new project''' 159 160 def post_save(instance, created): 161 # Create default roles in the project 162 create_project_roles(instance, request.user)
163 164 def redirect(instance): 165 return reverse("project_detail", args=[instance.id]) 166 167 return generic_crud( 168 request, None, 169 model=Project, 170 form_class=ProjectCreateForm, 171 template=TEMPLATE_PATH+"/create_update.html", 172 post_save=post_save, 173 redirect=redirect, 174 template_object_name="project", 175 extra_context={ 176 "breadcrumbs": ( 177 ("Home", reverse("home")), 178 ("Create Project", request.path), 179 ), 180 }, 181 success_msg = lambda instance: "Successfully created project %s." % instance.name, 182 ) 183 184 @require_objs_permissions_for_view( 185 perm_names=["can_view_project"], 186 permittee_func=get_user_from_req, 187 target_func=get_queryset(Project, "proj_id"), 188 ) 189 @require_objs_permissions_for_view( 190 perm_names=["can_edit_project"], 191 permittee_func=get_user_from_req, 192 target_func=get_queryset(Project, "proj_id"), 193 methods=["POST"], 194 )
195 -def update(request, proj_id, iframe=False):
196 '''Update information about a project''' 197 198 project = get_object_or_404(Project, id=proj_id) 199 200 def redirect(instance): 201 if iframe: 202 return reverse("project_list") 203 else: 204 return reverse("project_detail", args=[instance.id])
205 206 return generic_crud( 207 request, proj_id, 208 model=Project, 209 form_class=ProjectCreateForm, 210 template=TEMPLATE_PATH+"/create_update.html", 211 redirect=redirect, 212 template_object_name="project", 213 extra_context={ 214 "breadcrumbs": ( 215 ("Home", reverse("home")), 216 ("Project %s" % project.name, reverse("project_detail", args=[project.id])), 217 ("Update Info", request.path), 218 ), 219 }, 220 success_msg = lambda instance: "Successfully updated project %s." % instance.name, 221 ) 222 223 @require_objs_permissions_for_view( 224 perm_names=["can_add_aggregates"], 225 permittee_func=get_user_from_req, 226 target_func=get_queryset(Project, "proj_id"), 227 )
228 -def add_aggregate(request, proj_id):
229 '''Add/remove aggregates to/from a project''' 230 231 project = get_object_or_404(Project, id=proj_id) 232 aggregate_list = Aggregate.objects.exclude( 233 id__in=project.aggregates.all().values_list("id", flat=True)) 234 235 if request.method == "GET": 236 return simple.direct_to_template( 237 request, template=TEMPLATE_PATH+"/add_aggregates.html", 238 extra_context={ 239 "aggregate_list": aggregate_list, 240 "project": project, 241 "breadcrumbs": ( 242 ("Home", reverse("home")), 243 ("Project %s" % project.name, reverse("project_detail", args=[project.id])), 244 ("Add Project Aggregates", request.path), 245 ), 246 } 247 ) 248 249 elif request.method == "POST": 250 # check which submit button was pressed 251 try: 252 agg_id = int(request.POST.get("id", 0)) 253 except ValueError: 254 raise Http404 255 256 if agg_id not in aggregate_list.values_list("id", flat=True): 257 raise Http404 258 259 aggregate = get_object_or_404(Aggregate, id=agg_id).as_leaf_class() 260 return HttpResponseRedirect(aggregate.add_to_project( 261 project, reverse("project_add_agg", args=[proj_id]))) 262 else: 263 return HttpResponseNotAllowed("GET", "POST")
264 265 @require_objs_permissions_for_view( 266 perm_names=["can_add_aggregates"], 267 permittee_func=get_user_from_req, 268 target_func=get_queryset(Project, "proj_id"), 269 )
270 -def update_aggregate(request, proj_id, agg_id):
271 '''Update any info stored at the aggregate''' 272 project = get_object_or_404(Project, id=proj_id) 273 aggregate = get_object_or_404( 274 Aggregate, id=agg_id, id__in=project.aggregates.values_list( 275 "id", flat=True)).as_leaf_class() 276 277 if request.method == "POST": 278 return HttpResponseRedirect(aggregate.add_to_project( 279 project, reverse("project_detail", args=[proj_id]))) 280 else: 281 return HttpResponseNotAllowed(["POST"])
282 283 @require_objs_permissions_for_view( 284 perm_names=["can_remove_aggregates"], 285 permittee_func=get_user_from_req, 286 target_func=get_queryset(Project, "proj_id"), 287 )
288 -def remove_aggregate(request, proj_id, agg_id):
289 """Remove the aggregate from the project""" 290 project = get_object_or_404(Project, id=proj_id) 291 aggregate = get_object_or_404( 292 Aggregate, id=agg_id, id__in=project.aggregates.values_list( 293 "id", flat=True)).as_leaf_class() 294 295 if request.method == "POST": 296 return HttpResponseRedirect(aggregate.remove_from_project( 297 project, reverse("project_detail", args=[proj_id]))) 298 else: 299 return HttpResponseNotAllowed(["POST"])
300 301 @require_objs_permissions_for_view( 302 perm_names=["can_add_members"], 303 permittee_func=get_user_from_req, 304 target_func=get_queryset(Project, "proj_id"), 305 )
306 -def add_member(request, proj_id):
307 """Add a member to the project""" 308 309 project = get_object_or_404(Project, id=proj_id) 310 311 if request.method == "POST": 312 form = AddMemberForm(project=project, giver=request.user, data=request.POST) 313 if form.is_valid(): 314 form.save() 315 return HttpResponseRedirect(reverse("project_detail", args=[proj_id])) 316 317 else: 318 form = AddMemberForm(project=project, giver=request.user) 319 320 return simple.direct_to_template( 321 request, 322 template=TEMPLATE_PATH+"/add_member.html", 323 extra_context={ 324 "form": form, 325 "project": project, 326 "breadcrumbs": ( 327 ("Home", reverse("home")), 328 ("Project %s" % project.name, reverse("project_detail", args=[project.id])), 329 ("Add Member", request.path), 330 ), 331 }, 332 )
333 334 @require_objs_permissions_for_view( 335 perm_names=["can_add_members"], 336 permittee_func=get_user_from_req, 337 target_func=get_queryset(Project, "proj_id"), 338 )
339 -def update_member(request, proj_id, user_id):
340 """Update a member's roles""" 341 342 project = get_object_or_404(Project, id=proj_id) 343 member = get_object_or_404(User, id=user_id) 344 345 if request.method == "POST": 346 form = MemberForm( 347 project=project, user=member, 348 giver=request.user, data=request.POST) 349 350 if form.is_valid(): 351 form.save() 352 return HttpResponseRedirect( 353 reverse("project_detail", args=[proj_id])) 354 355 else: 356 form = MemberForm( 357 project=project, user=member, 358 giver=request.user) 359 360 return simple.direct_to_template( 361 request, 362 template=TEMPLATE_PATH+"/update_member.html", 363 extra_context={ 364 "form": form, 365 "project": project, 366 "member": member, 367 "breadcrumbs": ( 368 ("Home", reverse("home")), 369 ("Project %s" % project.name, reverse("project_detail", args=[project.id])), 370 ("Update Member %s" % member.username, request.path), 371 ), 372 }, 373 )
374 375 @require_objs_permissions_for_view( 376 perm_names=["can_remove_members"], 377 permittee_func=get_user_from_req, 378 target_func=get_queryset(Project, "proj_id"), 379 )
380 -def remove_member(request, proj_id, user_id):
381 """Kick a member out by stripping his roles""" 382 383 project = get_object_or_404(Project, id=proj_id) 384 member = get_object_or_404(User, id=user_id) 385 386 if request.method == "POST": 387 member = Permittee.objects.get_as_permittee(member) 388 # Remove the roles 389 for role in ProjectRole.objects.filter(project=project): 390 role.remove_from_permittee(member) 391 # Remove other permissions 392 PermissionOwnership.objects.delete_all_for_target(project, member) 393 return HttpResponseRedirect( 394 reverse("project_detail", args=[proj_id])) 395 396 return simple.direct_to_template( 397 request, 398 template=TEMPLATE_PATH+"/remove_member.html", 399 extra_context={ 400 "project": project, 401 "member": member, 402 "breadcrumbs": ( 403 ("Home", reverse("home")), 404 ("Project %s" % project.name, reverse("project_detail", args=[project.id])), 405 ("Remove Member %s" % member.username, request.path), 406 ), 407 }, 408 )
409