From b8dfaf1f7179f23b5534e2ec3e78397ce4da96ce Mon Sep 17 00:00:00 2001
From: "J.-S. Caux" <J.S.Caux@uva.nl>
Date: Mon, 18 Apr 2016 16:17:43 +0200
Subject: [PATCH] Improve permissions overall, add login redirection

---
 commentaries/views.py                |  59 ++++----
 comments/views.py                    |   9 +-
 scipost/models.py                    |   7 +-
 scipost/templates/scipost/login.html |   3 +
 scipost/urls.py                      |   2 +-
 scipost/views.py                     | 199 ++++++++++++++-------------
 submissions/views.py                 |  36 ++---
 theses/views.py                      |  58 ++++----
 8 files changed, 193 insertions(+), 180 deletions(-)

diff --git a/commentaries/views.py b/commentaries/views.py
index 203ac73b4..147accf93 100644
--- a/commentaries/views.py
+++ b/commentaries/views.py
@@ -2,6 +2,7 @@ import datetime
 from django.utils import timezone
 from django.shortcuts import get_object_or_404, render
 from django.contrib.auth import authenticate, login, logout
+from django.contrib.auth.decorators import login_required, permission_required
 from django.contrib.auth.models import User
 from django.core.mail import EmailMessage
 from django.core.urlresolvers import reverse
@@ -24,38 +25,36 @@ from scipost.forms import AuthenticationForm
 ################
 
 
+@login_required
+@permission_required('scipost.can_request_commentary_pages', raise_exception=True)
 def request_commentary(request):
-    # commentary pages can only be requested by registered contributors:
-    if request.user.is_authenticated():
-        if request.method == 'POST':
-            form = RequestCommentaryForm(request.POST)
-            if form.is_valid():
-                contributor = Contributor.objects.get(user=request.user)
-                commentary = Commentary (
-                    requested_by = contributor,
-                    type = form.cleaned_data['type'],
-                    discipline = form.cleaned_data['discipline'],
-                    domain = form.cleaned_data['domain'],
-                    specialization = form.cleaned_data['specialization'],
-                    pub_title = form.cleaned_data['pub_title'],
-                    arxiv_link = form.cleaned_data['arxiv_link'],
-                    pub_DOI_link = form.cleaned_data['pub_DOI_link'],
-                    author_list = form.cleaned_data['author_list'],
-                    pub_date = form.cleaned_data['pub_date'],
-                    pub_abstract = form.cleaned_data['pub_abstract'],
-                    latest_activity = timezone.now(),
-                    )
-                commentary.parse_link_into_url()
-                commentary.save()
-                return HttpResponseRedirect('request_commentary_ack')
-        else:
-            form = RequestCommentaryForm()
-        return render(request, 'commentaries/request_commentary.html', {'form': form})
-    else: # user is not authenticated:
-        form = AuthenticationForm()
-        return render(request, 'scipost/login.html', {'form': form})
+    if request.method == 'POST':
+        form = RequestCommentaryForm(request.POST)
+        if form.is_valid():
+            contributor = Contributor.objects.get(user=request.user)
+            commentary = Commentary (
+                requested_by = contributor,
+                type = form.cleaned_data['type'],
+                discipline = form.cleaned_data['discipline'],
+                domain = form.cleaned_data['domain'],
+                specialization = form.cleaned_data['specialization'],
+                pub_title = form.cleaned_data['pub_title'],
+                arxiv_link = form.cleaned_data['arxiv_link'],
+                pub_DOI_link = form.cleaned_data['pub_DOI_link'],
+                author_list = form.cleaned_data['author_list'],
+                pub_date = form.cleaned_data['pub_date'],
+                pub_abstract = form.cleaned_data['pub_abstract'],
+                latest_activity = timezone.now(),
+                )
+            commentary.parse_link_into_url()
+            commentary.save()
+            return HttpResponseRedirect('request_commentary_ack')
+    else:
+        form = RequestCommentaryForm()
+    return render(request, 'commentaries/request_commentary.html', {'form': form})
 
 
+@permission_required('scipost.can_vet_commentary_requests', raise_exception=True)
 def vet_commentary_requests(request):
     contributor = Contributor.objects.get(user=request.user)
     commentary_to_vet = Commentary.objects.filter(vetted=False).first() # only handle one at a time
@@ -63,7 +62,7 @@ def vet_commentary_requests(request):
     context = {'contributor': contributor, 'commentary_to_vet': commentary_to_vet, 'form': form }
     return render(request, 'commentaries/vet_commentary_requests.html', context)
 
-
+@permission_required('scipost.can_vet_commentary_requests', raise_exception=True)
 def vet_commentary_request_ack(request, commentary_id):
     if request.method == 'POST':
         form = VetCommentaryForm(request.POST)
diff --git a/comments/views.py b/comments/views.py
index a82b8c1c9..d613f9a63 100644
--- a/comments/views.py
+++ b/comments/views.py
@@ -2,6 +2,7 @@ import datetime
 from django.utils import timezone
 from django.shortcuts import get_object_or_404, render
 from django.contrib.auth import authenticate, login, logout
