1 | import json |
||
2 | import logging |
||
3 | |||
4 | from django.contrib import auth, messages |
||
5 | from django.contrib.auth.decorators import login_required |
||
6 | from django.contrib.auth.models import User |
||
7 | from django.db.models import Q |
||
8 | from django.template import RequestContext |
||
9 | from django.http import HttpResponseBadRequest |
||
10 | from django.shortcuts import get_object_or_404, redirect, render |
||
11 | from django.views.decorators.http import require_http_methods |
||
12 | from django.http import Http404 |
||
13 | |||
14 | from ore.models import Graph, Project, notations, Sharing |
||
15 | |||
16 | |||
17 | logger = logging.getLogger('ore') |
||
18 | |||
19 | GREETINGS = [ |
||
20 | 'Loading the ORE cookie generator...', |
||
21 | 'Trying to find your Data... it was here somewhere', |
||
22 | 'Fiddeling with your Graph... Stand by!', |
||
23 | 'Loading good Karma into your Browser...', |
||
24 | 'Calculating the Answer to Life...', |
||
25 | 'Man, this takes like forever to load...', |
||
26 | 'This may take a moment, time to grab some coffee...' |
||
27 | ] |
||
28 | |||
29 | |||
30 | def index(request): |
||
31 | """ |
||
32 | Function: index |
||
33 | |||
34 | This is the view handler for loading the landing page of the editor. The index.html is rendered unless the user is |
||
35 | already signed in and being redirected to his or her dashboard. |
||
36 | |||
37 | Parameters: |
||
38 | {HttpRequest} request - a django request object |
||
39 | |||
40 | Returns: |
||
41 | {HttpResponse} a django response object |
||
42 | """ |
||
43 | if 'logout' in request.GET: |
||
44 | auth.logout(request) |
||
45 | |||
46 | if request.user.is_authenticated(): |
||
47 | if 'next' in request.GET and len(request.GET['next']) > 0: |
||
48 | return redirect(request.GET['next']) |
||
49 | else: |
||
50 | return redirect('projects') |
||
51 | |||
52 | if 'next' in request.GET: |
||
53 | # Makes this a hidden form parameter for the OpenID auth form |
||
54 | # submission |
||
55 | return render(request, 'index.html', {'next': request.GET['next'], 'pwlogin': ('pwlogin' in request.GET)}, |
||
56 | context_instance=RequestContext(request)) |
||
57 | else: |
||
58 | return render(request, 'index.html', {'pwlogin': ('pwlogin' in request.GET)}, |
||
59 | context_instance=RequestContext(request)) |
||
60 | |||
61 | |||
62 | def about(request): |
||
63 | """ |
||
64 | Function: about |
||
65 | |||
66 | Simple rendering of the about page. |
||
67 | |||
68 | Parameters: |
||
69 | {HttpRequest} request - a django request |
||
70 | |||
71 | Returns: |
||
72 | {HttpResponse} a django response object |
||
73 | """ |
||
74 | return render(request, 'util/about.html') |
||
75 | |||
76 | |||
77 | def privacy(request): |
||
78 | return render(request, 'util/privacy.html') |
||
79 | |||
80 | |||
81 | @login_required |
||
82 | def projects(request): |
||
83 | """ |
||
84 | Function: projects |
||
85 | |||
86 | This view handler renders a project overview containing all projects which are not marked as deleted, as well as in |
||
87 | which the actual user is the owner or a project member. The resulting list of projects is ordered descending by its |
||
88 | creation date. Also, a user is able to create a new project, as well as to delete a certain project if he is the owner. |
||
89 | |||
90 | Parameters: |
||
91 | {HttpRequest} request - a django request object |
||
92 | |||
93 | Returns: |
||
94 | {HttpResponse} a django response object |
||
95 | """ |
||
96 | user = request.user |
||
97 | |||
98 | projects = ( |
||
99 | user.projects.filter( |
||
100 | deleted=False) | user.own_projects.filter( |
||
101 | deleted=False)).order_by('-created') |
||
102 | |||
103 | parameters = {'projects': [project.to_dict() for project in projects], |
||
104 | 'user': user |
||
105 | } |
||
106 | |||
107 | # provide notification box on the projects overview page, if something is |
||
108 | # available for this user |
||
109 | try: |
||
110 | notification = request.user.notification_set.latest('modified') |
||
111 | parameters['notification'] = notification |
||
112 | except Exception: |
||
113 | pass |
||
114 | |||
115 | return render(request, 'project_menu/projects.html', parameters) |
||
116 | |||
117 | |||
118 | @login_required |
||
119 | def project_new(request): |
||
120 | """ |
||
121 | Function: project_new |
||
122 | |||
123 | This handler is responsible for rendering a dialog to the user to create a new project. It is also responsible for |
||
124 | processing a save request of such a 'new project' request and forwards the user to the project overview site after doing so. |
||
125 | |||
126 | Parameters: |
||
127 | {HttpRequest} request - a django request object |
||
128 | |||
129 | Returns: |
||
130 | {HttpResponse} a django response object |
||
131 | """ |
||
132 | |||
133 | if request.method == 'POST': |
||
134 | project = Project( |
||
135 | name=request.POST.get('name'), |
||
136 | owner=request.user, |
||
137 | deleted=False) |
||
138 | project.save() |
||
139 | return redirect('projects') |
||
140 | |||
141 | return render(request, 'project_menu/project_new.html') |
||
142 | |||
143 | |||
144 | @login_required |
||
145 | def project_edit(request, project_id): |
||
146 | """ |
||
147 | Function: project_edit |
||
148 | |||
149 | This handler function is responsible for allowing the user to edit the properties of an already existing project. |
||
150 | Therefore the system renders a edit dialog to the user where changes can be made and saved or the project can be |
||
151 | deleted. |
||
152 | |||
153 | Parameters: |
||
154 | {HttpResponse} request - a django request object |
||
155 | {int} project_id - the project to be edited |
||
156 | |||
157 | Returns: |
||
158 | {HttpResponse} a django response object |
||
159 | """ |
||
160 | project = get_object_or_404(Project, pk=project_id, owner=request.user) |
||
161 | POST = request.POST |
||
162 | |||
163 | # deletion requested? do it and go back to project overview |
||
164 | if POST.get('delete'): |
||
165 | project.deleted = True |
||
166 | project.save() |
||
167 | messages.add_message(request, messages.SUCCESS, 'Project deleted.') |
||
168 | return redirect('projects') |
||
169 | |||
170 | # the owner made changes to the project's field, better save it (if we can) |
||
171 | elif POST.get('save'): |
||
172 | project.name = POST.get('name', '') |
||
173 | project.save() |
||
174 | messages.add_message(request, messages.SUCCESS, 'Project saved.') |
||
175 | return redirect('projects') |
||
176 | |||
177 | # please show the edit page to the user on get requests |
||
178 | elif POST.get('edit') or request.method == 'GET': |
||
179 | parameters = {'project': project.to_dict()} |
||
180 | return render(request, 'project_menu/project_edit.html', parameters) |
||
181 | |||
182 | # something was not quite right here |
||
183 | raise HttpResponseBadRequest() |
||
184 | |||
185 | |||
186 | def shared_graphs_dashboard(request): |
||
187 | """ |
||
188 | Function: shared_graphs |
||
189 | |||
190 | This handler function is responsible for rendering a list of graphs that have been shared with the current user. |
||
191 | Shared in this context means the user isn't the owner but is allowed to view a certain graph in read-only mode. |
||
192 | The graphs are listed within a specific dashboard that offers the option to remove sharing of certain gaphs. |
||
193 | |||
194 | Parameters: |
||
195 | {HttpResponse} request - a django request object |
||
196 | |||
197 | Returns: |
||
198 | {HttpResponse} a django response object |
||
199 | """ |
||
200 | user = request.user |
||
201 | |||
202 | if request.method == 'GET': |
||
203 | |||
204 | sharings = user.sharings.all() |
||
205 | |||
206 | if not sharings: |
||
207 | return redirect('projects') |
||
208 | |||
209 | shared_graphs = [sharing.graph for sharing in sharings] |
||
210 | |||
211 | # projects in which the actual user is owner or member and that were |
||
212 | # recently modified are proposed to the user |
||
213 | proposal_limit = 3 |
||
214 | project_proposals = Project.objects.filter(Q(deleted=False), Q( |
||
215 | users=request.user) | Q(owner=request.user)).order_by('-modified')[:proposal_limit] |
||
216 | |||
217 | parameters = {'graphs': [(notations.by_kind[graph.kind]['name'], graph) for graph in shared_graphs], |
||
218 | 'proposals': [project.to_dict() for project in project_proposals] |
||
219 | } |
||
220 | |||
221 | return render( |
||
222 | request, 'dashboard/shared_graphs_dashboard.html', parameters) |
||
223 | |||
224 | elif request.method == 'POST': |
||
225 | POST = request.POST |
||
226 | |||
227 | if POST.get('unshare'): |
||
228 | |||
229 | selected_graphs = POST.getlist('graph_id[]') |
||
230 | |||
231 | sharings = [ |
||
232 | get_object_or_404( |
||
233 | Sharing, |
||
234 | user=user, |
||
235 | graph_id=graph_id) for graph_id in selected_graphs] |
||
236 | |||
237 | for sharing in sharings: |
||
238 | sharing.delete() |
||
239 | |||
240 | return redirect('shared_graphs_dashboard') |
||
241 | |||
242 | # something is not right with the request |
||
243 | return HttpResponseBadRequest() |
||
244 | |||
245 | |||
246 | @login_required |
||
247 | def dashboard(request, project_id): |
||
248 | """ |
||
249 | Function: dashboard |
||
250 | |||
251 | This view handler renders the dashboard in the context of a certain project. It lists all the graphs belonging to the project that are not marked as |
||
252 | deleted ordered descending by its creation date. Also, a user is able to add new graphs to the project, as well as to edit or delete |
||
253 | existing graphs from here. |
||
254 | |||
255 | Parameters: |
||
256 | {HttpRequest} request - a django request object |
||
257 | |||
258 | Returns: |
||
259 | {HttpResponse} a django response object |
||
260 | """ |
||
261 | project = get_object_or_404(Project, pk=project_id) |
||
262 | |||
263 | if not (project.is_authorized(request.user)): |
||
264 | raise Http404 |
||
265 | |||
266 | # projects in which the actual user is owner or member and that were |
||
267 | # recently modified are proposed to the user |
||
268 | proposal_limit = 3 |
||
269 | project_proposals = Project.objects.filter(Q(deleted=False), Q(users=request.user) | Q( |
||
270 | owner=request.user)).exclude(id=project.id).order_by('-modified')[:proposal_limit] |
||
271 | |||
272 | graphs = project.graphs.filter(deleted=False).order_by('-created') |
||
273 | parameters = {'graphs': [(notations.by_kind[graph.kind]['name'], graph) for graph in graphs], |
||
274 | 'project': project.to_dict(), |
||
275 | 'proposals': [pr.to_dict() for pr in project_proposals], |
||
276 | 'user': request.user |
||
277 | } |
||
278 | |||
279 | return render(request, 'dashboard/dashboard.html', parameters) |
||
280 | |||
281 | |||
282 | @login_required |
||
283 | def dashboard_import(request, project_id): |
||
284 | """ |
||
285 | Handles POST request for GraphML file import in the dashboard, |
||
286 | """ |
||
287 | project = get_object_or_404(Project, pk=project_id) |
||
288 | |||
289 | parameters = { |
||
290 | 'project': project.to_dict() |
||
291 | } |
||
292 | |||
293 | # user can only create a graph if he is owner or member of the respective |
||
294 | # project |
||
295 | if not (project.is_authorized(request.user)): |
||
296 | raise Http404 |
||
297 | |||
298 | # import the graph |
||
299 | if request.POST.get('save'): |
||
300 | for name, f in request.FILES.iteritems(): |
||
301 | graph = Graph(owner=request.user, project=project) |
||
302 | try: |
||
303 | graph.from_graphml(f.read()) |
||
304 | graph.name = request.POST.get("title", "Imported graph") |
||
305 | graph.save() |
||
306 | graph.ensure_default_nodes() |
||
307 | return redirect('dashboard', project_id=project_id) |
||
308 | except Exception as e: |
||
309 | parameters['error_text'] = str(e) |
||
310 | |||
311 | return render(request, 'dashboard/dashboard_import.html', parameters) |
||
312 | |||
313 | |||
314 | @login_required |
||
315 | def dashboard_new(request, project_id, kind): |
||
316 | """ |
||
317 | Function: dashboard_new |
||
318 | |||
319 | This handler is responsible for rendering a dialog to the user to create a new diagram. It is also responsible for |
||
320 | processing a save request of such a 'new diagram' request and forwards the user to the dashboard after doing so. |
||
321 | |||
322 | Parameters: |
||
323 | {HttpRequest} request - a django http request object |
||
324 | |||
325 | Returns: |
||
326 | {HttpResponse} a django response object |
||
327 | """ |
||
328 | project = get_object_or_404(Project, pk=project_id) |
||
329 | |||
330 | # user can only create a graph if he is owner or member of the respective |
||
331 | # project |
||
332 | if not (project.is_authorized(request.user)): |
||
333 | raise Http404 |
||
334 | |||
335 | POST = request.POST |
||
336 | |||
337 | # save the graph |
||
338 | if POST.get('save') and POST.get('name'): |
||
339 | graph = Graph( |
||
340 | kind=kind, |
||
341 | name=POST['name'], |
||
342 | owner=request.user, |
||
343 | project=project) |
||
344 | graph.save() |
||
345 | graph.ensure_default_nodes() |
||
346 | return redirect('dashboard', project_id=project_id) |
||
347 | |||
348 | # render the create diagram if fuzztree |
||
349 | elif kind in notations.by_kind: |
||
350 | parameters = { |
||
351 | 'kind': kind, |
||
352 | 'name': notations.by_kind[kind]['name'], |
||
353 | 'project': project.to_dict() |
||
354 | } |
||
355 | return render(request, 'dashboard/dashboard_new.html', parameters) |
||
356 | |||
357 | elif kind == "from_graphml": |
||
358 | # Redirect to file upload dialogue |
||
359 | return render(request, 'dashboard/dashboard_import.html', |
||
360 | {'project': project.to_dict()}) |
||
361 | |||
362 | # something is not right with the request |
||
363 | return HttpResponseBadRequest() |
||
364 | |||
365 | |||
366 | @login_required |
||
367 | def dashboard_edit(request, project_id): |
||
368 | """ |
||
369 | Function: dashboard_edit |
||
370 | |||
371 | This handler function is responsible for allowing the user to perform certain actions (copying, deleting, creating snapshots, sharing) on multiple graphs simultaneously. |
||
372 | For this purpose a button toolbar is rendered in the view with which the user can submit a list of graphs in order to perform a specific action. |
||
373 | |||
374 | Parameters: |
||
375 | {HttpResponse} request - a django request object |
||
376 | {int} project_id - id of the dashboard specific project |
||
377 | |||
378 | Returns: |
||
379 | {HttpResponse} a django response object |
||
380 | """ |
||
381 | project = get_object_or_404(Project, pk=project_id) |
||
382 | |||
383 | POST = request.POST |
||
384 | |||
385 | # Save determination of chosen graphs |
||
386 | if "graph_id[]" in POST: |
||
387 | # Coming directly from a form with <select> entries |
||
388 | selected_graphs = POST.getlist('graph_id[]') |
||
389 | elif "graph_id_list" in POST: |
||
390 | # Coming from a stringified list stored by ourselves |
||
391 | selected_graphs = json.loads(POST.get('graph_id_list')) |
||
392 | graphs = [ |
||
393 | get_object_or_404( |
||
394 | Graph, |
||
395 | pk=graph_id, |
||
396 | owner=request.user, |
||
397 | deleted=False) for graph_id in selected_graphs] |
||
0 ignored issues
–
show
introduced
by
![]() |
|||
398 | |||
399 | if POST.get('share'): |
||
400 | # "Share" button pressed for one or multiple graphs |
||
401 | users = User.objects.exclude(pk=request.user.pk) |
||
402 | parameters = { |
||
403 | 'project': project, |
||
404 | 'users': users, |
||
405 | 'graph_id_list': json.dumps([graph.pk for graph in graphs]) |
||
406 | } |
||
407 | return render(request, 'dashboard/dashboard_share.html', parameters) |
||
408 | |||
409 | elif POST.get("share_save"): |
||
410 | # Save choice of users for the graphs |
||
411 | user_ids = POST.getlist('users') |
||
412 | users = [get_object_or_404(User, pk=user_id) for user_id in user_ids] |
||
413 | |||
414 | for graph in graphs: |
||
415 | for user in users: |
||
416 | # check if graph is already shared with the specific user |
||
417 | if not Sharing.objects.filter(user=user, graph=graph).exists(): |
||
418 | sharing = Sharing(graph=graph, user=user) |
||
419 | sharing.save() |
||
420 | users_str = ','.join([u.visible_name() for u in users]) |
||
421 | messages.add_message( |
||
422 | request, messages.SUCCESS, "'%s' shared with %s." % |
||
423 | (graph, users_str)) |
||
424 | return redirect('dashboard', project_id=project.id) |
||
425 | |||
426 | elif POST.get('copy'): |
||
427 | # "Copy" button pressed for one or multiple graphs |
||
428 | for old_graph in graphs: |
||
429 | graph = Graph( |
||
430 | kind=old_graph.kind, |
||
431 | name=old_graph.name + |
||
432 | ' (copy)', |
||
433 | owner=request.user, |
||
434 | project=project) |
||
435 | graph.save() |
||
436 | graph.copy_values(old_graph) |
||
437 | graph.save() |
||
438 | messages.add_message( |
||
439 | request, |
||
440 | messages.SUCCESS, |
||
441 | 'Duplication successful.') |
||
442 | return redirect('dashboard', project_id=project.id) |
||
443 | |||
444 | elif POST.get('snapshot'): |
||
445 | # "Snapshot" button pressed for one or multiple graphs |
||
446 | for old_graph in graphs: |
||
447 | graph = Graph( |
||
448 | kind=old_graph.kind, |
||
449 | name=old_graph.name + |
||
450 | ' (snapshot)', |
||
451 | owner=request.user, |
||
452 | project=project) |
||
453 | graph.save() |
||
454 | graph.copy_values(old_graph) |
||
455 | graph.read_only = True |
||
456 | graph.save() |
||
457 | messages.add_message( |
||
458 | request, |
||
459 | messages.SUCCESS, |
||
460 | 'Snapshot creation sucessful.') |
||
461 | return redirect('dashboard', project_id=project.id) |
||
462 | |||
463 | elif POST.get('delete'): |
||
464 | # "Delete" button pressed for one or multiple graphs |
||
465 | for graph in graphs: |
||
466 | # all graph sharings will be deleted irretrievably |
||
467 | graph.sharings.all().delete() |
||
468 | graph.deleted = True |
||
469 | graph.save() |
||
470 | |||
471 | messages.add_message(request, messages.SUCCESS, 'Deletion sucessful.') |
||
472 | return redirect('dashboard', project_id=project.id) |
||
473 | |||
474 | return HttpResponseBadRequest() |
||
475 | |||
476 | |||
477 | def graph_settings(request, graph_id): |
||
478 | """ |
||
479 | Function: graph_settings |
||
480 | |||
481 | This handler function is responsible for allowing the user to edit the properties of an already existing graph. |
||
482 | Therefore the system renders a settings dialog to the user where changes can be made and saved for the graph. |
||
483 | |||
484 | Parameters: |
||
485 | {HttpResponse} request - a django request object |
||
486 | {int} graph_id - the graph to be edited |
||
487 | |||
488 | Returns: |
||
489 | {HttpResponse} a django response object |
||
490 | """ |
||
491 | graph = get_object_or_404(Graph, pk=graph_id, owner=request.user) |
||
492 | project = get_object_or_404( |
||
493 | Project, |
||
494 | pk=graph.project.pk, |
||
495 | owner=request.user) |
||
496 | |||
497 | POST = request.POST |
||
498 | |||
499 | # the owner made changes to the graph's fields, better save it (if we can) |
||
500 | if POST.get('save'): |
||
501 | # changes in the graphs name |
||
502 | graph.name = POST.get('name', '') |
||
503 | graph.save() |
||
504 | |||
505 | # added/removed viewers from the graph |
||
506 | user_ids = POST.getlist('users') |
||
507 | |||
508 | new_users = set([get_object_or_404(User, pk=user_id) |
||
509 | for user_id in user_ids]) |
||
510 | old_users = set([sharing.user for sharing in graph.sharings.all()]) |
||
511 | |||
512 | users_to_add = new_users - old_users |
||
513 | users_to_remove = old_users - new_users |
||
514 | |||
515 | for user in users_to_add: |
||
516 | sharing = Sharing(graph=graph, user=user) |
||
517 | sharing.save() |
||
518 | |||
519 | for user in users_to_remove: |
||
520 | sharing = Sharing.objects.get(graph=graph, user=user) |
||
521 | sharing.delete() |
||
522 | |||
523 | messages.add_message( |
||
524 | request, |
||
525 | messages.SUCCESS, |
||
526 | 'Saved new graph settings.') |
||
527 | return redirect('dashboard', project_id=project.pk) |
||
528 | |||
529 | # please show the edit page to the user on get requests |
||
530 | elif POST.get('edit') or request.method == 'GET': |
||
531 | |||
532 | users = User.objects.exclude(pk=request.user.pk) |
||
533 | shared_users = [sharing.user for sharing in graph.sharings.all()] |
||
534 | |||
535 | parameters = { |
||
536 | 'graph': graph, |
||
537 | 'kind': notations.by_kind[graph.kind]['name'], |
||
538 | 'users': users, |
||
539 | 'shared_users': shared_users |
||
540 | } |
||
541 | return render(request, 'dashboard/dashboard_edit.html', parameters) |
||
542 | |||
543 | # something was not quite right here |
||
544 | return HttpResponseBadRequest() |
||
545 | |||
546 | |||
547 | @login_required |
||
548 | def settings(request): |
||
549 | """ |
||
550 | Function: settings |
||
551 | |||
552 | The view for the settings page. The code remembers the last page (e.g. project overview or project details) and goes |
||
553 | backe to it afterwards. |
||
554 | |||
555 | Parameters: |
||
556 | {HttpRequest} request - a django request object |
||
557 | |||
558 | Returns: |
||
559 | {HttpResponse} a django response object |
||
560 | """ |
||
561 | try: |
||
562 | comes_from = request.META["HTTP_REFERER"] |
||
563 | if 'settings' not in comes_from: |
||
564 | request.session['comes_from'] = comes_from |
||
565 | except Exception: |
||
566 | # deal with missing REFERER |
||
567 | request.session['comes_from'] = '/projects/' |
||
568 | POST = request.POST |
||
569 | |||
570 | if POST.get('save'): |
||
571 | user = request.user |
||
572 | profile = user.profile |
||
573 | |||
574 | user.first_name = POST.get('first_name', user.first_name) |
||
575 | user.last_name = POST.get('last_name', user.last_name) |
||
576 | user.email = POST.get('email', user.email) |
||
577 | profile.newsletter = bool(POST.get('newsletter')) |
||
578 | |||
579 | profile.save() |
||
580 | user.save() |
||
581 | |||
582 | messages.add_message(request, messages.SUCCESS, 'Settings saved.') |
||
583 | return redirect(request.session['comes_from']) |
||
584 | elif POST.get('generate'): |
||
585 | from tastypie.models import ApiKey |
||
586 | user = request.user |
||
587 | # User may be new, without any previous API key |
||
588 | ApiKey.objects.get_or_create(user=user, defaults={'user': user}) |
||
589 | # Save new API key |
||
590 | user.api_key.key = user.api_key.generate_key() |
||
591 | user.api_key.save() |
||
592 | elif POST.get('cancel'): |
||
593 | return redirect(request.session['comes_from']) |
||
594 | |||
595 | return render(request, 'util/settings.html') |
||
596 | |||
597 | |||
598 | @login_required |
||
599 | def editor(request, graph_id): |
||
600 | """ |
||
601 | Function: editor |
||
602 | |||
603 | View handler for loading the editor. It just tries to locate the graph to be opened in the editor and passes it to |
||
604 | its according view. |
||
605 | |||
606 | Parameters: |
||
607 | {HttpRequest} request - a django request object |
||
608 | {int} graph_id - the id of the graph to be opened in the editor |
||
609 | |||
610 | Returns: |
||
611 | {HttpResponse} a django response object |
||
612 | """ |
||
613 | if request.user.is_staff: |
||
614 | graph = get_object_or_404(Graph, pk=graph_id) |
||
615 | else: |
||
616 | graph = get_object_or_404( |
||
617 | Graph, |
||
618 | pk=graph_id, |
||
619 | owner=request.user, |
||
620 | deleted=False) |
||
621 | if graph.read_only: |
||
622 | return HttpResponseBadRequest() |
||
623 | |||
624 | project = graph.project |
||
625 | notation = notations.by_kind[graph.kind] |
||
626 | nodes = notation['nodes'] |
||
627 | |||
628 | parameters = { |
||
629 | 'graph': graph, |
||
630 | 'graph_notation': notation, |
||
631 | 'nodes': [(node, nodes[node]) for node in notation['shapeMenuNodeDisplayOrder']], |
||
632 | 'greetings': GREETINGS, |
||
633 | 'project': project, |
||
634 | 'user': request.user |
||
635 | } |
||
636 | |||
637 | return render(request, 'editor/editor.html', parameters) |
||
638 | |||
639 | |||
640 | @login_required |
||
641 | def snapshot(request, graph_id): |
||
642 | """ |
||
643 | Function: snapshot |
||
644 | |||
645 | View handler for loading the snapshot viewer. It just tries to locate the graph to be opened |
||
646 | and passes it to its according view. For the moment, this is the editor itself, were the JavaScript |
||
647 | code handles the read-only mode from UI perspective. |
||
648 | |||
649 | Parameters: |
||
650 | {HttpRequest} request - a django request object |
||
651 | {int} graph_id - the id of the graph to be opened in the snapshot viewer |
||
652 | |||
653 | Returns: |
||
654 | {HttpResponse} a django response object |
||
655 | """ |
||
656 | |||
657 | graph = get_object_or_404(Graph, pk=graph_id) |
||
658 | |||
659 | # either current user is admin, owner of the graph, or graph is shared |
||
660 | # with the user |
||
661 | if not (request.user.is_staff or graph.owner == |
||
662 | request.user or graph.sharings.filter(user=request.user)): |
||
663 | raise Http404 |
||
664 | |||
665 | project = graph.project |
||
666 | notation = notations.by_kind[graph.kind] |
||
667 | nodes = notation['nodes'] |
||
668 | |||
669 | parameters = { |
||
670 | 'graph': graph, |
||
671 | 'graph_notation': notation, |
||
672 | 'nodes': [(node, nodes[node]) for node in notation['shapeMenuNodeDisplayOrder']], |
||
673 | 'greetings': GREETINGS, |
||
674 | 'project': project, |
||
675 | 'user': request.user |
||
676 | } |
||
677 | |||
678 | return render(request, 'editor/editor.html', parameters) |
||
679 | |||
680 | |||
681 | @require_http_methods(['GET', 'POST']) |
||
682 | def login(request): |
||
683 | """ |
||
684 | Function: login |
||
685 | |||
686 | View handler for loging in a user using OpenID. If the user is not yet know to the system a new profile is created |
||
687 | for him using his or her personal information as provided by the OpenID provider. |
||
688 | |||
689 | The login view always redirects to the index view - and not directly to the project view - in order to keep |
||
690 | the 'next' parameter handling in one place. Otherwise, the project view would need to consider the parameter too. |
||
691 | |||
692 | Parameters: |
||
693 | {HttpRequest} request - a django request object |
||
694 | |||
695 | Returns: |
||
696 | {HttpResponse} a django response object |
||
697 | """ |
||
698 | POST = request.POST |
||
699 | |||
700 | # Consider the 'next' redirection |
||
701 | if 'next' in POST: |
||
702 | # TODO: Security issue ? |
||
703 | redirect_params = '?next=' + POST['next'] |
||
704 | else: |
||
705 | redirect_params = '' |
||
706 | |||
707 | # Ordinary password login. Since this is normally disabled in favour of OpenID login, all such users |
||
708 | # got garbage passwords. This means that this code can remain in here as last ressort fallback for |
||
709 | # the admin users that have real passwords. |
||
710 | if 'username' in POST and 'password' in POST: |
||
711 | user = auth.authenticate( |
||
712 | username=POST['username'], |
||
713 | password=POST['password']) |
||
714 | # user found? sign-on |
||
715 | if user is not None and user.is_active: |
||
716 | auth.login(request, user) |
||
717 | return redirect('/projects/' + redirect_params) |
||
718 | |||
719 | return redirect('/' + redirect_params) |
||
720 |