Initial commit of DEMOS2 with the upgraded 'Create Event' UI. However, there is no input validation currently

This commit is contained in:
vince0656 2018-06-12 13:31:38 +01:00
commit 7084bd1b16
155 changed files with 8102 additions and 0 deletions

0
allauthdemo/polls/__init__.py Executable file
View file

43
allauthdemo/polls/admin.py Executable file
View file

@ -0,0 +1,43 @@
from django.contrib import admin
# Register your models here.
from allauthdemo.auth.models import DemoUser
from .models import Event, PollOption, Poll, Organiser
"""
from .models import Question, Choice
class ChoiceInline(admin.TabularInline):
model = Choice
extra = 3
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
]
inlines = [ChoiceInline]
list_display = ('question_text', 'pub_date', 'was_published_recently')
list_filter = ['pub_date']
search_fields = ['question_text']
"""
class PollAdminInline(admin.TabularInline):
model = Poll
class PollOptionAdminInline(admin.TabularInline):
model = PollOption
class EventAdmin(admin.ModelAdmin):
list_display = ("title",)
filter_horizontal = ('users_organisers', 'users_trustees')
class PollAdmin(admin.ModelAdmin):
inlines = [PollOptionAdminInline]
list_display = ("question_text",)
admin.site.register(Event, EventAdmin)
admin.site.register(Poll, PollAdmin)

7
allauthdemo/polls/apps.py Executable file
View file

@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class PollsConfig(AppConfig):
name = 'polls'

61
allauthdemo/polls/cpp_calls.py Executable file
View file

@ -0,0 +1,61 @@
import os
import shlex
import subprocess
import json
import urllib2
#change this file name etc., temporary change to get it working for the meantime
'''
All functions in this file have been re-implemenented by Thomas Smith
'''
def param():
jsondict = json.load(urllib2.urlopen('http://localhost:8080/param'))
return json.dumps(jsondict)
def combpk(amount, pks):
url = 'http://localhost:8080/cmpkstring'
querystring = '?number='+str(amount)
for pk in pks:
querystring += '&PK='+pk
print(url+querystring)
jsondict = json.load(urllib2.urlopen(url+querystring))
print(json.dumps(jsondict))
return json.dumps(jsondict)
def addec(amount, ciphers):
url = 'http://localhost:8080/addec'
querystring = '?number='+str(amount)
c1s = ciphers['c1s']
c2s = ciphers['c2s']
for i, value in enumerate(c1s):
querystring += "&C1="+str(c1s[i])
querystring += "&C2="+str(c2s[i])
print(url+querystring)
jsondict = json.load(urllib2.urlopen(url+querystring))
print(json.dumps(jsondict))
return json.dumps(jsondict)
def tally(amount, param, decs, cipher):
url = 'http://localhost:8080/tally'
querystring = '?number='+str(amount)
querystring += '&param='+urllib2.quote(str(param))
testquerystring = '?number='+str(amount)
testquerystring += '&param='+str(param)
for i, value in enumerate(decs):
querystring += "&decs="+str(value)
testquerystring += "&decs="+str(value)
querystring += '&cipher=' + urllib2.quote(str(cipher))
testquerystring += '&cipher=' + str(cipher)
print(url+querystring)
print(url+testquerystring)
jsondict = json.load(urllib2.urlopen(url+querystring))
print('tally: ' + str(jsondict['M']))
return str(jsondict['M'])

383
allauthdemo/polls/forms.py Executable file
View file