+from django.contrib.auth.decorators import login_required, permission_required
 from django.contrib.auth.models import User
 from django.core.mail import EmailMessage
 from django.core.urlresolvers import reverse
@@ -15,6 +16,7 @@ from .forms import *
 from scipost.models import title_dict
 
 
+@permission_required('scipost.can_vet_comments')
 def vet_submitted_comments(request):
     contributor = Contributor.objects.get(user=request.user)
     comments_to_vet = Comment.objects.filter(status=0).order_by('date_submitted')
@@ -22,7 +24,7 @@ def vet_submitted_comments(request):
     context = {'contributor': contributor, 'comments_to_vet': comments_to_vet, 'form': form }
     return(render(request, 'comments/vet_submitted_comments.html', context))
 
-
+@permission_required('scipost.can_vet_comments')
 def vet_submitted_comment_ack(request, comment_id):
     if request.method == 'POST':
         form = VetCommentForm(request.POST)
@@ -87,6 +89,7 @@ def vet_submitted_comment_ack(request, comment_id):
     return render(request, 'comments/vet_submitted_comment_ack.html', context)
 
 
+@permission_required('scipost.can_submit_comments')
 def reply_to_comment(request, comment_id):
     comment = get_object_or_404(Comment, pk=comment_id)
     # Verify if this is from an author:
@@ -129,13 +132,13 @@ def reply_to_comment(request, comment_id):
     return render(request, 'comments/reply_to_comment.html', context)
 
 
+@permission_required('scipost.can_submit_comments')
 def reply_to_report(request, report_id):
     report = get_object_or_404(Report, pk=report_id)
     # Verify if this is from an author:
     is_author = False
     if report.submission.authors.filter(id=request.user.contributor.id).exists():
         is_author = True
-
     if is_author and request.method == 'POST':
         form = CommentForm(request.POST)
         if form.is_valid():
@@ -166,7 +169,7 @@ def reply_to_report(request, report_id):
     return render(request, 'comments/reply_to_report.html', context)
 
 
-
+@permission_required('scipost.can_express_opinion_on_comments')
 def express_opinion(request, comment_id, opinion):
     # A contributor has expressed an opinion on a comment
     contributor = request.user.contributor
diff --git a/scipost/models.py b/scipost/models.py
index d9a8e73c3..29b8e09ab 100644
--- a/scipost/models.py
+++ b/scipost/models.py
@@ -3,7 +3,6 @@ from django.db import models
 from django.contrib.auth.models import User, Group
 from django.contrib.postgres.fields import JSONField
 from django.template import Template, Context
-from django.template import defaultfilters
 
 from django_countries.fields import CountryField
 
@@ -302,7 +301,7 @@ class List(models.Model):
 
     def contents(self):
         context = Context({})
-        output = defaultfilters.linebreaks(self.description)
+        output = self.description
         output += '<hr class="hr6"/>'
         emptylist = True
         if self.submissions.exists():
@@ -396,7 +395,7 @@ class Graph(models.Model):
 
     def contents(self):
         context = Context({})
-        output = defaultfilters.linebreaks(self.description)
+        output = self.description
         template = Template(output)
         return template.render(context)
 
@@ -428,7 +427,7 @@ class Node(models.Model):
 
     def contents(self):
         context = Context({'graph_id': self.graph.id, 'id': self.id, 'name': self.name, 
-                           'description': defaultfilters.linebreaks(self.description)})
+                           'description': self.description})
         output = '<div class="node_contents node_id{{ id }}"><h3>{{ name }}</h3><p>{{ description }}</p></div>'
         template = Template(output)
         return template.render(context)
diff --git a/scipost/templates/scipost/login.html b/scipost/templates/scipost/login.html
index 77e88a7a6..9acebe198 100644
--- a/scipost/templates/scipost/login.html
+++ b/scipost/templates/scipost/login.html
@@ -16,6 +16,9 @@
 	  </ul>
 	</table>
 	<input type="submit" value="Login" />
+	{% if next %}
+	<input type="hidden" name="next" value="{{ next }}"/>
+	{% endif %}
       </form>
       <br/>
       <a href="{% url 'scipost:reset_password' %}">Forgot your password?</a>
