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):
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 )
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 )
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
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
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 )
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 )
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
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 )
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 )
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 )
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 )
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 )
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
389 for role in ProjectRole.objects.filter(project=project):
390 role.remove_from_permittee(member)
391
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