@ -0,0 +1,383 @@
from functools import partial
from django import forms
from django.core.validators import MinLengthValidator
from django.template.loader import render_to_string
from django.template import Context
from django.core.exceptions import ValidationError
from django.core.validators import EmailValidator
from django.core.mail import send_mail
from crispy_forms.helper import FormHelper
from crispy_forms.layout import LayoutObject, Layout, TEMPLATE_PACK, Fieldset, ButtonHolder, Submit, Div, Field, HTML
from crispy_forms.bootstrap import StrictButton, TabHolder, Tab, FormActions, PrependedText, PrependedAppendedText, Accordion, AccordionGroup
from captcha.fields import ReCaptchaField
from allauthdemo.auth.models import DemoUser
from .models import Event, Poll, PollOption, Organiser
def is_valid_email(email):
try:
valid_email = EmailValidator()
valid_email(email)
return True
except ValidationError:
return False
class EventForm(forms.ModelForm):
#trustees = forms.CharField(label="Trustee list", widget=forms.Textarea(attrs={'width':"100%", 'cols' : "80", 'rows': "20", }))
voters = forms.CharField(label="Voters", required=False, widget=forms.Textarea(attrs={'width':"100%", 'cols' : "80", 'rows': "20", }))
#self.voters.widget=forms.Textarea(attrs={'width':"100%", 'cols' : "80", 'rows': "20", })
votersTextFile = forms.FileField(required=False)
captcha = ReCaptchaField()
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.form_show_labels = False
self.helper.layout = Layout(
Accordion(
AccordionGroup('Event Details',
PrependedText('title', 'Title', placeholder="Title of the Event"),
Div(
PrependedAppendedText('start_time', 'Begins', '<span class="glyphicon glyphicon-calendar"></span>', placeholder="dd/mm/yyyy hh:mm"),
css_class="input-group date col-sm-6"
),
Div(
PrependedAppendedText('end_time', 'Ends', '<span class="glyphicon glyphicon-calendar"></span>', placeholder="dd/mm/yyyy hh:mm"),
css_class="input-group date col-sm-6"
),
Field('captcha')
),
AccordionGroup("Organisers",
HTML("<p>Event creators are automatically made an Organiser. Click and drag the tabs to reorder. Blank fields will be ignored.</p>"),
Formset("organiser_formset",
"polls/create_option.html",
OrganiserFormSetHelper()
),
),
AccordionGroup('Trustees',
HTML("<p>Click and drag the tabs to reorder. Blank fields will be ignored.</p>"),
Formset("trustee_formset",
"polls/create_option.html",
TrusteeFormSetHelper()
),
),
AccordionGroup('Voters',
'voters',
HTML("<p>Comma seperated (.csv) file of valid email addresses</p>"),
'votersTextFile'
),
),
)
super(EventForm, self).__init__(*args, **kwargs)
class Meta:
model = Event
fields = ('title', 'start_time', 'end_time', 'captcha') # TWEAK!!!
widgets = {
'voters': forms.Textarea(attrs={'cols': 80, 'rows': 20})
}
class EventEditForm(forms.ModelForm):
#trustees = forms.CharField(label="Trustee list", widget=forms.Textarea(attrs={'width':"100%", 'cols' : "80", 'rows': "20", }))
voters = forms.CharField(label="Voters", required=False, widget=forms.Textarea(attrs={'width':"100%", 'cols' : "80", 'rows': "20", }))
#self.voters.widget=forms.Textarea(attrs={'width':"100%", 'cols' : "80", 'rows': "20", })
votersTextFile = forms.FileField(required=False)
captcha = ReCaptchaField()
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.form_show_labels = False
self.helper.layout = Layout(
Accordion(
AccordionGroup('Event Details',
PrependedText('title', 'Title', placeholder="Title of the Event"),
Div(
PrependedAppendedText('start_time', 'Begins', '<span class="glyphicon glyphicon-calendar"></span>', placeholder="dd/mm/yyyy hh:mm"),
css_class="input-group date col-sm-6"
),
Div(
PrependedAppendedText('end_time', 'Ends', '<span class="glyphicon glyphicon-calendar"></span>', placeholder="dd/mm/yyyy hh:mm"),
css_class="input-group date col-sm-6"
),
Field('captcha')
),
AccordionGroup('Voters',
'voters',
HTML("<p>Comma seperated (.csv) file of valid email addresses</p>"),
'votersTextFile'
),
),
)
super(EventEditForm, self).__init__(*args, **kwargs)
class Meta:
model = Event
fields = ('title', 'start_time', 'end_time', 'captcha') # TWEAK!!!
widgets = {
'voters': forms.Textarea(attrs={'cols': 80, 'rows': 20})
}
class EventSetupForm(forms.Form):
public_key = forms.CharField(max_length=1024, required=True)
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.form_show_labels = False
self.helper.layout = Layout(
Field('public_key', id="public-key")
)
super(EventSetupForm, self).__init__(*args, **kwargs)
class Meta:
fields = ('public_key',)
class PollForm(forms.ModelForm):
question_text = forms.CharField(
max_length = 80,
required = True,
)
def __init__(self, *args, **kwargs):
option_formset = kwargs.pop('option_formset', None)
choices = option_formset.total_form_count() if option_formset else 2
self.helper = FormHelper()
self.helper.form_show_labels = False
self.helper.form_tag = False
self.helper.layout = Layout(
Accordion(
AccordionGroup("Poll Details",
PrependedText('question_text', 'Question', placeholder='The question or title of your poll')
),
AccordionGroup("Poll Options",
HTML("<p>Click and drag the tabs to reorder</p>"),
Formset("option_formset",
"polls/create_option.html",
PollOptionFormSetHelper()
)
)
),
)
super(PollForm, self).__init__(*args, **kwargs)
class Meta:
model = Poll
fields = ('question_text',)
class VoteModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return obj.choice_text
class VoteForm(forms.ModelForm):
cipher_text_c1 = forms.CharField(
max_length = 1024,
required = True,
)
cipher_text_c2 = forms.CharField(
max_length = 1024,
required = True,
)
def __init__(self, *args, **kwargs):
super(VoteForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_show_labels = False
self.helper.form_tag = False
self.helper.layout = Layout(
Field('cipher_text_c1', type="hidden"),
Field('cipher_text_c2', type="hidden")
)
class Meta:
model = Poll
fields = ()#'options')
class DecryptionForm(forms.Form):
text = forms.CharField(max_length=1024, required=True)
def __init__(self, *args, **kwargs):
super(DecryptionForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_show_labels = False
self.helper.form_tag = False
self.layout = Layout(
PrependedText('text', 'Cipher'),
)
class Meta:
model = Poll
fields = ('enc',)#'options')
class EmailForm(forms.Form):
email = forms.CharField(
max_length = 80,
required = True,
)
def __init__(self, *args, **kwargs):
super(EmailForm, self).__init__(*args, **kwargs)
def clean_email(self):
email = self.cleaned_data['email']
if is_valid_email(email):
return email
raise forms.ValidationError(u'This doesn\'t appear to be a valid email address.')
class OrganiserForm(EmailForm):
def clean_email(self):
email = self.cleaned_data['email']
if is_valid_email(email):
if DemoUser.objects.filter(email=email).exists():
return email
raise forms.ValidationError(u'User "%s" does not exist.' % email)
raise forms.ValidationError(u'This doesn\'t appear to be a valid email address.')
class BaseFormSetHelper(FormHelper):
def __init__(self, *args, **kwargs):
super(BaseFormSetHelper, self).__init__(*args, **kwargs)
self.form_method = 'post'
self.form_show_labels = False
self.form_tag = False
self.layout = Layout()
#Field('organiser_email', placeholder="Option here")
self.render_required_fields = True
class OrganiserFormSetHelper(BaseFormSetHelper):
def __init__(self, *args, **kwargs):
super(OrganiserFormSetHelper, self).__init__(*args, **kwargs)
self.layout = Layout(
Div(
Field('DELETE', css_class='input-small hidden'),
PrependedAppendedText('email', 'Email ', "<span data-toggle='tooltip' title='Delete this Organiser' class='glyphicon glyphicon-trash'></span>", placeholder="Email address of the organiser"),
css_class="formset_object")
)
class DecryptionFormSetHelper(BaseFormSetHelper):
def __init__(self, *args, **kwargs):
super(DecryptionFormSetHelper, self).__init__(*args, **kwargs)
self.form_show_labels = False
self.layout = Layout(
Div(
PrependedText('text', 'Cipher '),
css_class="formset_object")
)
class TrusteeFormSetHelper(BaseFormSetHelper):
def __init__(self, *args, **kwargs):
super(TrusteeFormSetHelper, self).__init__(*args, **kwargs)
self.layout = Layout(
Div(
Field('DELETE', css_class='input-small hidden'),
PrependedAppendedText('email', 'Email ', "<span data-toggle='tooltip' title='Delete this Trustee' class='glyphicon glyphicon-trash'></span>", placeholder="Email address of the trustee"),
css_class="formset_object")
)
class PollOptionFormSetHelper(BaseFormSetHelper):
def __init__(self, *args, **kwargs):
super(PollOptionFormSetHelper, self).__init__(*args, **kwargs)
self.layout = Layout(
Div(
Field('DELETE', css_class='input-small hidden'),
PrependedAppendedText('choice_text', 'Option', "<span class='glyphicon glyphicon-trash'></span>", placeholder="Option"),
css_class="formset_object")
)
class PollOptionFormSetHelper(BaseFormSetHelper):
def __init__(self, *args, **kwargs):
super(PollOptionFormSetHelper, self).__init__(*args, **kwargs)
self.layout = Layout(
Div(
Field('DELETE', css_class='input-small hidden'),
PrependedAppendedText('choice_text', 'Option', "<span class='glyphicon glyphicon-trash'></span>", placeholder="Option"),
css_class="formset_object")
)
### EXPERIMENTAL https://stackoverflow.com/questions/15157262/django-crispy-forms-nesting-a-formset-within-a-form/22053952#22053952
class Formset(LayoutObject):
"""
Layout object. It renders an entire formset, as though it were a Field.
Example::
Formset("attached_files_formset")
"""
template = "%s/formset.html" % TEMPLATE_PACK
def __init__(self, formset_name_in_context, template=None, helper=None):
self.formset_name_in_context = formset_name_in_context
# crispy_forms/layout.py:302 requires us to have a fields property
self.fields = []
# Overrides class variable with an instance level variable
if template:
self.template = template
if helper:
self.helper = helper
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK):
formset = context[self.formset_name_in_context]
return render_to_string(self.template, Context({'wrapper': self,
'formset': formset, 'helper': self.helper}))
class OptionForm(forms.ModelForm):
choice_text = forms.CharField(label=('Option'),
min_length=1, max_length=1024)
def clean_option(self):
return _trim_whitespace(self.cleaned_data['text'])
class Meta:
model = PollOption
fields = ('choice_text',)
OrganiserFormSet = forms.formset_factory(form=OrganiserForm, extra=0, min_num=1, max_num=10, can_delete=True)
TrusteeFormSet = forms.formset_factory(form=EmailForm, extra=1, min_num=1, max_num=10, can_delete=True)
DecryptionFormset = forms.formset_factory(form=DecryptionForm, extra=0, min_num=0, validate_min=True, max_num=20, can_delete=False)
OptionFormset = forms.inlineformset_factory(Poll, PollOption, form=OptionForm, min_num=2, max_num=20, validate_min=True, extra=0, fields=('choice_text',), can_delete=True)
QuestionFormset = forms.inlineformset_factory(Event, Poll, form=PollForm, extra=0, min_num=2, validate_min=True, max_num=20, can_delete=True)
"""
PartialQuestionFormSet = partial(forms.formset_factory, PollQuestionForm, extra=2,
validate_min=True, validate_max=True, min_num=1, max_num=10)
OptionFormset = forms.inlineformset_factory(PollQuestion, QuestionChoice, extra=3, fields=('choice_text',))
QuestionFormset = forms.inlineformset_factory(Poll, PollQuestion,
formset=BasePollQuestionFormset, extra=2, fields=('question_text',))
TenantFormset = forms.inlineformset_factory(Building, Tenant, extra=1, fields=('name',))
BuildingFormset = forms.inlineformset_factory(Block, Building,
formset=BaseBuildingFormset, extra=1, fields=('address',))
AccordionGroup('Poll Questions',
Formset("question_formset",
"polls/create_question.html"
)
),
"""
"""
class PollQuestionForm(forms.ModelForm):
question_text = forms.CharField(
label = "Poll Title",
max_length = 80,
required = True,
)
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.layout = Layout(
TabHolder(
Tab('question_text')
),
)
super(PollQuestionForm, self).__init__(*args, **kwargs)
class Meta:
model = PollQuestion
fields = ('question_text',)
"""

110
allauthdemo/polls/models.py Executable file
View file

@ -0,0 +1,110 @@
from __future__ import unicode_literals
from django.db import models
from django import forms
# Create your models here.
import datetime
from django.utils import timezone
from allauthdemo.auth.models import DemoUser
class EmailUser(models.Model):
email = models.CharField(max_length=80, unique=True)
def __unicode__(self):
return self.email
class Event(models.Model):
users_organisers = models.ManyToManyField(DemoUser, blank=True, related_name="organisers")
users_trustees = models.ManyToManyField(EmailUser, blank=True, related_name="trustees")
voters = models.ManyToManyField(EmailUser, blank=True, related_name="voters")
start_time = models.DateTimeField()
end_time = models.DateTimeField()
prepared = models.BooleanField(default=False)
public_key = models.CharField(null=True, blank=False, max_length=1024)
title = models.CharField(max_length=1024)
EID = models.CharField(max_length=2048, blank=True)
creator = models.CharField(max_length=256, blank=True)
c_email = models.CharField(max_length=512, blank=True)
trustees = models.CharField(max_length=4096)
def __str__(self):
return self.title
class TrusteeKey(models.Model):
event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name="trustee_keys")
user = models.ForeignKey(EmailUser, on_delete=models.CASCADE, related_name="trustee_keys")
key = models.CharField(max_length=1024, unique=True) # ideally composite key here, but django doesn't really support yet
class AccessKey(models.Model):
event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name="keys")
user = models.ForeignKey(EmailUser, on_delete=models.CASCADE, related_name="keys")
key = models.CharField(max_length=1024, unique=True) # ideally composite key here, but django doesn't really support yet
#total = models.IntegerField(blank=True, null=True, default=0)
def has_started(self):
return timezone.now() >= self.start
def has_ended(self):
return timezone.now() >= self.end
def __unicode__(self):
return self.title
class Poll(models.Model):
question_text = models.CharField(max_length=200)
total_votes = models.IntegerField(default=0)
min_num_selections = models.IntegerField(default=0)
max_num_selections = models.IntegerField(default=1)
event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name="polls")
enc = models.CharField(max_length=4096, null=True)
#index = models.IntegerField()
def __str__(self):
return self.question_text
class Decryption(models.Model):
event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name="decryptions")
poll = models.ForeignKey(Poll, on_delete=models.CASCADE, related_name="decryptions")
user = models.ForeignKey(EmailUser, on_delete=models.CASCADE, related_name="decryptions")
text = models.CharField(max_length=1024)
#some modification to this class
class Ballot(models.Model):
voter = models.ForeignKey(EmailUser, on_delete=models.CASCADE, related_name="ballots")
poll = models.ForeignKey(Poll, on_delete=models.CASCADE, related_name="ballots")
cipher_text_c1 = models.CharField(max_length=4096)#the encryption system uses two byte strings
cipher_text_c2 = models.CharField(max_length=4096)
cast = models.BooleanField(default=False)
class PollOption(models.Model):
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
question = models.ForeignKey(Poll, on_delete=models.CASCADE, related_name="options")
#index = models.IntegerField()
def __str__(self):
return self.choice_text
class Organiser(models.Model):
index = models.IntegerField(default=0)
email = models.CharField(max_length=100, blank=False, null=False)
event = models.ForeignKey(Event, on_delete=models.CASCADE)
'''
class Organiser(models.Model):
user = models.ForeignKey(DemoUser, on_delete=models.CASCADE)
event = models.ForeignKey(Event, on_delete=models.CASCADE)
class Trustee(models.Model):
user = models.ForeignKey(DemoUser, on_delete=models.CASCADE)
event = models.ForeignKey(Event, on_delete=models.CASCADE)
'''
#class EventOrganisers():
#event = models.ForeignKey(Event, on_delete=models.CASCADE)