diff --git a/scipost/urls.py b/scipost/urls.py
index 5a49b1364..768db3895 100644
--- a/scipost/urls.py
+++ b/scipost/urls.py
@@ -40,7 +40,7 @@ urlpatterns = [
     url(r'^accept_invitation_error$', TemplateView.as_view(template_name='scipost/accept_invitation_error.html'), name='accept_invitation_error'),
 
     ## Authentication
-    url(r'^login$', views.login_view, name='login'),
+    url(r'^login/$', views.login_view, name='login'),
     url(r'^logout$', views.logout_view, name='logout'),
     url(r'^personal_page$', views.personal_page, name='personal_page'),
     url(r'^change_password$', views.change_password, name='change_password'),
diff --git a/scipost/views.py b/scipost/views.py
index 8c13772c9..3d35d6d40 100644
--- a/scipost/views.py
+++ b/scipost/views.py
@@ -7,7 +7,7 @@ import string
 from django.utils import timezone
 from django.shortcuts import get_object_or_404, render
 from django.contrib.auth import authenticate, login, logout
-from django.contrib.auth.decorators import permission_required
+from django.contrib.auth.decorators import login_required, permission_required
 from django.contrib.auth.models import User, Group, Permission
 from django.contrib.auth.views import password_reset, password_reset_confirm
 from django.core.mail import EmailMessage
@@ -15,6 +15,7 @@ from django.core.urlresolvers import reverse
 from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
 from django.shortcuts import redirect
 from django.template import RequestContext
+from django.utils.http import is_safe_url
 from django.views.decorators.csrf import csrf_protect
 from django.db.models import Avg
 
@@ -275,7 +276,7 @@ def request_new_activation_link(request, oldkey):
     return render (request, 'scipost/request_new_activation_link_ack.html')
 
 
-@permission_required('scipost.can_vet_registration_requests', raise_exception=True)
+@permission_required('scipost.can_vet_registration_requests')
 def vet_registration_requests(request):
     contributor = Contributor.objects.get(user=request.user)
     contributors_to_vet = Contributor.objects.filter(user__is_active=True, status=0).order_by('key_expires')
@@ -284,7 +285,7 @@ def vet_registration_requests(request):
     context = {'contributors_to_vet': contributors_to_vet, 'form': form }
     return render(request, 'scipost/vet_registration_requests.html', context)
 
-@permission_required('scipost.can_vet_registration_requests', raise_exception=True)
+@permission_required('scipost.can_vet_registration_requests')
 def vet_registration_request_ack(request, contributor_id):
     # process the form
     if request.method == 'POST':
@@ -334,7 +335,7 @@ def vet_registration_request_ack(request, contributor_id):
     return render(request, 'scipost/vet_registration_request_ack.html', context)
 
 
-@permission_required('scipost.can_manage_registration_invitations', raise_exception=True)
+@permission_required('scipost.can_manage_registration_invitations')
 def registration_invitations(request):
     # List invitations sent; send new ones
     errormessage = ''
@@ -345,6 +346,8 @@ def registration_invitations(request):
         if reg_inv_form.is_valid():
             if Utils.email_already_invited():
                 errormessage = 'DUPLICATE ERROR: This email address has already been used for an invitation'
+            elif Utils.email_already_taken():
+                errormessage = 'DUPLICATE ERROR: This email address is already associated to a Contributor'
             else:
                 Utils.create_and_save_invitation()
                 Utils.send_registration_invitation_email()
@@ -369,6 +372,13 @@ def registration_invitations(request):
 
 
 def login_view(request):
+    redirect_to = request.POST.get('next', 
+                                   request.GET.get('next', reverse('scipost:personal_page')))
+    redirect_to = (redirect_to 
+                   if is_safe_url(redirect_to, request.get_host()) 
+                   else reverse('scipost:personal_page'))
+    if request.user.is_authenticated: # for users who navigate back to pre-logged in page
+        return redirect(redirect_to)
     if request.method == 'POST':
         username = request.POST['username']
         password = request.POST['password']
@@ -378,15 +388,14 @@ def login_view(request):
                 login(request, user)
                 contributor = Contributor.objects.get(user=request.user)
                 context = {'contributor': contributor }
-                #return render(request, 'scipost/personal_page.html', context)
-                return HttpResponseRedirect('personal_page')
+                return redirect(redirect_to)
             else:
                 return render(request, 'scipost/disabled_account.html')
         else:
             return render(request, 'scipost/login_error.html')
     else:
         form = AuthenticationForm()
-        return render(request, 'scipost/login.html', {'form': form})
+        return render(request, 'scipost/login.html', {'form': form, 'next': redirect_to})
 
 
 def logout_view(request):
@@ -492,8 +501,12 @@ def personal_page(request):
         return render(request, 'scipost/login.html', context)
 
 
+@login_required
 def change_password(request):
-    if request.user.is_authenticated and request.method == 'POST':
+#    if not request.user.is_authenticated:
+#        form = AuthenticationForm()
+#        return render(request, 'scipost/login.html', {'form': form})
+    if request.method == 'POST':
         form = PasswordChangeForm(request.POST)
         if form.is_valid():
             if not request.user.check_password(form.cleaned_data['password_prev']):
@@ -523,70 +536,65 @@ def reset_password(request):
         post_reset_redirect=reverse('scipost:login'))
 
 
+@login_required
 def update_personal_data(request):
