diff --git a/helios/security.py b/helios/security.py index 73115e00bcc85f1c3062918f2b25de7c6db4f34c..7abbf329858591f01ee1e94cadd27ddc8213306d 100644 --- a/helios/security.py +++ b/helios/security.py @@ -7,6 +7,7 @@ Ben Adida (ben@adida.net) # nicely update the wrapper function from functools import update_wrapper +from django.core.urlresolvers import reverse from django.core.exceptions import * from django.conf import settings @@ -72,17 +73,17 @@ def election_view(**checks): def election_view_decorator(func): def election_view_wrapper(request, election_uuid=None, *args, **kw): election = get_election_by_uuid(election_uuid) - + # do checks do_election_checks(election, checks) # if private election, only logged in voters if election.private_p and not checks.get('allow_logins',False): - from views import get_voter, get_user + from views import get_voter, get_user, password_voter_login user = get_user(request) if not user_can_admin_election(user, election) and not get_voter(request, user, election): # FIXME: should be a nice redirect - raise PermissionDenied() + return HttpResponseRedirect(reverse(password_voter_login, args=[election.uuid])) return func(request, election, *args, **kw) diff --git a/helios/templates/password_voter_login.html b/helios/templates/password_voter_login.html new file mode 100644 index 0000000000000000000000000000000000000000..dd92a32597317b242722e457ed8951afdc15d32d --- /dev/null +++ b/helios/templates/password_voter_login.html @@ -0,0 +1,12 @@ +{% extends TEMPLATE_BASE %} + +{% block title %}Log In to View Election{% endblock %} +{% block content %} +<h2>Private Election - Please Log In</h2> + +<p> +This election, with fingerprint <tt>{{election.hash}}</tt>, is private, and can only be viewed by eligible voters. +</p> + +{% include "_castconfirm_password.html" %} +{% endblock %} diff --git a/helios/tests.py b/helios/tests.py index 760c8deb84a3b7a8f2f726779fdfa03512406ba2..70bdabece16d2fc5fc05d424a2bd9a8660dece0c 100644 --- a/helios/tests.py +++ b/helios/tests.py @@ -492,7 +492,7 @@ class ElectionBlackboxTests(TestCase): # return the voter username and password to vote return election_id, username, password - def _cast_ballot(self, election_id, username, password): + def _cast_ballot(self, election_id, username, password, need_login=True): # vote by preparing a ballot via the server-side encryption response = self.client.post("/helios/elections/%s/encrypt-ballot" % election_id, { 'answers_json': utils.to_json([[1]])}) @@ -507,12 +507,15 @@ class ElectionBlackboxTests(TestCase): 'encrypted_vote': encrypted_vote}) self.assertRedirects(response, "%s/helios/elections/%s/cast_confirm" % (settings.SECURE_URL_HOST, election_id)) - # log in - response = self.client.post("/helios/elections/%s/password_voter_login" % election_id, { - 'voter_id' : username, - 'password' : password - }) - self.assertRedirects(response, "/helios/elections/%s/cast_confirm" % election_id) + if need_login: + response = self.client.post("/helios/elections/%s/password_voter_login" % election_id, { + 'voter_id' : username, + 'password' : password + }) + self.assertRedirects(response, "/helios/elections/%s/cast_confirm" % election_id) + else: + response = self.client.get("/helios/elections/%s/cast_confirm" % election_id) + self.assertContains(response, "I am ") # confirm the vote response = self.client.post("/helios/elections/%s/cast_confirm" % election_id, { @@ -576,5 +579,5 @@ class ElectionBlackboxTests(TestCase): }) self.assertRedirects(response, "/helios/elections/%s/view" % election_id) - self._cast_ballot(election_id, username, password) + self._cast_ballot(election_id, username, password, need_login = False) self._do_tally(election_id) diff --git a/helios/views.py b/helios/views.py index e2b377650e0ae681418ee1f9530f50e22952c57f..fbad7baa47420763a8d8301f0955c2f1ad7aa28b 100644 --- a/helios/views.py +++ b/helios/views.py @@ -499,11 +499,16 @@ def one_election_cast(request, election): return HttpResponseRedirect("%s%s" % (settings.SECURE_URL_HOST, reverse(one_election_cast_confirm, args=[election.uuid]))) -@election_view(frozen=True, allow_logins=True) +@election_view(allow_logins=True) def password_voter_login(request, election): """ This is used to log in as a voter for a particular election """ + + if request.method == "GET": + password_login_form = forms.VoterPasswordForm() + return render_template(request, 'password_voter_login', {'election': election, 'password_login_form': password_login_form}) + password_login_form = forms.VoterPasswordForm(request.POST) # redirect base depending on whether this is a private election