Allow hiding voters and/or votes

This commit is contained in:
RunasSudo 2021-10-16 20:44:31 +11:00
parent d44c21cbd7
commit fc4366c028
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
6 changed files with 63 additions and 20 deletions

View File

@ -214,6 +214,8 @@ class STVResult(Result):
random = BlobField()
class Election(TopLevelObject):
_ver = StringField(default='0.9')
_id = UUIDField()
workflow = EmbeddedObjectField(Workflow) # Once saved, we don't care what kind of workflow it is
name = StringField()
@ -222,6 +224,9 @@ class Election(TopLevelObject):
questions = EmbeddedObjectListField()
results = EmbeddedObjectListField(is_hashed=False)
is_voters_public = BooleanField(is_hashed=False, default=False)
is_votes_public = BooleanField(is_hashed=False, default=False)
def can_audit(self):
"""Can prepared votes be audited?"""
return False

View File

@ -225,6 +225,9 @@ class InternalMixingTrustee(MixingTrustee):
return True
class PSRElection(Election):
is_voters_public = BooleanField(is_hashed=False, default=True)
is_votes_public = BooleanField(is_hashed=False, default=True)
sk = EmbeddedObjectField(SEGPrivateKey, is_protected=True) # TODO: Threshold
public_key = EmbeddedObjectField(SEGPublicKey)

View File

@ -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
@ -255,7 +255,20 @@ def elections_batch():
@using_election
def election_api_json(election):
is_full = 'full' in flask.request.args
return flask.Response(EosObject.to_json(EosObject.serialise_and_wrap(election, None, SerialiseOptions(should_protect=True, for_hash=(not is_full), combine_related=True))), mimetype='application/json')
serialised = EosObject.serialise_and_wrap(election, None, SerialiseOptions(should_protect=True, for_hash=(not is_full), combine_related=True))
# Protect voters, votes if required
if not election.is_voters_public:
if 'voters' in serialised['value']:
del serialised['value']['voters']
if not election.is_votes_public:
if 'voters' in serialised['value']:
for voter in serialised['value']['voters']:
if 'votes' in voter['value']:
del voter['value']['votes']
return flask.Response(EosObject.to_json(serialised), mimetype='application/json')
@app.route('/election/<election_id>/view')
@using_election
@ -278,14 +291,20 @@ def election_view_questions(election):
@app.route('/election/<election_id>/view/ballots')
@using_election
def election_view_ballots(election):
return flask.render_template('election/view/ballots.html', election=election)
if election.is_voters_public or ('user' in flask.session and flask.session['user'].is_admin()):
return flask.render_template('election/view/ballots.html', election=election)
return flask.Response('Voters not public', 403)
@app.route('/election/<election_id>/voter/<voter_id>')
@using_election
def election_voter_view(election, voter_id):
voter_id = uuid.UUID(voter_id)
voter = next(voter for voter in election.voters if voter._id == voter_id)
return flask.render_template('election/voter/view.html', election=election, voter=voter)
if (election.is_voters_public and election.is_votes_public) or ('user' in flask.session and flask.session['user'].is_admin()):
voter_id = uuid.UUID(voter_id)
voter = next(voter for voter in election.voters if voter._id == voter_id)
return flask.render_template('election/voter/view.html', election=election, voter=voter)
return flask.Response('Voters not public', 403)
@app.route('/election/<election_id>/view/trustees')
@using_election

View File

@ -39,7 +39,11 @@
{% endblock %}
{% block buttons %}
<a href="{{ election_base_url }}view/ballots" class="ui right floated primary button">Finish</a>
{% if election.is_votes_public %}
<a href="{{ election_base_url }}view/ballots" class="ui right floated primary button">Finish</a>
{% else %}
<a href="{{ election_base_url }}view" class="ui right floated primary button">Finish</a>
{% endif %}
{% endblock %}
{% block after %}

View File

@ -1,6 +1,6 @@
{#
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
@ -19,5 +19,11 @@
{% block tabs %}
{{ tab('Overview', 'election_view') }}
{{ tab('Questions', 'election_view_questions') }}
{{ tab('Voters and ballots', 'election_view_ballots') }}
{% if election.is_voters_public or (session.user and session.user.is_admin()) %}
{% if election.is_votes_public or (session.user and session.user.is_admin()) %}
{{ tab('Voters and ballots', 'election_view_ballots') }}
{% else %}
{{ tab('Voters', 'election_view_ballots') }}
{% endif %}
{% endif %}
{% endblock %}

View File

@ -2,7 +2,7 @@
{#
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
@ -23,21 +23,27 @@
<thead>
<tr>
<th>Voter</th>
<th>Ballot fingerprint</th>
{% if election.is_votes_public or (session.user and session.user.is_admin()) %}
<th>Ballot fingerprint</th>
{% endif %}
</tr>
</thead>
<tbody>
{% for voter in election.voters %}
<tr>
<td class="selectable"><a href="{{ url_for('election_voter_view', election_id=election._id, voter_id=voter._id) }}">{{ voter.name }}</a></td>
{% set votes = voter.votes.get_all() %}
<td class="selectable"><a href="{{ url_for('election_voter_view', election_id=election._id, voter_id=voter._id) }}">
{% if votes|length > 0 %}
<span class="hash">{{ SHA256().update_obj(votes[-1].ballot).hash_as_b64(True) }}</span>
{% else %}
&nbsp;
{% endif %}
</a></td>
{% if election.is_votes_public or (session.user and session.user.is_admin()) %}
<td class="selectable"><a href="{{ url_for('election_voter_view', election_id=election._id, voter_id=voter._id) }}">{{ voter.name }}</a></td>
{% set votes = voter.votes.get_all() %}
<td class="selectable"><a href="{{ url_for('election_voter_view', election_id=election._id, voter_id=voter._id) }}">
{% if votes|length > 0 %}
<span class="hash">{{ SHA256().update_obj(votes[-1].ballot).hash_as_b64(True) }}</span>
{% else %}
&nbsp;
{% endif %}
</a></td>
{% else %}
<td>{{ voter.name }}</td>
{% endif %}
</tr>
{% endfor %}
</tbody>