-    if request.user.is_authenticated:
-        contributor = Contributor.objects.get(user=request.user)
-        if request.method == 'POST':
-            user_form = UpdateUserDataForm(request.POST)
-            cont_form = UpdatePersonalDataForm(request.POST)
-            if user_form.is_valid() and cont_form.is_valid():
-                request.user.email = user_form.cleaned_data['email']
-                request.user.first_name = user_form.cleaned_data['first_name']
-                request.user.last_name = user_form.cleaned_data['last_name']
-                request.user.contributor.title = cont_form.cleaned_data['title']
-                request.user.contributor.orcid_id = cont_form.cleaned_data['orcid_id']
-                request.user.contributor.country_of_employment = cont_form.cleaned_data['country_of_employment']
-                request.user.contributor.address = cont_form.cleaned_data['address']
-                request.user.contributor.affiliation = cont_form.cleaned_data['affiliation']
-                request.user.contributor.personalwebpage = cont_form.cleaned_data['personalwebpage']
-                request.user.save()
-                request.user.contributor.save()
-                return render(request, 'scipost/update_personal_data_ack.html')
-        else:
-            user_form = UpdateUserDataForm(instance=contributor.user)
-            cont_form = UpdatePersonalDataForm(instance=contributor)
-        return render(request, 'scipost/update_personal_data.html', {'user_form': user_form, 'cont_form': cont_form})
+    contributor = Contributor.objects.get(user=request.user)
+    if request.method == 'POST':
+        user_form = UpdateUserDataForm(request.POST)
+        cont_form = UpdatePersonalDataForm(request.POST)
+        if user_form.is_valid() and cont_form.is_valid():
+            request.user.email = user_form.cleaned_data['email']
+            request.user.first_name = user_form.cleaned_data['first_name']
+            request.user.last_name = user_form.cleaned_data['last_name']
+            request.user.contributor.title = cont_form.cleaned_data['title']
+            request.user.contributor.orcid_id = cont_form.cleaned_data['orcid_id']
+            request.user.contributor.country_of_employment = cont_form.cleaned_data['country_of_employment']
+            request.user.contributor.address = cont_form.cleaned_data['address']
+            request.user.contributor.affiliation = cont_form.cleaned_data['affiliation']
+            request.user.contributor.personalwebpage = cont_form.cleaned_data['personalwebpage']
+            request.user.save()
+            request.user.contributor.save()
+            return render(request, 'scipost/update_personal_data_ack.html')
     else:
-        form = AuthenticationForm()
-        return render(request, 'scipost/login.html', {'form': form})
+        user_form = UpdateUserDataForm(instance=contributor.user)
+        cont_form = UpdatePersonalDataForm(instance=contributor)
+    return render(request, 'scipost/update_personal_data.html', {'user_form': user_form, 'cont_form': cont_form})
 
 
+@login_required
 def claim_authorships(request):
-    if request.user.is_authenticated:
-       contributor = Contributor.objects.get(user=request.user)
-
-       submission_authorships_to_claim = (Submission.objects
-                                          .filter(author_list__contains=contributor.user.last_name)
-                                          .exclude(authors__in=[contributor])
-                                          .exclude(authors_claims__in=[contributor])
-                                          .exclude(authors_false_claims__in=[contributor]))
-       sub_auth_claim_form = AuthorshipClaimForm()
-       commentary_authorships_to_claim = (Commentary.objects
-                                          .filter(author_list__contains=contributor.user.last_name)
-                                          .exclude(authors__in=[contributor])
-                                          .exclude(authors_claims__in=[contributor])
-                                          .exclude(authors_false_claims__in=[contributor]))
-       com_auth_claim_form = AuthorshipClaimForm()
-       thesis_authorships_to_claim = (ThesisLink.objects
-                                      .filter(author__contains=contributor.user.last_name)
-                                      .exclude(author_as_cont__in=[contributor])
-                                      .exclude(author_claims__in=[contributor])
-                                      .exclude(author_false_claims__in=[contributor]))
-       thesis_auth_claim_form = AuthorshipClaimForm()
-
-       context = {'submission_authorships_to_claim': submission_authorships_to_claim,
-                  'sub_auth_claim_form': sub_auth_claim_form,
-                  'commentary_authorships_to_claim': commentary_authorships_to_claim,
-                  'com_auth_claim_form': com_auth_claim_form,
-                  'thesis_authorships_to_claim': thesis_authorships_to_claim,
-                  'thesis_auth_claim_form': thesis_auth_claim_form,
-                  }
-       return render(request, 'scipost/claim_authorships.html', context)
-    else:
-        form = AuthenticationForm()
-        return render(request, 'scipost/login.html', {'form': form})
+    contributor = Contributor.objects.get(user=request.user)
+    
+    submission_authorships_to_claim = (Submission.objects
+                                       .filter(author_list__contains=contributor.user.last_name)
+                                       .exclude(authors__in=[contributor])
+                                       .exclude(authors_claims__in=[contributor])
+                                       .exclude(authors_false_claims__in=[contributor]))
+    sub_auth_claim_form = AuthorshipClaimForm()
+    commentary_authorships_to_claim = (Commentary.objects
+                                       .filter(author_list__contains=contributor.user.last_name)
+                                       .exclude(authors__in=[contributor])
+                                       .exclude(authors_claims__in=[contributor])
+                                       .exclude(authors_false_claims__in=[contributor]))
+    com_auth_claim_form = AuthorshipClaimForm()
+    thesis_authorships_to_claim = (ThesisLink.objects
+                                   .filter(author__contains=contributor.user.last_name)
+                                   .exclude(author_as_cont__in=[contributor])
+                                   .exclude(author_claims__in=[contributor])
+                                   .exclude(author_false_claims__in=[contributor]))
+    thesis_auth_claim_form = AuthorshipClaimForm()
+    
+    context = {'submission_authorships_to_claim': submission_authorships_to_claim,
+               'sub_auth_claim_form': sub_auth_claim_form,
+               'commentary_authorships_to_claim': commentary_authorships_to_claim,
+               'com_auth_claim_form': com_auth_claim_form,
+               'thesis_authorships_to_claim': thesis_authorships_to_claim,
+               'thesis_auth_claim_form': thesis_auth_claim_form,
+               }
+    return render(request, 'scipost/claim_authorships.html', context)
 
 
+@login_required
 def claim_sub_authorship(request, submission_id, claim):
     if request.method == 'POST':
         contributor = Contributor.objects.get(user=request.user)
