From 246609e62f7e835aaf41ee69e00e922c8c8a9edd Mon Sep 17 00:00:00 2001
From: Ben Adida <ben@adida.net>
Date: Sun, 6 Apr 2014 11:50:23 -0700
Subject: [PATCH] added better voter file upload processing

---
 helios/fixtures/voter-badfile.csv           |  5 +++++
 helios/models.py                            |  5 +++++
 helios/templates/voters_upload_confirm.html | 10 ++++++++++
 helios/tests.py                             |  9 ++++++++-
 helios/views.py                             |  7 ++++++-
 requirements.txt                            |  1 +
 6 files changed, 35 insertions(+), 2 deletions(-)
 create mode 100644 helios/fixtures/voter-badfile.csv

diff --git a/helios/fixtures/voter-badfile.csv b/helios/fixtures/voter-badfile.csv
new file mode 100644
index 0000000..fd674a9
--- /dev/null
+++ b/helios/fixtures/voter-badfile.csv
@@ -0,0 +1,5 @@
+Ben78@adida.net,Ben78 Adida
+ benadida5,ben5@adida.net ,  Ben5 Adida 
+benadida6,ben6@adida.net,Ben6 Adida
+benadida7,ben7@adida.net,Ben7 Adida
+ernesto,helios-testing-ernesto@adida.net,Erñesto Testing Helios
\ No newline at end of file
diff --git a/helios/models.py b/helios/models.py
index c59a089..3df75bb 100644
--- a/helios/models.py
+++ b/helios/models.py
@@ -703,9 +703,14 @@ class VoterFile(models.Model):
 
       if len(voter_fields) > 1:
         return_dict['email'] = voter_fields[1].strip()
+      else:
+        # assume single field means the email is the same field
+        return_dict['email'] = voter_fields[0].strip()
 
       if len(voter_fields) > 2:
         return_dict['name'] = voter_fields[2].strip()
+      else:
+        return_dict['name'] = return_dict['email']
 
       yield return_dict
     
diff --git a/helios/templates/voters_upload_confirm.html b/helios/templates/voters_upload_confirm.html
index 18d5e09..4f5d2ad 100644
--- a/helios/templates/voters_upload_confirm.html
+++ b/helios/templates/voters_upload_confirm.html
@@ -14,6 +14,14 @@ You have uploaded a file of voters. The first few rows of this file are:
 {% endfor %}
 </table>
 
+{% if email_problem %}
+<p style="font-size: 1.5em;">
+<b>HOLD ON</b>: those don't look like correct email addresses. Are you sure you uploaded a file with email address as second field?<br />
+
+<a href="{% url helios.views.voters_upload_cancel election.uuid %}">no, let me upload a different file</a>
+</p>
+
+{% else %}
 <p></p>
 <form method="post" action="" id="upload_form">
   Does this look right to you?
@@ -23,4 +31,6 @@ You have uploaded a file of voters. The first few rows of this file are:
 
 <a href="{% url helios.views.voters_upload_cancel election.uuid %}">no, let me upload a different file</a>
 
+{% endif %}
+
 {% endblock %}
diff --git a/helios/tests.py b/helios/tests.py
index f04114a..eeb9cac 100644
--- a/helios/tests.py
+++ b/helios/tests.py
@@ -543,6 +543,13 @@ class ElectionBlackboxTests(WebTest):
         response = self.client.get("/helios/elections/%s/trustees/view" % election_id)
         self.assertContains(response, "Trustee #1")
 
+        # add a few voters with an improperly placed email address
+        FILE = "helios/fixtures/voter-badfile.csv"
+        voters_file = open(FILE)
+        response = self.client.post("/helios/elections/%s/voters/upload" % election_id, {'voters_file': voters_file})
+        voters_file.close()
+        self.assertContains(response, "HOLD ON")
+
         # add a few voters, via file upload
         # this file now includes a UTF-8 encoded unicode character
         # yes I know that's not how you spell Ernesto.
@@ -652,7 +659,7 @@ class ElectionBlackboxTests(WebTest):
             # cast_confirm_page = cast_confirm_page.follow()
         else:
             # here we should be at the cast-confirm page and logged in
-            self.assertContains(cast_confirm_page, "I am ")
+            self.assertContains(cast_confirm_page, "CAST this ballot")
 
             # confirm the vote, now with the actual form
             cast_form = cast_confirm_page.form
diff --git a/helios/views.py b/helios/views.py
index 44002da..2c27750 100644
--- a/helios/views.py
+++ b/helios/views.py
@@ -13,6 +13,8 @@ from django.db import transaction
 
 from mimetypes import guess_type
 
+from validate_email import validate_email
+
 import csv, urllib, os, base64
 
 from crypto import algs, electionalgs, elgamal
@@ -1204,7 +1206,10 @@ def voters_upload(request, election):
         # import the first few lines to check
         voters = [v for v in voter_file_obj.itervoters()][:5]
 
-        return render_template(request, 'voters_upload_confirm', {'election': election, 'voters': voters})
+        # check if voter emails look like emails
+        email_problem = False in [validate_email(v['email']) for v in voters]
+
+        return render_template(request, 'voters_upload_confirm', {'election': election, 'voters': voters, 'email_problem': email_problem})
       else:
         return HttpResponseRedirect("%s?%s" % (settings.SECURE_URL_HOST + reverse(voters_upload, args=[election.uuid]), urllib.urlencode({'e':'no voter file specified, try again'})))
 
diff --git a/requirements.txt b/requirements.txt
index fa99dcf..0ee4a32 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -22,3 +22,4 @@ django-secure==0.1.2
 bleach==1.4
 boto==2.27.0
 django-ses==0.6.0
+validate_email==1.2
-- 
GitLab