View file

View file

@ -0,0 +1,22 @@
from django.contrib import admin
# Register your models here.
from .models import Question, Choice
class ChoiceInline(admin.TabularInline):
model = Choice
extra = 3
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
]
inlines = [ChoiceInline]
list_display = ('question_text', 'pub_date', 'was_published_recently')
list_filter = ['pub_date']
search_fields = ['question_text']
admin.site.register(Question, QuestionAdmin)

View file

@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class PollsConfig(AppConfig):
name = 'polls'

Binary file not shown.

View file

View file

@ -0,0 +1,32 @@
from __future__ import unicode_literals
from django.db import models
# Create your models here.
import datetime
from django.utils import timezone
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
was_published_recently.admin_order_field = 'pub_date'
was_published_recently.boolean = True
was_published_recently.short_description = 'Published recently?'
def __str__(self):
return self.question_text
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text

View file

@ -0,0 +1,3 @@
li a {
color: green;
}

View file

@ -0,0 +1,9 @@
from django.test import TestCase
# Create your tests here.
import datetime
from django.utils import timezone
from django.test import TestCase
from django.core.urlresolvers import reverse

23
allauthdemo/polls/polls/urls.py Executable file
View file

@ -0,0 +1,23 @@
from django.conf.urls import url
from django.contrib.auth.decorators import login_required, permission_required
from . import views
app_name = 'polls'
#urlpatterns = [
# url(r'^$', views.index, name='index'),
# ex: /polls/5/
# url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
# ex: /polls/5/results/
# url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
# ex: /polls/5/vote/
# url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
#]
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>[0-9]+)/$', login_required(views.DetailView.as_view()), name='detail'),
url(r'^(?P<pk>[0-9]+)/results/$', login_required(views.ResultsView.as_view()), name='results'),
url(r'^(?P<question_id>[0-9]+)/vote/$', login_required(views.vote), name='vote'),
]

