Added full input validation to the Create Event including unique event name and slug validation as well as email validation. The appropriate template data required for this from Event and DemoUser model is passed in upon rendering the create_event html template

This commit is contained in:
vince0656 2018-06-14 17:01:14 +01:00
parent 4ca3398683
commit 7fb52678ef
4 changed files with 613 additions and 106 deletions

View file

@ -1,17 +1,12 @@
import os
from io import StringIO
from django.shortcuts import render
from django.forms import inlineformset_factory, formset_factory
from django.contrib.auth.decorators import user_passes_test
from django.contrib import messages
from django.http import HttpResponseRedirect, HttpResponse, Http404
from django.core.urlresolvers import reverse
from django.shortcuts import get_object_or_404, render, render_to_response
from django.template import RequestContext
from django.core.exceptions import ObjectDoesNotExist
from django.utils import timezone
from django.views import generic
from django.conf import settings
from django.core import serializers
from .forms import EventForm, PollForm, OptionFormset, QuestionFormset, OrganiserFormSet, TrusteeFormSet, VoteForm, EventSetupForm, EventEditForm, DecryptionFormset, DecryptionFormSetHelper
from .models import Event, Poll, PollOption, EmailUser, Ballot, TrusteeKey, Decryption
@ -304,21 +299,12 @@ def create_event(request):
return HttpResponseRedirect("/event/")
elif request.method == "GET":
#form = EventForm()
#organiser_formset = OrganiserFormSet(prefix="formset_organiser", initial=[{'email': request.user.email }])
#trustee_formset = TrusteeFormSet(prefix="formset_trustee", initial=[{'email': request.user.email }])
# Create the formset, specifying the form and formset we want to use.
'''return render(request,
"polls/create_event.html",
{
"event": event,
"form": form,
"organiser_formset": organiser_formset,
"trustee_formset": trustee_formset,
"G_R_SITE_KEY": settings.RECAPTCHA_PUBLIC_KEY
})'''
# Obtain context data for the rendering of the html template
events = Event.objects.all()
demo_users = DemoUser.objects.all()
return render(request, "polls/create_event.html", {"G_R_SITE_KEY": settings.RECAPTCHA_PUBLIC_KEY, "user_email": request.user.email})
# Render the template
return render(request, "polls/create_event.html", {"G_R_SITE_KEY": settings.RECAPTCHA_PUBLIC_KEY, "user_email": request.user.email, "events": events, "demo_users": demo_users})
else:
return HttpResponseNotAllowed()

View file