@@ -600,6 +608,7 @@ def claim_sub_authorship(request, submission_id, claim):
         submission.save()
     return redirect('scipost:claim_authorships')
 
+@login_required
 def claim_com_authorship(request, commentary_id, claim):
     if request.method == 'POST':
         contributor = Contributor.objects.get(user=request.user)
@@ -613,6 +622,7 @@ def claim_com_authorship(request, commentary_id, claim):
         commentary.save()
     return redirect('scipost:claim_authorships')
 
+@login_required
 def claim_thesis_authorship(request, thesis_id, claim):
     if request.method == 'POST':
         contributor = Contributor.objects.get(user=request.user)
@@ -627,11 +637,13 @@ def claim_thesis_authorship(request, thesis_id, claim):
     return redirect('scipost:claim_authorships')
 
 
+@permission_required('scipost.can_vet_authorship_claims')
 def vet_authorship_claims(request):
     claims_to_vet = AuthorshipClaim.objects.filter(status='0')
     context = {'claims_to_vet': claims_to_vet}
     return render(request, 'scipost/vet_authorship_claims.html', context)
 
+@permission_required('scipost.can_vet_authorship_claims')
 def vet_authorship_claim(request, claim_id, claim):
     if request.method == 'POST':
         vetting_contributor = Contributor.objects.get(user=request.user)
@@ -670,29 +682,25 @@ def vet_authorship_claim(request, claim_id, claim):
     return redirect('scipost:vet_authorship_claims')
 
 
+@login_required
 def contributor_info(request, contributor_id):
-    if request.user.is_authenticated():
-        contributor = Contributor.objects.get(pk=contributor_id)
-        contributor_submissions = Submission.objects.filter(authors__in=[contributor])
-        contributor_commentaries = Commentary.objects.filter(authors__in=[contributor])
-        contributor_theses = ThesisLink.objects.filter(author_as_cont__in=[contributor])
-        contributor_comments = (Comment.objects
-                                .filter(author=contributor, is_author_reply=False, status__gte=1)
-                                .order_by('-date_submitted'))
-        contributor_authorreplies = (Comment.objects
-                                     .filter(author=contributor, is_author_reply=True, status__gte=1)
-                                     .order_by('-date_submitted'))
-        context = {'contributor': contributor, 
-                   'contributor_submissions': contributor_submissions,
-                   'contributor_commentaries': contributor_commentaries,
-                   'contributor_theses': contributor_theses,
-                   'contributor_comments': contributor_comments, 
-                   'contributor_authorreplies': contributor_authorreplies}
-        return render(request, 'scipost/contributor_info.html', context)
-    else:
-        form = AuthenticationForm()
-        context = {'form': form}
-        return render(request, 'scipost/login.html', context)
+    contributor = Contributor.objects.get(pk=contributor_id)
+    contributor_submissions = Submission.objects.filter(authors__in=[contributor])
+    contributor_commentaries = Commentary.objects.filter(authors__in=[contributor])
+    contributor_theses = ThesisLink.objects.filter(author_as_cont__in=[contributor])
+    contributor_comments = (Comment.objects
+                            .filter(author=contributor, is_author_reply=False, status__gte=1)
+                            .order_by('-date_submitted'))
+    contributor_authorreplies = (Comment.objects
+                                 .filter(author=contributor, is_author_reply=True, status__gte=1)
+                                 .order_by('-date_submitted'))
+    context = {'contributor': contributor, 
+               'contributor_submissions': contributor_submissions,
+               'contributor_commentaries': contributor_commentaries,
+               'contributor_theses': contributor_theses,
+               'contributor_comments': contributor_comments, 
+               'contributor_authorreplies': contributor_authorreplies}
+    return render(request, 'scipost/contributor_info.html', context)
 
 
 