View file

@ -0,0 +1,98 @@
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.shortcuts import get_object_or_404, render
from django.utils import timezone
from .models import Question, Choice
from django.views import generic
""" from allauthdemo.auth.forms import RegistrationForm
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = RegistrationForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = RegistrationForm()
return render(request, 'polls/index.html', {'form': form}) """
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'
def get_queryset(self):
"""
Return the last five published questions (not including those set to be
published in the future).
"""
return Question.objects.filter(
pub_date__lte=timezone.now()
).order_by('-pub_date')[:5]
class DetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html'
def get_queryset(self):
"""
Excludes any questions that aren't published yet.
"""
return Question.objects.filter(pub_date__lte=timezone.now())
class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html'
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)
def detail(request, question_id):
return HttpResponse("You're looking at question %s." % question_id)
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
# ...
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})

View file

@ -0,0 +1,3 @@
li a {
color: green;
}

117
allauthdemo/polls/tasks.py Executable file
View file

@ -0,0 +1,117 @@
from __future__ import absolute_import
import csv
from os import urandom
import base64
from io import StringIO
from celery import task
from django.core.exceptions import ValidationError
from django.core.validators import EmailValidator
from django.core.mail import send_mail
from allauthdemo.polls.models import Ballot, Event, EmailUser, AccessKey
from .cpp_calls import param, combpk, addec, tally
def is_valid_email(email):
try:
valid_email = EmailValidator(whitelist=None)
valid_email(email)
return True
except ValidationError:
return False
@task()
def create_ballots(poll):
for voter in poll.event.voters.all():
ballot = poll.ballots.create(voter=voter, poll=poll)
@task()
def create_voters(csvfile, event):
print("Creating voters for event " + event.title)
reader = csv.reader(csvfile, delimiter=',')
string = ""
for row in reader:
email = string.join(row)
print(email)
#testvoter = EmailUser.objects.get_or_create(email='notarealemail@live.com')[0]
#event.voters.add(testvoter)
if (is_valid_email(email)):
voter = EmailUser.objects.get_or_create(email=email)[0]
event.voters.add(voter)
key = base64.urlsafe_b64encode(urandom(16)).decode('utf-8')
AccessKey.objects.create(user=voter, event=event, key=key)
send_mail(
'Your Voting Key',
'Key: ' + key,
'from@example.com',
[string.join(row)],
fail_silently=False,
)
'''
Starting here: functions re-implemented by Thomas Smith
'''
@task()
def generate_event_param(event):
event.EID = param()
event.save()
@task()
def tally_results(event):
for poll in event.polls.all():
decs = list()
for dec in poll.decryptions.all():
decs.append(dec.text)
amount = len(decs)
result = tally(amount, event.EID, decs, poll.enc)
send_mail(
'Your Results:',
poll.question_text + ": " + result,
'from@example.com',
["fake@fake.com"],
fail_silently=False,
)
print(poll.question_text + ": " + result)
@task()
def generate_combpk(event):
pks = list()
for tkey in event.trustee_keys.all():
pks.append(str(tkey.key))
amount = len(pks)
event.public_key = combpk(amount, pks)
event.prepared = True
event.save()
@task
def generate_enc(poll):
c1s = list()#c1 components of ciphertexts
c2s = list()#c1 components of ciphertexts
for ballot in poll.ballots.all():
if (ballot.cast):
c1s.append(str(ballot.cipher_text_c1))
c2s.append(str(ballot.cipher_text_c2))
ciphers = {
'c1s':c1s,
'c2s':c2s
}
amount = len(c1s)
poll.enc = addec(amount, ciphers)
poll.save()
'''
End of re-implemented code
'''
@task()
def add(x, y):
return x + y
@task()
def mul(x, y):
return x * y
@task()
def xsum(numbers):
return sum(numbers)

View file

View file

@ -0,0 +1,9 @@
from django import template
register = template.Library()
#get a value for additively homomorphic encryption ballots
#we can't do maths in the template normally so a filter is a way around it
@register.filter
def get_ballot_value(value):
return pow(10, value-1)

