Support null-encrypted election in web UI
This commit is contained in:
parent
adbdb21e0d
commit
d44c21cbd7
@ -1,5 +1,5 @@
|
||||
# Eos - Verifiable elections
|
||||
# Copyright © 2017-2019 RunasSudo (Yingtong Li)
|
||||
# Copyright © 2017-2021 RunasSudo (Yingtong Li)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
@ -29,6 +29,9 @@ class NullEncryptedAnswer(EncryptedAnswer):
|
||||
|
||||
def decrypt(self):
|
||||
return None, self.answer
|
||||
|
||||
def deaudit(self):
|
||||
return self
|
||||
|
||||
class Ballot(EmbeddedObject):
|
||||
#_id = UUIDField()
|
||||
@ -219,6 +222,10 @@ class Election(TopLevelObject):
|
||||
questions = EmbeddedObjectListField()
|
||||
results = EmbeddedObjectListField(is_hashed=False)
|
||||
|
||||
def can_audit(self):
|
||||
"""Can prepared votes be audited?"""
|
||||
return False
|
||||
|
||||
def verify(self):
|
||||
#__pragma__('skip')
|
||||
from eos.core.hashing import SHA256
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Eos - Verifiable elections
|
||||
# Copyright © 2017-18 RunasSudo (Yingtong Li)
|
||||
# Copyright © 2017-2021 RunasSudo (Yingtong Li)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
@ -38,7 +38,7 @@ class ElectionTestCase(EosTestCase):
|
||||
def test_run_election(self):
|
||||
# Set up election
|
||||
election = Election()
|
||||
election.workflow = WorkflowBase()
|
||||
election.workflow = BaseWorkflow()
|
||||
|
||||
# Check _instance
|
||||
self.assertEqual(election.workflow._instance, (election, 'workflow'))
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Eos - Verifiable elections
|
||||
# Copyright © 2017-18 RunasSudo (Yingtong Li)
|
||||
# Copyright © 2017-2021 RunasSudo (Yingtong Li)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
@ -58,7 +58,12 @@ class WorkflowTask(EmbeddedObject):
|
||||
|
||||
def are_dependencies_met(self):
|
||||
for depends_on_desc in self.depends_on:
|
||||
for depends_on_task in self.workflow.get_tasks(depends_on_desc):
|
||||
depends_on_tasks = list(self.workflow.get_tasks(depends_on_desc))
|
||||
|
||||
if len(depends_on_tasks) == 0:
|
||||
return False
|
||||
|
||||
for depends_on_task in depends_on_tasks:
|
||||
if depends_on_task.status is not WorkflowTaskStatus.EXITED:
|
||||
return False
|
||||
return True
|
||||
@ -184,7 +189,9 @@ class TaskReleaseResults(WorkflowTask):
|
||||
# Concrete workflows
|
||||
# ==================
|
||||
|
||||
class WorkflowBase(Workflow):
|
||||
class BaseWorkflow(Workflow):
|
||||
"""Base workflow, with no encryption"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Eos - Verifiable elections
|
||||
# Copyright © 2017 RunasSudo (Yingtong Li)
|
||||
# Copyright © 2017-2021 RunasSudo (Yingtong Li)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
@ -230,7 +230,12 @@ class PSRElection(Election):
|
||||
public_key = EmbeddedObjectField(SEGPublicKey)
|
||||
mixing_trustees = EmbeddedObjectListField()
|
||||
|
||||
def can_audit(self):
|
||||
"""Overrides Election.can_audit"""
|
||||
return True
|
||||
|
||||
def verify(self):
|
||||
"""Overrides Election.verify"""
|
||||
# Verify ballots
|
||||
super().verify()
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Eos - Verifiable elections
|
||||
Copyright © 2017-2019 RunasSudo (Yingtong Li)
|
||||
Copyright © 2017-2021 RunasSudo (Yingtong Li)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -22,17 +22,34 @@ isLibrariesLoaded = false;
|
||||
eosjs = null;
|
||||
|
||||
function generateEncryptedVote(election, answers, should_do_fingerprint) {
|
||||
encrypted_answers = [];
|
||||
for (var q_num = 0; q_num < answers.length; q_num++) {
|
||||
answer_json = answers[q_num];
|
||||
answer = eosjs.eos.core.objects.EosObject.deserialise_and_unwrap(answer_json, null);
|
||||
encrypted_answer = eosjs.eos.psr.election.BlockEncryptedAnswer.encrypt(election.public_key, answer, election.questions.__getitem__(q_num).max_bits() + 32); // +32 bits for the length
|
||||
encrypted_answers.push(eosjs.eos.core.objects.EosObject.serialise_and_wrap(encrypted_answer, null));
|
||||
if (election._name === 'eos.psr.election.PSRElection') {
|
||||
encrypted_answers = [];
|
||||
for (var q_num = 0; q_num < answers.length; q_num++) {
|
||||
answer_json = answers[q_num];
|
||||
answer = eosjs.eos.core.objects.EosObject.deserialise_and_unwrap(answer_json, null);
|
||||
encrypted_answer = eosjs.eos.psr.election.BlockEncryptedAnswer.encrypt(election.public_key, answer, election.questions.__getitem__(q_num).max_bits() + 32); // +32 bits for the length
|
||||
encrypted_answers.push(eosjs.eos.core.objects.EosObject.serialise_and_wrap(encrypted_answer, null));
|
||||
}
|
||||
|
||||
postMessage({
|
||||
encrypted_answers: encrypted_answers
|
||||
});
|
||||
} else if (election._name === 'eos.base.election.Election') {
|
||||
encrypted_answers = [];
|
||||
for (var q_num = 0; q_num < answers.length; q_num++) {
|
||||
answer_json = answers[q_num];
|
||||
answer = eosjs.eos.core.objects.EosObject.deserialise_and_unwrap(answer_json, null);
|
||||
encrypted_answer = eosjs.eos.base.election.NullEncryptedAnswer();
|
||||
encrypted_answer.answer = answer;
|
||||
encrypted_answers.push(eosjs.eos.core.objects.EosObject.serialise_and_wrap(encrypted_answer, null));
|
||||
}
|
||||
|
||||
postMessage({
|
||||
encrypted_answers: encrypted_answers
|
||||
});
|
||||
} else {
|
||||
throw "Don't know how to encrypt ballots in election of type " + election._name;
|
||||
}
|
||||
|
||||
postMessage({
|
||||
encrypted_answers: encrypted_answers
|
||||
});
|
||||
}
|
||||
|
||||
onmessage = function(msg) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{#
|
||||
Eos - Verifiable elections
|
||||
Copyright © 2017-2019 RunasSudo (Yingtong Li)
|
||||
Copyright © 2017-2021 RunasSudo (Yingtong Li)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -32,9 +32,17 @@
|
||||
{% elif template == 'booth/audit.html' %}
|
||||
{% set menuindex = 4 %}
|
||||
{% elif template == 'booth/cast.html' %}
|
||||
{% set menuindex = 5 %}
|
||||
{% if election.can_audit() %}
|
||||
{% set menuindex = 5 %}
|
||||
{% else %}
|
||||
{% set menuindex = 4 %}
|
||||
{% endif %}
|
||||
{% elif template == 'booth/complete.html' %}
|
||||
{% set menuindex = 6 %}
|
||||
{% if election.can_audit() %}
|
||||
{% set menuindex = 6 %}
|
||||
{% else %}
|
||||
{% set menuindex = 5 %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% macro menuitem(index, text) %}
|
||||
@ -50,9 +58,14 @@
|
||||
{{ menuitem(1, "Welcome") }}
|
||||
{{ menuitem(2, "Select") }}
|
||||
{{ menuitem(3, "Review") }}
|
||||
{{ menuitem(4, "Audit") }}
|
||||
{{ menuitem(5, "Cast") }}
|
||||
{{ menuitem(6, "Finish") }}
|
||||
{% if election.can_audit() %}
|
||||
{{ menuitem(4, "Audit") }}
|
||||
{{ menuitem(5, "Cast") }}
|
||||
{{ menuitem(6, "Finish") }}
|
||||
{% else %}
|
||||
{{ menuitem(4, "Cast") }}
|
||||
{{ menuitem(5, "Finish") }}
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<div class="ui container">
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
{#
|
||||
Eos - Verifiable elections
|
||||
Copyright © 2017-2019 RunasSudo (Yingtong Li)
|
||||
Copyright © 2017-2021 RunasSudo (Yingtong Li)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
{% block content %}
|
||||
<div id="cast_prompt">
|
||||
<p>Your vote has <span class="superem">not</span> yet been cast. Please make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>.</p>
|
||||
<p>Your vote has <span class="superem">not</span> yet been cast.{% if election.can_audit() %} Please make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>.{% endif %}</p>
|
||||
|
||||
<div class="ui negative message">
|
||||
<p>Your vote has <span class="superem">not</span> yet been cast. Please follow the instructions to continue.</p>
|
||||
@ -69,10 +69,12 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block after %}
|
||||
<div class="ui tiny message" style="margin-top: 3em;">
|
||||
<div class="header">Information for advanced users</div>
|
||||
<p>Your full ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64() }}</span>.</p>
|
||||
</div>
|
||||
{% if election.can_audit() %}
|
||||
<div class="ui tiny message" style="margin-top: 3em;">
|
||||
<div class="header">Information for advanced users</div>
|
||||
<p>Your full ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64() }}</span>.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
$(".message .close").on("click", function() {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
{#
|
||||
Eos - Verifiable elections
|
||||
Copyright © 2017-2019 RunasSudo (Yingtong Li)
|
||||
Copyright © 2017-2021 RunasSudo (Yingtong Li)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -23,7 +23,9 @@
|
||||
<p>Your vote has <span class="superem">not</span> yet been cast. Please follow the instructions to continue.</p>
|
||||
</div>
|
||||
|
||||
<p>Please make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>. Please retain a copy of your ballot fingerprint – you can use it to verify that your vote has been counted correctly. You may <a href="#" onclick="window.print();return false;">print this page</a> as a receipt if you wish.</p>
|
||||
{% if election.can_audit() %}
|
||||
<p>Please make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>. Please retain a copy of your ballot fingerprint – you can use it to verify that your vote has been counted correctly. You may <a href="#" onclick="window.print();return false;">print this page</a> as a receipt if you wish.</p>
|
||||
{% endif %}
|
||||
|
||||
<p>To continue, copy and paste the ballot below and provide it to the election administrator.</p>
|
||||
|
||||
@ -39,10 +41,12 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block after %}
|
||||
<div class="ui tiny message" style="margin-top: 3em;">
|
||||
<div class="header">Information for advanced users</div>
|
||||
<p>Your full ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64() }}</span>.</p>
|
||||
</div>
|
||||
{% if election.can_audit() %}
|
||||
<div class="ui tiny message" style="margin-top: 3em;">
|
||||
<div class="header">Information for advanced users</div>
|
||||
<p>Your full ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64() }}</span>.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block help %}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
{#
|
||||
Eos - Verifiable elections
|
||||
Copyright © 2017-2019 RunasSudo (Yingtong Li)
|
||||
Copyright © 2017-2021 RunasSudo (Yingtong Li)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -26,13 +26,16 @@
|
||||
<div class="content">
|
||||
<div class="header">Smart ballot tracker</div>
|
||||
<p>This smart ballot tracker confirms that {{ voter.py_name }} cast a vote in the election {{ election.py_name }} at {{ vote.cast_at }}.</p>
|
||||
<p>Ballot fingerprint: <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(vote.ballot).hash_as_b64(true) }}</span></p>
|
||||
{% if election.can_audit() %}
|
||||
<p>Ballot fingerprint: <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(vote.ballot).hash_as_b64(true) }}</span></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Please check that the ballot fingerprint above matches the ballot fingerprint you recorded earlier.</p>
|
||||
|
||||
<p>To confirm that your ballot was cast correctly, please go to the <a href="{{ election_base_url }}view/ballots">‘Voters and ballots’ page</a> for the {{ election.kind }} or click ‘Finish’, and confirm that the above ballot fingerprint appears next to your name.</p>
|
||||
{% if election.can_audit() %}
|
||||
<p>Please check that the ballot fingerprint above matches the ballot fingerprint you recorded earlier.</p>
|
||||
<p>To confirm that your ballot was cast correctly, please go to the <a href="{{ election_base_url }}view/ballots">‘Voters and ballots’ page</a> for the {{ election.kind }} or click ‘Finish’, and confirm that the above ballot fingerprint appears next to your name.</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block buttons %}
|
||||
@ -40,10 +43,12 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block after %}
|
||||
<div class="ui tiny message" style="margin-top: 3em;">
|
||||
<div class="header">Information for advanced users</div>
|
||||
<p>Your full ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(vote.ballot).hash_as_b64() }}</span>.</p>
|
||||
</div>
|
||||
{% if election.can_audit() %}
|
||||
<div class="ui tiny message" style="margin-top: 3em;">
|
||||
<div class="header">Information for advanced users</div>
|
||||
<p>Your full ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(vote.ballot).hash_as_b64() }}</span>.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block help %}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
{#
|
||||
Eos - Verifiable elections
|
||||
Copyright © 2017-2019 RunasSudo (Yingtong Li)
|
||||
Copyright © 2017-2021 RunasSudo (Yingtong Li)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -30,8 +30,12 @@
|
||||
{% include templates[selection_model_view_map[election.questions.__getitem__(loop.index0)._name]["selections_review"]] %}
|
||||
{% endfor %}
|
||||
|
||||
<p>If you are happy with your selections, then make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>.</p>
|
||||
<p>Click ‘Continue’, and you will be able to log in to cast your vote.</p>
|
||||
{% if election.can_audit() %}
|
||||
<p>If you are happy with your selections, then make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>.</p>
|
||||
<p>Click ‘Continue’, and you will be able to log in to cast your vote.</p>
|
||||
{% else %}
|
||||
<p>If you are happy with your selections, then click ‘Continue’, and you will be able to log in to cast your vote.</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block buttons %}
|
||||
@ -40,11 +44,13 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block after %}
|
||||
<div class="ui tiny message" style="margin-top: 3em;">
|
||||
<div class="header">Information for advanced users</div>
|
||||
<p>Your ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64() }}</span>.</p>
|
||||
<p>If you would like to audit your ballot, <a href="#" onclick="nextTemplate(1);">click here</a></p>
|
||||
</div>
|
||||
{% if election.can_audit() %}
|
||||
<div class="ui tiny message" style="margin-top: 3em;">
|
||||
<div class="header">Information for advanced users</div>
|
||||
<p>Your ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64() }}</span>.</p>
|
||||
<p>If you would like to audit your ballot, <a href="#" onclick="nextTemplate(1);">click here</a></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block help %}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
{#
|
||||
Eos - Verifiable elections
|
||||
Copyright © 2017-2019 RunasSudo (Yingtong Li)
|
||||
Copyright © 2017-2021 RunasSudo (Yingtong Li)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -30,8 +30,12 @@
|
||||
{% include templates[selection_model_view_map[election.questions.__getitem__(loop.index0)._name]["selections_review"]] %}
|
||||
{% endfor %}
|
||||
|
||||
<p>If you are happy with your selections, then make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>.</p>
|
||||
<p>Click ‘Continue’, and you will be able to copy your pre-poll ballot to provide to the election administrator.</p>
|
||||
{% if election.can_audit() %}
|
||||
<p>If you are happy with your selections, then make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>.</p>
|
||||
<p>Click ‘Continue’, and you will be able to copy your pre-poll ballot to provide to the election administrator.</p>
|
||||
{% else %}
|
||||
<p>If you are happy with your selections, then click ‘Continue’, and you will be able to copy your pre-poll ballot to provide to the election administrator.</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block buttons %}
|
||||
|
@ -212,12 +212,14 @@
|
||||
}
|
||||
});
|
||||
templates['booth/welcome.html'] = null;
|
||||
|
||||
boothTasks.append({
|
||||
activate: function(fromLeft) {
|
||||
showTemplate('booth/selections.html');
|
||||
}
|
||||
});
|
||||
templates['booth/selections.html'] = null;
|
||||
|
||||
boothTasks.append({
|
||||
activate: function(fromLeft) {
|
||||
if (fromLeft) {
|
||||
@ -237,12 +239,14 @@
|
||||
}
|
||||
});
|
||||
templates['booth/review_prepoll.html'] = null;
|
||||
|
||||
boothTasks.append({
|
||||
activate: function(fromLeft) {
|
||||
showTemplate('booth/audit.html', {ballot: booth.ballot});
|
||||
}
|
||||
});
|
||||
templates['booth/audit.html'] = null;
|
||||
|
||||
boothTasks.append({
|
||||
activate: function(fromLeft) {
|
||||
showTemplate('booth/cast_prepoll.html', {ballot: booth.ballot});
|
||||
@ -257,18 +261,21 @@
|
||||
}
|
||||
});
|
||||
templates['booth/review.html'] = null;
|
||||
|
||||
boothTasks.append({
|
||||
activate: function(fromLeft) {
|
||||
showTemplate('booth/audit.html', {ballot: booth.ballot});
|
||||
}
|
||||
});
|
||||
templates['booth/audit.html'] = null;
|
||||
|
||||
boothTasks.append({
|
||||
activate: function(fromLeft) {
|
||||
showTemplate('booth/cast.html', {ballot: booth.ballot, is_cast: false});
|
||||
}
|
||||
});
|
||||
templates['booth/cast.html'] = null;
|
||||
|
||||
boothTasks.append({
|
||||
activate: function(fromLeft) {
|
||||
showTemplate('booth/complete.html', {voter: booth.voter, vote: booth.vote});
|
||||
@ -287,6 +294,7 @@
|
||||
}
|
||||
});
|
||||
templates['booth/cast.html'] = null;
|
||||
|
||||
boothTasks.append({
|
||||
activate: function(fromLeft) {
|
||||
showTemplate('booth/complete.html', {voter: booth.voter, vote: booth.vote});
|
||||
|
8258
package-lock.json
generated
8258
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
9
package.json
Normal file
9
package.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@babel/cli": "^7.15.7",
|
||||
"@babel/core": "^7.15.8",
|
||||
"@babel/preset-env": "^7.15.8",
|
||||
"babelify": "^10.0.0",
|
||||
"browserify": "^17.0.0"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user