@@ -700,7 +708,7 @@ def contributor_info(request, contributor_id):
 # Lists #
 #########
 
-@permission_required('scipost.can_create_list', raise_exception=True)
+@permission_required('scipost.can_create_list')
 def create_list(request):
     listcreated = False
     message = None
@@ -722,7 +730,7 @@ def create_list(request):
     return render(request, 'scipost/create_list.html', context)
 
 
-@permission_required('scipost.can_create_list', raise_exception=True)
+@permission_required('scipost.can_create_list')
 def list(request, list_id):
     list = get_object_or_404(List, pk=list_id)
     context = {'list': list}
@@ -736,7 +744,7 @@ def list(request, list_id):
     return render(request, 'scipost/list.html', context)
 
 
-@permission_required('scipost.can_create_list', raise_exception=True)
+@permission_required('scipost.can_create_list')
 def list_add_element(request, list_id, type, element_id):
     list = get_object_or_404(List, pk=list_id)
     if type == 'C':
@@ -758,7 +766,7 @@ def list_add_element(request, list_id, type, element_id):
 # Teams #
 #########
 
-@permission_required('scipost.can_create_team', raise_exception=True)
+@permission_required('scipost.can_create_team')
 def create_team(request):
     if request.method == "POST":
         create_team_form = CreateTeamForm(request.POST)
@@ -775,7 +783,7 @@ def create_team(request):
                'add_team_member_form': add_team_member_form}
     return render(request, 'scipost/create_team.html', context)
 
-@permission_required('scipost.can_create_team', raise_exception=True)
+@permission_required('scipost.can_create_team')
 def add_team_member(request, team_id, contributor_id=None):
     team = get_object_or_404(Team, pk=team_id)
     contributors_found = None
@@ -799,7 +807,7 @@ def add_team_member(request, team_id, contributor_id=None):
 # Graphs #
 ##########
 
-@permission_required('scipost.can_create_graph', raise_exception=True)
+@permission_required('scipost.can_create_graph')
 def create_graph(request):
     graphcreated = False
     message = None
@@ -821,7 +829,7 @@ def create_graph(request):
     return render(request, 'scipost/create_graph.html', context)
 
 
-@permission_required('scipost.can_create_graph', raise_exception=True)
+@permission_required('scipost.can_create_graph')
 def graph(request, graph_id):
     graph = get_object_or_404(Graph, pk=graph_id)
     nodes = Node.objects.filter(graph=graph)
@@ -860,7 +868,7 @@ def graph(request, graph_id):
     return render(request, 'scipost/graph.html', context)
 
 
-@permission_required('scipost.can_create_graph', raise_exception=True)
+@permission_required('scipost.can_create_graph')
 def edit_graph_node(request, node_id):
     node = get_object_or_404(Node, pk=node_id)
     if request.method == "POST":
@@ -880,6 +888,7 @@ def edit_graph_node(request, node_id):
     return render(request, 'scipost/edit_graph_node.html', context)
 
 
+@login_required
 def api_graph(request, graph_id):
     """ Produce JSON data to plot graph """
     graph = get_object_or_404(Graph, pk=graph_id)
diff --git a/submissions/views.py b/submissions/views.py
index b3f301fa9..bb5900030 100644
--- a/submissions/views.py
+++ b/submissions/views.py
@@ -2,7 +2,7 @@ import datetime
 from django.utils import timezone
 from django.shortcuts import get_object_or_404, render, redirect
 from django.contrib.auth import authenticate, login, logout
-from django.contrib.auth.decorators import permission_required
+from django.contrib.auth.decorators import login_required, permission_required
 from django.contrib.auth.models import User
 from django.core.mail import send_mail
 from django.core.urlresolvers import reverse
@@ -26,6 +26,7 @@ from comments.forms import CommentForm
 # SUBMISSIONS:
 ###############
 
+@permission_required('scipost.can_submit_manuscript')
 def submit_manuscript(request):
     if request.method == 'POST':
         form = SubmissionForm(request.POST)
@@ -151,7 +152,7 @@ def submission_detail(request, submission_id):
 # Editorial workflow #
 ######################
 
-@permission_required('scipost.can_assign_submissions', raise_exception=True)
+@permission_required('scipost.can_assign_submissions')
 def assign_submissions(request):
     submission_to_assign = Submission.objects.filter(status='unassigned').first() # only handle one at at time
     if submission_to_assign is not None:
@@ -163,7 +164,7 @@ def assign_submissions(request):
     return render(request, 'submissions/assign_submissions.html', context)
 
 
-@permission_required('scipost.can_assign_submissions', raise_exception=True)
+@permission_required('scipost.can_assign_submissions')
 def assign_submission_ack(request, submission_id):
     submission = Submission.objects.get(pk=submission_id)
     if request.method == 'POST':
@@ -182,7 +183,7 @@ def assign_submission_ack(request, submission_id):
     return render(request, 'submissions/assign_submission_ack.html', context)
 
 