12
allauthdemo/polls/tests.py Executable file
View file

@ -0,0 +1,12 @@
from django.test import TestCase
# Create your tests here.
import datetime
from django.utils import timezone
from django.test import TestCase
from django.core.urlresolvers import reverse
from .models import Event
# come up with some tests

36
allauthdemo/polls/urls.py Executable file
View file

@ -0,0 +1,36 @@
from django.conf.urls import url
from django.contrib.auth.decorators import login_required, permission_required
from . import views
app_name = 'polls'
#urlpatterns = [
# url(r'^$', views.index, name='index'),
# ex: /polls/5/
# url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
# ex: /polls/5/results/
# url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
# ex: /polls/5/vote/
# url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
#]
urlpatterns = [
url(r'^vote/(?P<poll_id>[0-9]+)/$', views.test_poll_vote, name='vote-poll'),
url(r'^(?P<pk>[0-9]+)/$', views.EventDetailView.as_view(), name='view-event'),
url(r'^(?P<pk>[0-9]+)/polls$', views.EventDetailPollsView.as_view(), name='event-polls'),
url(r'^(?P<pk>[0-9]+)/organisers$', views.EventDetailOrganisersView.as_view(), name='event-organisers'),
url(r'^$', views.EventListView.as_view(), name='index'),
url(r'^create/$', login_required(views.create_event), name='create-event'),
url(r'^(?P<event_id>[0-9]+)/decrypt/$', login_required(views.event_trustee_decrypt), name='decrypt-event'),
url(r'^(?P<event_id>[0-9]+)/prepare/$', login_required(views.event_trustee_setup), name='prepare-event'),
url(r'^(?P<event_id>[0-9]+)/encrypt/$', login_required(views.event_addec), name='enc-event'),
url(r'^(?P<pk>[0-9]+)/launch/$', views.EventDetailLaunchView.as_view(), name='launch-event'),
url(r'^edit/(?P<event_id>[0-9]+)/$', login_required(views.edit_event), name='edit-event'),
url(r'^(?P<event_id>[0-9]+)/create/poll/$', login_required(views.manage_questions), name='create-poll'),
url(r'^(?P<event_id>[0-9]+)/poll/(?P<poll_num>[0-9]+)/$', login_required(views.view_poll), name='view-poll'),
url(r'^(?P<event_id>[0-9]+)/poll/(?P<poll_num>[0-9]+)/edit$', login_required(views.edit_poll), name='edit-poll'),
#url(r'^(?P<pk>[0-9]+)/$', login_required(views.DetailView.as_view()), name='detail'),
#url(r'^(?P<pk>[0-9]+)/results/$', login_required(views.ResultsView.as_view()), name='results'),
#url(r'^(?P<question_id>[0-9]+)/vote/$', login_required(views.vote), name='vote'),
]

View file

@ -0,0 +1,200 @@
from datetime import datetime
from allauthdemo.polls.models import Event
from allauthdemo.polls.models import Poll
from allauthdemo.polls.models import PollOption
from allauthdemo.polls.models import EmailUser
from allauthdemo.auth.models import DemoUser
'''
Goal: Convert the new form data (from the updated DEMOS2 UI) returned to '/event/create' into
an Event object that can be persisted via a Model to the DB
Author: Vincent de Almeida
Created: 11/07/2018
'''
# TODO: Define a validation function that can do back-end verification on top of the front end validation
# TODO: Validation can make use of __contains__ from QueryDict:
# TODO: https://docs.djangoproject.com/en/2.0/ref/request-response/#django.http.QueryDict
class CreateNewEventModelAdaptor:
# Raw data from form and django
form_data = None
user = None
# Extracted form data
event_name = None
identifier = None
starts_at = None
ends_at = None
min_num_selections = 0
max_num_selections = 0
organisers = []
trustees = []
voters = []
# Each element of the map has a sub array with 2 elements - poll and associated options
polls_options_map = []
# Event Model Object containing all the extracted data
event = None
def __init__(self, form_data, user):
self.form_data = form_data.copy()
self.user = user
# TODO: Call validation func here (incl functionality for verifying CSRF + reCAPTCHA)
self.__extractData()
def __extractData(self):
# Extract name and identifier first
self.event_name = self.form_data.pop('name-input')[0]
self.identifier = self.form_data.pop('identifier-input')[0]
# Extract start and end times as string and convert to datetime
starts_at = self.form_data.pop('vote-start-input')[0]
self.starts_at = datetime.strptime(starts_at, '%Y-%m-%d %H:%M')
ends_at = self.form_data.pop('vote-end-input')[0]
self.ends_at = datetime.strptime(ends_at, '%Y-%m-%d %H:%M')
# Extract the list of organisers
organisers_list = self.form_data.pop('organiser-email-input')
for organiser in organisers_list:
if organiser != '' and DemoUser.objects.filter(email=organiser).count() == 1:
self.organisers.append(DemoUser.objects.filter(email=organiser).get())
# Extract the list of trustees
trustees_list = self.form_data.pop('trustee-email-input')
for trustee in trustees_list:
if trustee != '':
if EmailUser.objects.filter(email=trustee).count() == 1:
self.trustees.append(EmailUser.objects.filter(email=trustee).get())
else:
self.trustees.append(EmailUser(email=trustee))
# Extract the email list of voters
voters_csv_string = self.form_data.pop('voters-list-input')[0].replace(' ', '')
voters_email_list = voters_csv_string.split(',')
for voter_email in voters_email_list:
if voter_email != '':
if EmailUser.objects.filter(email=voter_email).count() == 1:
self.voters.append(EmailUser.objects.filter(email=voter_email).get())
else:
self.voters.append(EmailUser(email=voter_email))
# Extract the min and max number of selections
self.min_num_selections = int(self.form_data.pop('minimum-input')[0])
self.max_num_selections = int(self.form_data.pop('maximum-input')[0])
# Create the Event model object - this does not persist it to the DB
self.event = Event(start_time=self.starts_at,
end_time=self.ends_at,
title=self.event_name,
EID=self.identifier,
creator=self.user.first_name + ' ' + self.user.last_name,
c_email=self.user.email,
trustees=voters_csv_string)
def __gen_polls_options_map(self):
# At the time of writing, you can only define one poll at event-creation time
# Generate PollOption objects from the option data defined in form_data
options = self.form_data.pop('option-name-input')
poll_options_list = []
for option in options:
if option != '':
poll_options_list.append(PollOption(choice_text=option, votes=0))
# Extract required Poll object data and create a poll with its PollOption objects
text = self.form_data.pop('question-input')[0]
votes = 0
poll = Poll(question_text=text,
total_votes=votes,
min_num_selections=self.min_num_selections,
max_num_selections=self.max_num_selections,
event=self.event)
self.polls_options_map.append([poll, poll_options_list])
# Instantiate all the polls and their associated poll options
def __get_instantiated_polls(self):
polls = []
for poll_option_map in self.polls_options_map:
poll = poll_option_map[0]
poll_options = poll_option_map[1]
# Save the poll to the db
poll.save()
# Instantiate poll options
for option in poll_options:
option.question = poll
option.save()
poll.options = poll_options
poll.save()
polls.append(poll)
return polls
def updateModel(self):
# First thing to do is persist the event object to the db
# with basic data before adding things like poll data
self.event.save()
# List of organisers should already be instantiated and present in the db
# so it can just be added
self.event.users_organisers = self.organisers
# Add the list of trustees to the event, making sure they're instantiated
for trustee in self.trustees:
if EmailUser.objects.filter(email=trustee.email).count() == 0:
trustee.save()
self.event.users_trustees = self.trustees
# Add the list of voters to the event, making sure they're instantiated
for voter in self.voters:
if EmailUser.objects.filter(email=voter.email).count() == 0:
voter.save()
self.event.voters = self.voters
# Extract all the poll data for the event and associated poll option data
# This can only be done at this point as the event has been persisted
self.__gen_polls_options_map()
# Get the instantiated list of polls which have already instantiated options
self.event.polls = self.__get_instantiated_polls()
self.event.save()
# Finally perform a data clean up
self.__clear_data()
def __clear_data(self):
self.form_data = None
self.user = None
self.event_name = None
self.identifier = None
self.starts_at = None
self.ends_at = None
self.min_num_selections = 0
self.max_num_selections = 0
self.organisers[:] = []
self.trustees[:] = []
self.voters[:] = []
self.polls_options_map[:] = []
self.event = None

