Dates, hashes and more cross-references
This commit is contained in:
parent
247f050d5b
commit
82aa31cf50
@ -32,10 +32,12 @@ class NullEncryptedAnswer(EncryptedAnswer):
|
||||
class Ballot(EmbeddedObject):
|
||||
#_id = UUIDField()
|
||||
encrypted_answers = EmbeddedObjectListField()
|
||||
election_id = UUIDField()
|
||||
election_hash = StringField()
|
||||
|
||||
class Vote(EmbeddedObject):
|
||||
ballot = EmbeddedObjectField()
|
||||
cast_at = StringField()
|
||||
cast_at = DateTimeField()
|
||||
|
||||
class Voter(EmbeddedObject):
|
||||
_id = UUIDField()
|
||||
|
@ -81,6 +81,8 @@ class ElectionTestCase(EosTestCase):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
election_hash = SHA256().update_obj(election).hash_as_b64()
|
||||
|
||||
# Open voting
|
||||
self.do_task_assert(election, 'eos.base.workflow.TaskOpenVoting', 'eos.base.workflow.TaskCloseVoting')
|
||||
election.save()
|
||||
@ -89,12 +91,12 @@ class ElectionTestCase(EosTestCase):
|
||||
VOTES = [[[0], [0]], [[0, 1], [1]], [[2], [0]]]
|
||||
|
||||
for i in range(3):
|
||||
ballot = Ballot()
|
||||
ballot = Ballot(election_id=election._id, election_hash=election_hash)
|
||||
for j in range(2):
|
||||
answer = ApprovalAnswer(choices=VOTES[i][j])
|
||||
encrypted_answer = NullEncryptedAnswer(answer=answer)
|
||||
ballot.encrypted_answers.append(encrypted_answer)
|
||||
vote = Vote(ballot=ballot)
|
||||
vote = Vote(ballot=ballot, cast_at=DateTimeField.now())
|
||||
election.voters[i].votes.append(vote)
|
||||
|
||||
election.save()
|
||||
|
@ -29,6 +29,7 @@ class WorkflowTask(EmbeddedObject):
|
||||
provides = []
|
||||
|
||||
status = IntField(default=0, is_hashed=False)
|
||||
exited_at = DateTimeField(is_hashed=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@ -81,7 +82,7 @@ class WorkflowTask(EmbeddedObject):
|
||||
listener()
|
||||
|
||||
def on_exit(self):
|
||||
pass
|
||||
self.exited_at = DateTimeField.now()
|
||||
|
||||
def exit(self):
|
||||
if self.status is not WorkflowTask.Status.ENTERED:
|
||||
|
@ -76,7 +76,6 @@ class BigInt(EosObject):
|
||||
setattr(self, key, make_operator_func(func))
|
||||
|
||||
for key, func in [
|
||||
('__eq__', lambda x: x == 0),
|
||||
('__ne__', lambda x: x != 0),
|
||||
('__lt__', lambda x: x < 0),
|
||||
('__gt__', lambda x: x > 0),
|
||||
@ -104,6 +103,12 @@ class BigInt(EosObject):
|
||||
def __str__(self):
|
||||
return str(self.impl)
|
||||
|
||||
# TNYI: Transcrypt doesn't like that we've defined __eq__ in EosObject
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, BigInt):
|
||||
other = BigInt(other)
|
||||
return self.impl.compareTo(other.impl) == 0
|
||||
|
||||
def __int__(self):
|
||||
# WARNING: This will yield unexpected results for large numbers
|
||||
return int(str(self.impl))
|
||||
|
@ -31,6 +31,7 @@ if is_python:
|
||||
from bson.binary import UUIDLegacy
|
||||
|
||||
import base64
|
||||
from datetime import datetime
|
||||
import hashlib
|
||||
import json
|
||||
import uuid
|
||||
@ -119,6 +120,37 @@ if is_python:
|
||||
else:
|
||||
UUIDField = PrimitiveField
|
||||
|
||||
class DateTimeField(Field):
|
||||
def pad(self, number):
|
||||
if number < 10:
|
||||
return '0' + str(number)
|
||||
return str(number)
|
||||
|
||||
def serialise(self, value, for_hash=False, should_protect=False):
|
||||
if value is None:
|
||||
return None
|
||||
|
||||
if is_python:
|
||||
return value.strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
else:
|
||||
return value.getUTCFullYear() + '-' + self.pad(value.getUTCMonth() + 1) + '-' + self.pad(value.getUTCDate()) + 'T' + self.pad(value.getUTCHours()) + ':' + self.pad(value.getUTCMinutes()) + ':' + self.pad(value.getUTCSeconds()) + 'Z'
|
||||
|
||||
def deserialise(self, value):
|
||||
if value is None:
|
||||
return None
|
||||
|
||||
if is_python:
|
||||
return datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ')
|
||||
else:
|
||||
return Date.parse(value)
|
||||
|
||||
@staticmethod
|
||||
def now():
|
||||
if is_python:
|
||||
return datetime.utcnow()
|
||||
else:
|
||||
return __pragma__('js', '{}', 'new Date()')
|
||||
|
||||
# Objects
|
||||
# =======
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
from eos.core.tests import *
|
||||
|
||||
from eos.core.objects import __pragma__
|
||||
from eos.core.objects import *
|
||||
from eos.core.bigint import *
|
||||
from eos.core.hashing import *
|
||||
from eos.psr.bitstream import *
|
||||
@ -26,6 +26,8 @@ from eos.psr.mixnet import *
|
||||
from eos.psr.secretsharing import *
|
||||
from eos.psr.workflow import *
|
||||
|
||||
from eos.core.objects import __pragma__
|
||||
|
||||
class GroupValidityTestCase(EosTestCase):
|
||||
# HAC 4.24
|
||||
def miller_rabin_test(self, n, t):
|
||||
@ -252,6 +254,8 @@ class ElectionTestCase(EosTestCase):
|
||||
# Freeze election
|
||||
self.do_task_assert(election, 'eos.base.workflow.TaskConfigureElection', 'eos.base.workflow.TaskOpenVoting')
|
||||
|
||||
election_hash = SHA256().update_obj(election).hash_as_b64() # Keep track of the hash and make sure it doesn't change
|
||||
|
||||
# Open voting
|
||||
self.do_task_assert(election, 'eos.base.workflow.TaskOpenVoting', 'eos.base.workflow.TaskCloseVoting')
|
||||
election.save()
|
||||
@ -260,12 +264,12 @@ class ElectionTestCase(EosTestCase):
|
||||
VOTES = [[[0], [0]], [[0, 1], [1]], [[2], [0]]]
|
||||
|
||||
for i in range(3):
|
||||
ballot = Ballot()
|
||||
ballot = Ballot(election_id=election._id, election_hash=election_hash)
|
||||
for j in range(2):
|
||||
answer = ApprovalAnswer(choices=VOTES[i][j])
|
||||
encrypted_answer = BlockEncryptedAnswer.encrypt(election.sk.public_key, answer)
|
||||
ballot.encrypted_answers.append(encrypted_answer)
|
||||
vote = Vote(ballot=ballot)
|
||||
vote = Vote(ballot=ballot, cast_at=DateTimeField.now())
|
||||
election.voters[i].votes.append(vote)
|
||||
|
||||
election.save()
|
||||
@ -302,6 +306,9 @@ class ElectionTestCase(EosTestCase):
|
||||
self.do_task_assert(election, 'eos.base.workflow.TaskReleaseResults', None)
|
||||
election.save()
|
||||
|
||||
# Check the hash hasn't changed during that
|
||||
self.assertEqual(SHA256().update_obj(election).hash_as_b64(), election_hash)
|
||||
|
||||
class PVSSTestCase(EosTestCase):
|
||||
@py_only
|
||||
def test_basic(self):
|
||||
|
@ -17,6 +17,7 @@
|
||||
import click
|
||||
import flask
|
||||
|
||||
from eos.core.objects import *
|
||||
from eos.base.election import *
|
||||
from eos.psr.crypto import *
|
||||
from eos.psr.election import *
|
||||
@ -170,7 +171,7 @@ def election_api_cast_vote(election):
|
||||
|
||||
# Cast the vote
|
||||
ballot = EosObject.deserialise_and_unwrap(data['ballot'])
|
||||
vote = Vote(ballot=ballot, cast_at=datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'))
|
||||
vote = Vote(ballot=ballot, cast_at=DateTimeField.now())
|
||||
voter.votes.append(vote)
|
||||
|
||||
election.save()
|
||||
|
@ -37,13 +37,13 @@
|
||||
<p>
|
||||
Voting in this election
|
||||
{% if election.workflow.get_task('eos.base.workflow.TaskOpenVoting').status == Status.EXITED %}
|
||||
opened
|
||||
opened at {{ election.workflow.get_task('eos.base.workflow.TaskOpenVoting').exited_at.strftime('%Y-%m-%d %H:%M:%S') }} UTC
|
||||
{% else %}
|
||||
is scheduled to open
|
||||
{% endif %}
|
||||
at the administrators' discretion, and
|
||||
{% if election.workflow.get_task('eos.base.workflow.TaskCloseVoting').status == Status.EXITED %}
|
||||
closed
|
||||
closed at {{ election.workflow.get_task('eos.base.workflow.TaskCloseVoting').exited_at.strftime('%Y-%m-%d %H:%M:%S') }} UTC
|
||||
{% else %}
|
||||
is scheduled to close
|
||||
{% endif %}
|
||||
@ -58,6 +58,8 @@
|
||||
{% if election.workflow.get_task('eos.base.workflow.TaskReleaseResults').status == Status.EXITED %}
|
||||
<h2>Results</h2>
|
||||
|
||||
<p>Results were released at {{ election.workflow.get_task('eos.base.workflow.TaskReleaseResults').exited_at.strftime('%Y-%m-%d %H:%M:%S') }} UTC.</p>
|
||||
|
||||
{% for question in election.questions %}
|
||||
<h3>{{ loop.index }}. {{ question.prompt }}</h2>
|
||||
{% include eosweb.core.main.model_view_map[question.__class__]['result_raw'] %}
|
||||
|
Loading…
Reference in New Issue
Block a user