Initial commit of DEMOS2 with the upgraded 'Create Event' UI. However, there is no input validation currently
This commit is contained in:
commit
7084bd1b16
155 changed files with 8102 additions and 0 deletions
0
allauthdemo/polls/__init__.py
Executable file
0
allauthdemo/polls/__init__.py
Executable file
43
allauthdemo/polls/admin.py
Executable file
43
allauthdemo/polls/admin.py
Executable 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
7
allauthdemo/polls/apps.py
Executable 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
61
allauthdemo/polls/cpp_calls.py
Executable 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 += '¶m='+urllib2.quote(str(param))
|
||||
|
||||
testquerystring = '?number='+str(amount)
|
||||
testquerystring += '¶m='+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
383
allauthdemo/polls/forms.py
Executable 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
110
allauthdemo/polls/models.py
Executable 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)
|
0
allauthdemo/polls/polls/__init__.py
Executable file
0
allauthdemo/polls/polls/__init__.py
Executable file
22
allauthdemo/polls/polls/admin.py
Executable file
22
allauthdemo/polls/polls/admin.py
Executable 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)
|
7
allauthdemo/polls/polls/apps.py
Executable file
7
allauthdemo/polls/polls/apps.py
Executable file
|
@ -0,0 +1,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class PollsConfig(AppConfig):
|
||||
name = 'polls'
|
BIN
allauthdemo/polls/polls/demos_encrypt.so.dylib
Executable file
BIN
allauthdemo/polls/polls/demos_encrypt.so.dylib
Executable file
Binary file not shown.
0
allauthdemo/polls/polls/forms.py
Executable file
0
allauthdemo/polls/polls/forms.py
Executable file
32
allauthdemo/polls/polls/models.py
Executable file
32
allauthdemo/polls/polls/models.py
Executable 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
|
3
allauthdemo/polls/polls/static/polls/style.css
Executable file
3
allauthdemo/polls/polls/static/polls/style.css
Executable file
|
@ -0,0 +1,3 @@
|
|||
li a {
|
||||
color: green;
|
||||
}
|
9
allauthdemo/polls/polls/tests.py
Executable file
9
allauthdemo/polls/polls/tests.py
Executable 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
23
allauthdemo/polls/polls/urls.py
Executable 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'),
|
||||
]
|
98
allauthdemo/polls/polls/views.py
Executable file
98
allauthdemo/polls/polls/views.py
Executable 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})
|
3
allauthdemo/polls/static/polls/style.css
Executable file
3
allauthdemo/polls/static/polls/style.css
Executable file
|
@ -0,0 +1,3 @@
|
|||
li a {
|
||||
color: green;
|
||||
}
|
117
allauthdemo/polls/tasks.py
Executable file
117
allauthdemo/polls/tasks.py
Executable 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)
|
0
allauthdemo/polls/templatetags/__init__.py
Executable file
0
allauthdemo/polls/templatetags/__init__.py
Executable file
9
allauthdemo/polls/templatetags/custom_filters_tags.py
Executable file
9
allauthdemo/polls/templatetags/custom_filters_tags.py
Executable 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
12
allauthdemo/polls/tests.py
Executable 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
36
allauthdemo/polls/urls.py
Executable 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'),
|
||||
]
|
200
allauthdemo/polls/utils/CreateNewEventModelAdaptor.py
Normal file
200
allauthdemo/polls/utils/CreateNewEventModelAdaptor.py
Normal 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
|
||||
|
0
allauthdemo/polls/utils/__init__.py
Normal file
0
allauthdemo/polls/utils/__init__.py
Normal file
367
allauthdemo/polls/views.py
Executable file
367
allauthdemo/polls/views.py
Executable 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
|
Reference in a new issue