-@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
+@permission_required('scipost.can_take_charge_of_submissions')
 def accept_or_decline_assignments(request):
     contributor = Contributor.objects.get(user=request.user)
     assignment = EditorialAssignment.objects.filter(to=contributor, accepted=None).first()
@@ -191,7 +192,7 @@ def accept_or_decline_assignments(request):
     return render(request, 'submissions/accept_or_decline_assignments.html', context)
 
 
-@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
+@permission_required('scipost.can_take_charge_of_submissions')
 def accept_or_decline_assignment_ack(request, assignment_id):
     contributor = Contributor.objects.get(user=request.user)
     assignment = get_object_or_404 (EditorialAssignment, pk=assignment_id)
@@ -218,7 +219,7 @@ def accept_or_decline_assignment_ack(request, assignment_id):
     return render(request, 'submissions/accept_or_decline_assignment_ack.html', context)
 
 
-@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
+@permission_required('scipost.can_take_charge_of_submissions')
 def editorial_page(request, submission_id):
     submission = get_object_or_404(Submission, pk=submission_id)
     ref_invitations = RefereeInvitation.objects.filter(submission=submission)
@@ -228,7 +229,7 @@ def editorial_page(request, submission_id):
     return render(request, 'submissions/editorial_page.html', context)
 
 
-@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
+@permission_required('scipost.can_take_charge_of_submissions')
 def select_referee(request, submission_id):
     submission = get_object_or_404(Submission, pk=submission_id)
     if request.method == 'POST':
@@ -244,7 +245,7 @@ def select_referee(request, submission_id):
     return render(request, 'submissions/select_referee.html', context)
 
 