@ -5,6 +5,29 @@
{% block content %}
<script type="text/javascript">
// This events list is generated for later input validation
var events_list = [
{% for event in events %}
{% if not forloop.first %},{% endif %}
{
title: "{{ event.title }}",
slug: "{{ event.EID }}"
}
{% endfor %}
];
// This list of demo user emails will be used for input validation
var user_emails = [
{% for user in demo_users %}
{% if not forloop.first %},{% endif %}
{
email: "{{ user.email }}"
}
{% endfor %}
];
</script>
<!-- The following UI was ported from the Election Authority UI in DEMOS1 by Vincent de Almeida -->
<!-- The DEMOS1 repository can be found at: https://github.com/mlevogiannis/demos-voting -->
<!-- TODO: look into i18n translations as this was a feature implemented in DEMOS1 -->
@ -19,31 +42,33 @@
{% csrf_token %}
<!-- TODO: Have not imported the if form not valid template code as this needs further investigating -->
<!-- Name -->
<div class="form-group"> <!-- Excluded class(missing %s): { if election_form.name.errors }has-error{ endif } -->
<div class="form-group">
<label for="name-input" class="col-sm-3 col-md-2 control-label">Name:</label> <!-- This text can be a template variable -->
<div class="col-sm-9 col-md-10">
<input type="text" class="form-control input-control" id="name-input" placeholder="Example: My poll" name="name-input" maxlength="255">
<span id="name-input-help-block" class="help-block">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
<span id="name-input-hint-block" class="help-block">
A short and clear name.
<!-- TODO: Alignment is potentially slightly too much to the left -->
</span>
<span id="name-input-error-block" class="help-block errorText">
<!-- Errors flagged here -->
</span>
</div>
</div>
<!-- Slug / Identifier -->
<div class="form-group"> <!-- Excluded class(missing %s): { if election_form.slug.errors }has-error{ endif } -->
<div class="form-group">
<label for="identifier-input" class="col-sm-3 col-md-2 control-label">Identifier:</label> <!-- This text can be a template variable -->
<div class="col-sm-9 col-md-10">
<input type="text" class="form-control input-control" id="identifier-input" placeholder="Example: My-poll" name="identifier-input" maxlength="255">
<span id="identifier-input-help-block" class="help-block">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
Used in the election URL, it must only consist of letters, numbers, underscores or hyphens; no whitespace is permitted.
<!-- TODO: Alignment is potentially slightly too much to the left -->
</span>
<span id="identifier-input-error-block" class="help-block errorText">
<!-- Errors flagged here -->
</span>
</div>
</div>
<!-- Voting start time -->
<div class="form-group "> <!-- Excluded class(missing %s): { if election_form.voting_starts_at.errors }has-error{ endif } -->
<div class="form-group ">
<label for="vote-start-input" class="col-sm-3 col-md-2 control-label">Voting starts at:</label>
<div class="col-sm-9 col-md-10">
<div class="input-group date">
@ -55,13 +80,15 @@
</span>
</div>
<span id="vote-start-input-help-block" class="help-block">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
Date and time when registered voters can commence voting. This includes the UTC offset starting with '+'.
</span>
<span id="vote-start-input-error-block" class="help-block errorText">
<!-- Errors flagged here -->
</span>
</div>
</div>
<!-- Voting end time -->
<div class="form-group "> <!-- Excluded class(missing %s): { if election_form.voting_ends_at.errors }has-error{ endif } -->
<div class="form-group ">
<label for="vote-end-input" class="col-sm-3 col-md-2 control-label">Voting ends at:</label>
<div class="col-sm-9 col-md-10">
<div class="input-group date">
@ -73,9 +100,11 @@
</span>
</div>
<span id="vote-end-input-help-block" class="help-block">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
Date and time when registered voters can no longer vote. This includes the UTC offset starting with '+'.
</span>
<span id="vote-end-input-error-block" class="help-block errorText">
<!-- Errors flagged here -->
</span>
</div>
</div>
<!-- Question / Statement -->
@ -84,9 +113,10 @@
<div class="col-sm-9 col-md-10">
<input type="text" class="form-control input-control" id="question-input" placeholder="Example: Elections for the European Parliament" name="question-input" maxlength="200">
<span id="question-input-help-block" class="help-block">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
Question / Statement that will be put forward to voters along with the below options.
<!-- TODO: Alignment is potentially slightly too much to the left -->
</span>
<span id="question-input-error-block" class="help-block errorText">
<!-- Errors flagged here -->
</span>
</div>
</div>
@ -94,14 +124,13 @@
<div class="form-group">
<label for="options-input" class="col-sm-3 col-md-2 control-label">Options:</label> <!-- This text can be a template variable -->
<div class="col-sm-9 col-md-10">
<div class="form-group"> <!-- Excluded class(missing %s): { if option_formset.non_form_errors }has-error{ endif }-->
<div class="form-group">
<table id="options-input-table" class="table table-hover">
<thead>
<tr>
<th class="text-center">#</th>
<th>Option</th>
<th class="text-center">Actions</th>
<!--Not sure what this does so disabling it: <th class="hidden">{ option_formset.management_form }</th> -->
</tr>
</thead>
<tbody id="sort" class="formset option-formset" data-formset-prefix="questions" data-formset-type="inline">
@ -113,10 +142,9 @@
</th>
<!-- Option Label -->
<td>
<div> <!-- Has error conditional class removed -->
<div>
<!-- TODO: Add an invisible screen reader label to associate with this and other inputs -->
<input type="text" class="form-control input-sm input-control" placeholder="Example: Candidate 1" id="option-name-input" name="option-name-input" maxlength="200">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
</div>
</td>
<!-- Delete Action -->
@ -134,10 +162,9 @@
</th>
<!-- Option Label -->
<td>
<div> <!-- Has error conditional class removed -->
<div>
<!-- TODO: Add an invisible screen reader label to associate with this and other inputs -->
<input type="text" class="form-control input-sm input-control" placeholder="Example: Candidate 2" id="option-name-input" name="option-name-input" maxlength="200">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
</div>
</td>
<!-- Delete Action -->
@ -155,10 +182,9 @@
</th>
<!-- Option Label -->
<td>
<div> <!-- Has error conditional class removed -->
<div>
<!-- TODO: Add an invisible screen reader label to associate with this and other inputs -->
<input type="text" class="form-control input-sm input-control" placeholder="Example: Candidate X" id="option-name-input" name="option-name-input" maxlength="200">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
</div>
</td>
<!-- Delete Action -->
@ -177,9 +203,11 @@
</button>
</div>
<span id="question-input-help-block" class="help-block">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
Drag and drop to re-order options.
</span>
<span id="options-input-error-block" class="help-block errorText">
<!-- Errors flagged here -->
</span>
</div>
</div>
</div>
@ -191,19 +219,18 @@
<div class="col-xs-6">
<label class="sr-only" for="minimum-input">Minimum</label>
<input type="number" class="form-control input-control" id="minimum-input" placeholder="Minimum" value="" name="minimum-input" min="0"> <!-- TODO: Max should be set to the number of options -->
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
</div>
<div class="col-xs-6">
<label class="sr-only" for="maximum-input">Maximum</label>
<input type="number" class="form-control input-control" id="maximum-input" placeholder="Maximum" value="" name="maximum-input" min="1"> <!-- TODO: Max should be set to the number of options -->
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
</div>
</div>
<span id="question-input-help-block" class="help-block">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
Minimum and maximum number of option selections that a voter can make for the specified question / statement.
<!-- TODO: Alignment is potentially slightly too much to the left -->
</span>
<span id="selections-input-error-block" class="help-block errorText">
<!-- Errors flagged here -->
</span>
</div>
</div>
<!-- Organisers -->
@ -217,7 +244,6 @@
<th class="text-center">#</th>
<th>Email</th>
<th class="text-center">Actions</th>
<!--Not sure what this does so disabling it: <th class="hidden">{ option_formset.management_form }</th> -->
</tr>
</thead>
<tbody class="formset organiser-formset" data-formset-prefix="organisers" data-formset-type="inline">
@ -229,10 +255,9 @@
</th>
<td>
<!-- Email -->
<div> <!-- Has error conditional class removed -->
<div>
<!-- TODO: Add an invisible screen reader label to associate with this and other inputs -->
<input type="text" class="form-control input-sm input-control" placeholder="Example: organiser@example.com" id="organiser-email-input" name="organiser-email-input" value="{{ user_email }}" maxlength="255">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
</div>
</td>
<td class="formset-form-actions text-center">
@ -250,10 +275,9 @@
</th>
<td>
<!-- Email -->
<div> <!-- Has error conditional class removed -->
<div>
<!-- TODO: Add an invisible screen reader label to associate with this and other inputs -->
<input type="text" class="form-control input-sm input-control" placeholder="Example: organiser@example.com" id="organiser-email-input" name="organiser-email-input" maxlength="255">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
</div>
</td>
<td class="formset-form-actions text-center">
@ -270,10 +294,9 @@
</th>
<td>
<!-- Email -->
<div> <!-- Has error conditional class removed -->
<div>
<!-- TODO: Add an invisible screen reader label to associate with this and other inputs -->
<input type="text" class="form-control input-sm input-control" placeholder="Example: organiser@example.com" id="organiser-email-input" name="organiser-email-input" maxlength="255">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
<input type="text" class="form-control input-sm input-control" placeholder="Example: organiserX@example.com" id="organiser-email-input" name="organiser-email-input" maxlength="255">
</div>
</td>
<td class="formset-form-actions text-center">
@ -291,9 +314,11 @@
</button>
</div>
<span id="question-input-help-block" class="help-block">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
Drag and drop to re-order emails.
</span>
<span id="organisers-input-error-block" class="help-block errorText">
<!-- Errors flagged here -->
</span>
</div>
</div>
</div>
@ -308,7 +333,6 @@
<th class="text-center">#</th>
<th>Email</th>
<th class="text-center">Actions</th>
<!--Not sure what this does so disabling it: <th class="hidden">{ option_formset.management_form }</th> -->
</tr>
</thead>
<tbody class="formset trustee-formset" data-formset-prefix="trustees" data-formset-type="inline">
@ -323,7 +347,6 @@
<div> <!-- Has error conditional class removed -->
<!-- TODO: Add an invisible screen reader label to associate with this and other inputs -->
<input type="text" class="form-control input-sm input-control" placeholder="Example: trustee@example.com" id="trustee-email-input" name="trustee-email-input" value="{{ user_email }}" maxlength="255">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
</div>
</td>
<td class="formset-form-actions text-center">
@ -344,7 +367,6 @@
<div> <!-- Has error conditional class removed -->
<!-- TODO: Add an invisible screen reader label to associate with this and other inputs -->
<input type="text" class="form-control input-sm input-control" placeholder="Example: trustee@example.com" id="trustee-email-input" name="trustee-email-input" maxlength="255">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
</div>
</td>
<td class="formset-form-actions text-center">
@ -363,8 +385,7 @@
<!-- Email -->
<div> <!-- Has error conditional class removed -->
<!-- TODO: Add an invisible screen reader label to associate with this and other inputs -->
<input type="text" class="form-control input-sm input-control" placeholder="Example: trustee@example.com" id="trustee-email-input" name="trustee-email-input" maxlength="255">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
<input type="text" class="form-control input-sm input-control" placeholder="Example: trusteeX@example.com" id="trustee-email-input" name="trustee-email-input" maxlength="255">
</div>
</td>
<td class="formset-form-actions text-center">
@ -381,10 +402,12 @@
Add Trustee Email
</button>
</div>
<span id="question-input-help-block" class="help-block">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
<span id="trustees-input-help-block" class="help-block">
Drag and drop to re-order emails.
</span>
<span id="trustees-input-error-block" class="help-block errorText">
<!-- Errors flagged here -->
</span>
</div>
</div>
</div>
@ -394,15 +417,16 @@
<div class="col-sm-9 col-md-10">
<textarea class="form-control input-control" id="voters-list-input" placeholder="alice@example.com, bob@example.com..." name="voters-list-input" rows="4"></textarea>
<span id="voters-list-input-help-block" class="help-block">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
Manually enter email addresses separated with commas. Alternatively, you can also upload a CSV file:
<!-- TODO: Alignment is potentially slightly too much to the left -->
</span>
<label for="files" class="btn btn-primary">
Upload CSV
</label>
<input type="file" id="files" name="file" class="btn-info">
<h4 id="result" class="hidden"></h4>
<span id="voters-input-error-block" class="help-block errorText">
<!-- Errors flagged here -->
</span>
</div>
</div>
<!-- reCAPTCHA -->
@ -414,15 +438,16 @@
data-expired-callback="reCExpiredCallback"
data-sitekey="{{ G_R_SITE_KEY }}"></div> <!-- Need to finish server implementation and import key from settings -->
<span id="recaptcha-input-help-block" class="help-block">
<!-- Error handling / input validation has been removed temporarily and would be placed here -->
Tick the box to prove that you're not a robot.
<!-- TODO: Alignment is potentially slightly too much to the left -->
</span>
</div>
</div>
<hr>
<input class="btn btn-success" type="submit" value="Create Event" id="submit-event-create" disabled/>
<input class="btn btn-danger" type="button" value="Cancel" id="cancel-event-create" onclick="location.href='{% url 'polls:index' %}'" />
<span id="all-errors-help-block" class="help-block errorText">
<!-- Place a summary of all errors here -->
</span>
</form>
</div>
</div>