View file

367
allauthdemo/polls/views.py Executable file
View file

@ -0,0 +1,367 @@
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 .forms import EventForm, PollForm, OptionFormset, QuestionFormset, OrganiserFormSet, TrusteeFormSet, VoteForm, EventSetupForm, EventEditForm, DecryptionFormset, DecryptionFormSetHelper
from .models import Event, Poll, PollOption, EmailUser, Ballot, TrusteeKey, Decryption
from allauthdemo.auth.models import DemoUser
from .tasks import create_voters, create_ballots, generate_event_param, generate_combpk, generate_enc, tally_results
from .cpp_calls import param, addec, combpk, tally
from .utils.CreateNewEventModelAdaptor import CreateNewEventModelAdaptor
class EventListView(generic.ListView):
model = Event
def get_context_data(self, **kwargs):
context = super(EventListView, self).get_context_data(**kwargs)
#context['now'] = timezone.now()
return context
class EventDetailView(generic.DetailView):
template_name="polls/event_detail_details.html"
model = Event
def get_context_data(self, **kwargs):
context = super(EventDetailView, self).get_context_data(**kwargs)
context['is_organiser'] = ((not self.request.user.is_anonymous()) and (self.object.users_organisers.filter(email=self.request.user.email).exists()))
#context['now'] = timezone.now()
return context
class EventDetailPollsView(EventDetailView):
template_name="polls/event_detail_polls.html"
class EventDetailOrganisersView(EventDetailView):
template_name="polls/event_detail_organisers.html"
class EventDetailLaunchView(EventDetailView):
template_name="polls/event_detail_launch.html"
class PollDetailView(generic.View):
model = Poll
def get_context_data(self, **kwargs):
context = super(PollDetailView, self).get_context_data(**kwargs)
#context['now'] = timezone.now()
context['form'] = VoteForm(instance=self.object)
context['poll_count'] = self.object.event.polls.all().count()
return context
#my_value = self.kwargs.get('key', 'default_value')
def test_poll_detail(request, event_id, poll_num, key=None):
context = {}
context['form'] = VoteForm(instance=self.object)
context['poll_count'] = self.object.event.polls.all().count()
return render(request, "polls/event_setup.html", context)
def util_get_poll_by_event_index(event, poll_num):
try:
poll_num = int(poll_num)
if ((poll_num < 1) or (poll_num > event.polls.all().count())):
return None
poll = event.polls.filter().order_by('id')[poll_num-1] # index field eventually
except ValueError:
return None
return poll
def edit_poll(request, event_id, poll_num):
event = get_object_or_404(Event, pk=event_id)
event_poll_count = event.polls.all().count()
poll = util_get_poll_by_event_index(event, poll_num)
if (poll == None):
raise Http404("Poll does not exist")
form = PollForm(instance=poll, prefix="main")
formset = OptionFormset(instance=poll, prefix="formset_options")
return render(request, "polls/generic_form.html", {'form_title': "Edit Poll: " + poll.question_text, 'form': form, 'option_formset': formset})
def view_poll(request, event_id, poll_num):
#return HttpResponse(param("012345"))
#return HttpResponse(combpk(param("012345"), "ABzqvL+pqTi+DNLLRcM62RwCoaZTaXVbOs3sk4fc0+Dc 0 AAaQd6S1x+bcgnkDp2ev5mTt34ICQdZIzP9GaqG4x5sy 0" "ABhQay9jI4pZvkAETNwfo8iwJ8eBMkjqplqAiu/FZxMy 0 ABPxj0jVj3rt0VW54iv4tV02gYtujnR41t5gf97asrPs 0 ABfoiW03bsYIUgfAThmjurmOViKy9L89vfkIavhQIblm 1 ABhQay9jI4pZvkAETNwfo8iwJ8eBMkjqplqAiu/FZxMy 0 ABPxj0jVj3rt0VW54iv4tV02gYtujnR41t5gf97asrPs 0 ABfoiW03bsYIUgfAThmjurmOViKy9L89vfkIavhQIblm 1 ABhQay9jI4pZvkAETNwfo8iwJ8eBMkjqplqAiu/FZxMy 0 ABPxj0jVj3rt0VW54iv4tV02gYtujnR41t5gf97asrPs 0 ABfoiW03bsYIUgfAThmjurmOViKy9L89vfkIavhQIblm 1"))
#return HttpResponse(addec("ACMW70Yj3+mJ/FO+6VOSDGYPYHf7NoTXdpInbfzUqYpH 0 ABV4Mo496B0FW3AW/7gY6Fs+oz6BwfwilonMYeriUyV/ 0 AAg+bdGhs3sxSxAc/wcKdBNUy+el8A2b4yVYShNOb8uX 0 AAspJbn5V2AaY4CgLkzCkHwUWbC5nyxrBzw+o4Az8HVM 1 ABKI7o5Yhgi44XwpFnPpLnH0/czbXA8y5vM4ucV8vojo 1 AAwVrT9+dcQsqRZYoI7+QsJvWOgd7JaJpfI6envmC2jU 1 ABIZO0DK4OrdROD805of6iRk2RenonGYmo2qG2IB1sj/ 1 ACMUHQdjGN0wyCd2AgDHMk9u0TpnywNVtamHWopGho8L 0 ABNT5lbE4siC3QklQXRvTwSQPwtme91+UrIr9iXT3y84 1 ABib0mmQ9ZVCrErqFwDgoRp3jHPpjHGQR2vsMVlwM+vI 0 ABvf3cg1NSS8fn6EKJNnTomeoflcEY1WBxkPPKrBBFl+ 0 ACBUZAtolN4HNh+mw4jLZuHzD+/rYHKR5av16PUc6BJF 0", "2"))
#return HttpResponse(tally("ACNQLLQlh+lNm1Dc+X+dEI0ECVLTkxRHjRnzX1OA+HtW 0 AAWOsUZK/G/cjhUee/gPAXop3Bc0CTVG3iDdQxD6+XqV 0", "ACNQLLQlh+lNm1Dc+X+dEI0ECVLTkxRHjRnzX1OA+HtW 0 0 2", "2"))
event = get_object_or_404(Event, pk=event_id)
if (not event.prepared):
messages.add_message(request, messages.WARNING, "This Event isn\'t ready for voting yet.")
return HttpResponseRedirect(reverse("user_home"))
event_poll_count = event.polls.all().count()
prev_poll_index, next_poll_index = False, False
can_vote, has_voted, voter_email, vote_count = False, False, "", 0
poll = util_get_poll_by_event_index(event, poll_num)
if (poll == None):
raise Http404("Poll does not exist")
form = VoteForm(instance=poll)
poll_num = int(poll_num) # now known to be safe as it suceeded in the util function
if (poll_num > 1):
prev_poll_index = (poll_num - 1)
if (poll_num < event_poll_count):
next_poll_index = (poll_num + 1)
access_key = request.GET.get('key', None)
email_key = event.keys.filter(key=access_key)
vote_count = Ballot.objects.filter(poll=poll, cast=True).count()
if (email_key.exists() and event.voters.filter(email=email_key[0].user.email).exists()):
ballot = Ballot.objects.filter(voter=email_key[0].user, poll=poll)
if (ballot.exists() and ballot[0].cast):
has_voted = True
if (access_key and email_key.exists()): #or (can_vote(request.user, event))
voter_email = email_key[0].user.email
can_vote = True
if (request.method == "POST"):
form = VoteForm(request.POST, instance=poll)
if (email_key.exists()):
#return HttpResponse(email_key[0].key)
ballot = Ballot.objects.get_or_create(voter=email_key[0].user, poll=poll)[0]
if (form.is_valid()):
ballot.cipher_text_c1 = request.POST["cipher_text_c1"]
ballot.cipher_text_c2 = request.POST["cipher_text_c2"]
ballot.cast = True
ballot.save()
if (next_poll_index):
return HttpResponseRedirect(reverse('polls:view-poll', kwargs={'event_id': event.id, 'poll_num': next_poll_index }) + "?key=" + email_key[0].key)
else:
return HttpResponse("Voted successfully!") # finished all polls in event
return render(request, "polls/poll_detail.html",
{"object": poll, "poll_num": poll_num , "event": event, "form": form, "poll_count": event.polls.all().count(),
"prev_index": prev_poll_index , "next_index": next_poll_index,
"can_vote": can_vote, "voter_email": voter_email, "has_voted": has_voted, "vote_count": vote_count
})
def event_trustee_setup(request, event_id):
event = get_object_or_404(Event, pk=event_id)
access_key = request.GET.get('key', None)
if (access_key):
email_key = event.keys.filter(key=access_key)
if (email_key.exists() and event.users_trustees.filter(email=email_key[0].user.email).exists()):
if (TrusteeKey.objects.filter(event=event, user=email_key[0].user).exists()):
messages.add_message(request, messages.WARNING, 'You have already submitted your key for this event')
return HttpResponseRedirect(reverse("user_home"))
if (request.method == "POST"):
form = EventSetupForm(request.POST)
if (form.is_valid()):
public_key = request.POST["public_key"]
key = TrusteeKey.objects.get_or_create(event=event, user=email_key[0].user)[0]
key.key = public_key
key.save()
if (event.trustee_keys.count() == event.users_trustees.count()): # ready for combpk
generate_combpk.delay(event)
messages.add_message(request, messages.SUCCESS, 'You have successfully submitted your public key for this event')
return HttpResponseRedirect(reverse("user_home"))
else:
form = EventSetupForm()
return render(request, "polls/event_setup.html", {"event": event, "form": form })
#if no key or is invalid?
messages.add_message(request, messages.WARNING, 'You do not have permission to access: ' + request.path)
return HttpResponseRedirect(reverse("user_home"))
def event_addec(request, event_id):
event = get_object_or_404(Event, pk=event_id)
for poll in event.polls.all():
generate_enc.delay(poll)
return HttpResponse("Generating enc.")
def event_trustee_decrypt(request, event_id):
event = get_object_or_404(Event, pk=event_id)
access_key = request.GET.get('key', None)
if (access_key):
email_key = event.keys.filter(key=access_key)
if (email_key.exists() and event.users_trustees.filter(email=email_key[0].user.email).exists()):
if (Decryption.objects.filter(event=event, user=email_key[0].user).exists()):
messages.add_message(request, messages.WARNING, 'You have already provided your decryptions for this event')
#if (event.decryptions.count() == (event.polls.count() * event.users_trustees.count())):
# tally_results.delay(event) # all keys are in
return HttpResponseRedirect(reverse("user_home"))
elif (request.method == "GET"):
initial = []
for poll in event.polls.all():
initial.append({'text': poll.enc })
formset = DecryptionFormset(initial=initial)
else:
formset = DecryptionFormset(request.POST)
data = []
for form in formset:
if form.is_valid():
data.append(form.cleaned_data.get('text'))
if (len(data) == event.polls.count()):
for dec, poll in zip(data, event.polls.all()):
Decryption.objects.get_or_create(user=email_key[0].user, event=event, poll=poll, text=dec)
messages.add_message(request, messages.SUCCESS, 'Decryption complete.')
if (event.decryptions.count() == (event.polls.count() * event.users_trustees.count())):
tally_results.delay(event) # all keys are in
else:
messages.add_message(request, messages.ERROR, 'You didn\'t provide decryptions for every poll. Please try again.')
return HttpResponseRedirect(reverse("user_home"))
return render(request, "polls/event_decrypt.html", {"event": event, "formset": formset, "helper": DecryptionFormSetHelper() })
messages.add_message(request, messages.WARNING, 'You do not have permission to decrypt this Event.')
return HttpResponseRedirect(reverse("user_home"))
def test_poll_vote(request, poll_id):
poll = get_object_or_404(Poll, pk=poll_id)
form = VoteForm(instance=poll)
return render(request, "polls/vote_poll.html", {"vote_form": form, "poll": poll})
def manage_questions(request, event_id):
event = get_object_or_404(Event, pk=event_id)
if (request.user.is_anonymous()) or (not event.users_organisers.filter(email=request.user.email).exists()):
messages.add_message(request, messages.WARNING, 'You do not have permission to access: ' + request.path)
return HttpResponseRedirect(reverse("user_home"))
poll = Poll()
formset = OptionFormset(instance=poll, prefix="formset_organiser")
if request.method == "POST":
form = PollForm(request.POST, prefix="main")
formset = OptionFormset(request.POST, prefix="formset_organiser") # incase form fails, we still want to retain formset data
if form.is_valid():
poll = form.save(commit=False)
poll.event_id = event_id
poll.save()
formset = OptionFormset(request.POST, prefix="formset_organiser", instance=poll)
if formset.is_valid():
for form in formset:
formset.save()
create_ballots.delay(poll)
messages.add_message(request, messages.SUCCESS, 'Poll created successfully')
return HttpResponseRedirect(reverse('polls:view-poll', kwargs={'event_id': poll.event_id, 'poll_num': event.polls.count() }))
return render(request, "polls/create_poll.html", {"event": event, "question_form": form, "option_formset": formset})
elif request.method == "GET":
form = PollForm(prefix="main") #, instance=poll
return render(request, "polls/create_poll.html", {"event": event, "question_form": form, "option_formset": formset})
else:
return HttpResponseNotAllowed()
def create_event(request):
#return HttpResponse(param(str(len("lol_age"))))
event = Event()
if request.method == "POST":
'''if request.FILES: # if there is a file we should ignore voters...?
csvfile = StringIO(request.FILES['votersTextFile'].read().decode('utf-8'))
print("got file from request:")
form = EventForm(request.POST)
organiser_formset = OrganiserFormSet(request.POST, prefix="formset_organiser") # incase form fails, we still want to retain formset data
trustee_formset = TrusteeFormSet(request.POST, prefix="formset_trustee")
if form.is_valid():
event = form.save()
generate_event_param.delay(event)
if request.FILES:
print("creating voters")
create_voters.delay(csvfile, event) # this will be done on event launch ultimately
if organiser_formset.is_valid():
#event.users_organisers.clear()
for oform in organiser_formset:
if (oform.cleaned_data.get('email')):
event.users_organisers.add(DemoUser.objects.get(email=oform.cleaned_data['email']))
event.users_organisers.add(request.user) # always add editor/creator
if trustee_formset.is_valid():
#event.users_trustees.clear()
for tform in trustee_formset:
if (tform.cleaned_data.get('email')):
event.users_trustees.add(EmailUser.objects.get_or_create(email=tform.cleaned_data['email'])[0])
return HttpResponseRedirect('/event/' + str(event.id) + '/create/poll') # change to reverse format
return render(request, "polls/create_event.html", {"event": event, "form": form, "organiser_formset": organiser_formset, "trustee_formset": trustee_formset})'''
adaptor = CreateNewEventModelAdaptor(request.POST, request.user)
adaptor.updateModel()
# TODO: Based on whether validation was successful within update model and whether
# TODO: data was actually persisted, either perform a redirect (success) or flag an error
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
})'''
return render(request, "polls/create_event.html", {"G_R_SITE_KEY": settings.RECAPTCHA_PUBLIC_KEY, "user_email": request.user.email})
else:
return HttpResponseNotAllowed()
def edit_event(request, event_id):
event = get_object_or_404(Event, pk=event_id)
if request.method == "GET":
form = EventEditForm(instance=event, prefix="main")
'''
organiser_initial_data = [{'email': request.user.email}]
trustee_initial_data = []
for user in event.users_organisers.exclude(email=request.user.email):
organiser_initial_data.append({'email': user.email})
organiser_formset = OrganiserFormSet(prefix="formset_organiser", initial=organiser_initial_data)
for trustee in event.users_trustees.all():
trustee_initial_data.append({'email': trustee.email})
trustee_formset = TrusteeFormSet(prefix="formset_trustee", initial=trustee_initial_data)
'''
elif request.method == "POST":
form = EventEditForm(request.POST, instance=event, prefix="main")
#trustee_formset = TrusteeFormSet(request.POST, prefix="formset_trustee")
#organiser_formset = OrganiserFormSet(request.POST, prefix="formset_organiser") # incase form fails, we still want to retain formset data
if form.is_valid():
form.save()
'''
if organiser_formset.is_valid():
event.users_organisers.clear()
for oform in organiser_formset:
if (oform.cleaned_data.get('email')):
event.users_organisers.add(DemoUser.objects.get(email=oform.cleaned_data['email']))
event.users_organisers.add(request.user) # always add editor/creator
if trustee_formset.is_valid():
event.users_trustees.clear()
for tform in trustee_formset:
if (tform.cleaned_data.get('email')):
event.users_trustees.add(EmailUser.objects.get_or_create(email=tform.cleaned_data['email'])[0])
'''
return HttpResponseRedirect(reverse('polls:view-event', kwargs={'pk': event.id}))
return render(request, "polls/generic_form.html", {"form_title": "Edit Event: " + event.title, "form": form}) #"organiser_formset": organiser_formset, "trustee_formset": trustee_formset})
#trustee_formset = TrusteeFormSet(request.POST, prefix="formset_trustee", instance=event)
#class CreatePoll(generic.View):
def can_vote(user, event):
if event.voters.filter(email=user.email).exists():
return True
return False