-@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
+@permission_required('scipost.can_take_charge_of_submissions')
 def recruit_referee(request, submission_id):
     """
     If the Editor-in-charge does not find the desired referee among Contributors,
@@ -290,7 +291,7 @@ def recruit_referee(request, submission_id):
     return redirect(reverse('submissions:editorial_page', kwargs={'submission_id': submission_id}))
 
             
-@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
+@permission_required('scipost.can_take_charge_of_submissions')
 def send_refereeing_invitation(request, submission_id, contributor_id):
     submission = get_object_or_404(Submission, pk=submission_id)
     contributor = get_object_or_404(Contributor, pk=contributor_id)
@@ -304,7 +305,7 @@ def send_refereeing_invitation(request, submission_id, contributor_id):
     return redirect(reverse('submissions:editorial_page', kwargs={'submission_id': submission_id}))
 
 
-@permission_required('scipost.can_referee', raise_exception=True)
+@permission_required('scipost.can_referee')
 def accept_or_decline_ref_invitations(request):
     contributor = Contributor.objects.get(user=request.user)
     invitation = RefereeInvitation.objects.filter(referee=contributor, accepted=None).first()
@@ -313,7 +314,7 @@ def accept_or_decline_ref_invitations(request):
     return render(request, 'submissions/accept_or_decline_ref_invitations.html', context)
 
 
-@permission_required('scipost.can_referee', raise_exception=True)
+@permission_required('scipost.can_referee')
 def accept_or_decline_ref_invitation_ack(request, invitation_id):
     contributor = Contributor.objects.get(user=request.user)
     invitation = get_object_or_404 (RefereeInvitation, pk=invitation_id)
@@ -332,7 +333,7 @@ def accept_or_decline_ref_invitation_ack(request, invitation_id):
     return render(request, 'submissions/accept_or_decline_ref_invitation_ack.html', context)
 
 
-@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
+@permission_required('scipost.can_take_charge_of_submissions')
 def extend_refereeing_deadline(request, submission_id, days):
     submission = get_object_or_404 (Submission, pk=submission_id)
     submission.reporting_deadline += datetime.timedelta(days=int(days))
@@ -340,7 +341,7 @@ def extend_refereeing_deadline(request, submission_id, days):
     return redirect(reverse('submissions:editorial_page', kwargs={'submission_id': submission_id}))
     
 
-@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
+@permission_required('scipost.can_take_charge_of_submissions')
 def close_refereeing_round(request, submission_id):
     submission = get_object_or_404 (Submission, pk=submission_id)
     submission.open_for_reporting = False
@@ -350,6 +351,7 @@ def close_refereeing_round(request, submission_id):
     return redirect(reverse('submissions:editorial_page', kwargs={'submission_id': submission_id}))
 
 
+@login_required
 def communication(request, submission_id, type, referee_id=None):
     submission = get_object_or_404 (Submission, pk=submission_id)
     if request.method == 'POST':
@@ -373,7 +375,7 @@ def communication(request, submission_id, type, referee_id=None):
     return render(request, 'submissions/communication.html', context)
 
 
-@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
+@permission_required('scipost.can_take_charge_of_submissions')
 def eic_recommendation(request, submission_id):
     submission = get_object_or_404 (Submission, pk=submission_id)
     if request.method == 'POST':
@@ -397,7 +399,7 @@ def eic_recommendation(request, submission_id):
 # Reports
 ###########
 
-@permission_required('scipost.can_referee', raise_exception=True)
+@permission_required('scipost.can_referee')
 def submit_report(request, submission_id):
     submission = get_object_or_404 (Submission, pk=submission_id)
     if request.method == 'POST':
@@ -441,7 +443,7 @@ def submit_report(request, submission_id):
     return render(request, 'submissions/submit_report.html', context)
 
 
-@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
+@permission_required('scipost.can_take_charge_of_submissions')
 def vet_submitted_reports(request):
     contributor = Contributor.objects.get(user=request.user)
     report_to_vet = Report.objects.filter(status=0).first() # only handle one at a time
@@ -450,7 +452,7 @@ def vet_submitted_reports(request):
     return(render(request, 'submissions/vet_submitted_reports.html', context))
 
 
-@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
+@permission_required('scipost.can_take_charge_of_submissions')
 def vet_submitted_report_ack(request, report_id):
     if request.method == 'POST':
         form = VetReportForm(request.POST)
diff --git a/theses/views.py b/theses/views.py
index ab7305548..03b748e77 100644
--- a/theses/views.py
+++ b/theses/views.py
@@ -2,6 +2,7 @@ import datetime
 from django.utils import timezone
 from django.shortcuts import get_object_or_404, render
 from django.contrib.auth import authenticate, login, logout
+from django.contrib.auth.decorators import login_required, permission_required
 from django.contrib.auth.models import User
 from django.core.mail import EmailMessage
 from django.core.urlresolvers import reverse
@@ -23,38 +24,35 @@ title_dict = dict(TITLE_CHOICES) # Convert titles for use in emails
 ################
 
 
+@permission_required('scipost.can_request_thesislink')
 def request_thesislink(request):
-    if request.user.is_authenticated():
-        # If POST, process the form data
-        if request.method == 'POST':
-            form = RequestThesisLinkForm(request.POST)
-            if form.is_valid():
-                contributor = Contributor.objects.get(user=request.user)
-                thesislink = ThesisLink (
-                    requested_by = contributor,
-                    type = form.cleaned_data['type'],
-                    discipline = form.cleaned_data['discipline'],
-                    domain = form.cleaned_data['domain'],
-                    specialization = form.cleaned_data['specialization'],
-                    title = form.cleaned_data['title'],
-                    author = form.cleaned_data['author'],
-                    supervisor = form.cleaned_data['supervisor'],
-                    institution = form.cleaned_data['institution'],
-                    defense_date = form.cleaned_data['defense_date'],
-                    pub_link = form.cleaned_data['pub_link'],
-                    abstract = form.cleaned_data['abstract'],
-                    latest_activity = timezone.now(),
-                    )
-                thesislink.save()
-                return HttpResponseRedirect('request_thesislink_ack')
-        else:
-            form = RequestThesisLinkForm()
-        return render(request, 'theses/request_thesislink.html', {'form': form})
-    else: # user is not authenticated:
-        form = AuthenticationForm()
-        return render(request, 'scipost/login.html', {'form': form})
+    if request.method == 'POST':
+        form = RequestThesisLinkForm(request.POST)
+        if form.is_valid():
+            contributor = Contributor.objects.get(user=request.user)
+            thesislink = ThesisLink (
+                requested_by = contributor,
+                type = form.cleaned_data['type'],
+                discipline = form.cleaned_data['discipline'],
+                domain = form.cleaned_data['domain'],
+                specialization = form.cleaned_data['specialization'],
+                title = form.cleaned_data['title'],
+                author = form.cleaned_data['author'],
+                supervisor = form.cleaned_data['supervisor'],
+                institution = form.cleaned_data['institution'],
+                defense_date = form.cleaned_data['defense_date'],
+                pub_link = form.cleaned_data['pub_link'],
+                abstract = form.cleaned_data['abstract'],
+                latest_activity = timezone.now(),
+                )
+            thesislink.save()
+            return HttpResponseRedirect('request_thesislink_ack')
+    else:
+        form = RequestThesisLinkForm()
+    return render(request, 'theses/request_thesislink.html', {'form': form})
 
 
+@permission_required('scipost.can_vet_thesislink_requests')
 def vet_thesislink_requests(request):
     contributor = Contributor.objects.get(user=request.user)
     thesislink_to_vet = ThesisLink.objects.filter(vetted=False).first() # only handle one at a time
@@ -62,7 +60,7 @@ def vet_thesislink_requests(request):
     context = {'contributor': contributor, 'thesislink_to_vet': thesislink_to_vet, 'form': form }
     return render(request, 'theses/vet_thesislink_requests.html', context)
 
-
+@permission_required('scipost.can_vet_thesislink_requests')
 def vet_thesislink_request_ack(request, thesislink_id):
     if request.method == 'POST':
         form = VetThesisLinkForm(request.POST)
-- 
GitLab