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

View File

@ -225,6 +225,9 @@ class InternalMixingTrustee(MixingTrustee):
return True return True
class PSRElection(Election): 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 sk = EmbeddedObjectField(SEGPrivateKey, is_protected=True) # TODO: Threshold
public_key = EmbeddedObjectField(SEGPublicKey) public_key = EmbeddedObjectField(SEGPublicKey)

View File

@ -1,5 +1,5 @@
# Eos - Verifiable elections # 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 # 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 # it under the terms of the GNU Affero General Public License as published by
@ -255,7 +255,20 @@ def elections_batch():
@using_election @using_election
def election_api_json(election): def election_api_json(election):
is_full = 'full' in flask.request.args 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') @app.route('/election/<election_id>/view')
@using_election @using_election
@ -278,15 +291,21 @@ def election_view_questions(election):
@app.route('/election/<election_id>/view/ballots') @app.route('/election/<election_id>/view/ballots')
@using_election @using_election
def election_view_ballots(election): def election_view_ballots(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.render_template('election/view/ballots.html', election=election)
return flask.Response('Voters not public', 403)
@app.route('/election/<election_id>/voter/<voter_id>') @app.route('/election/<election_id>/voter/<voter_id>')
@using_election @using_election
def election_voter_view(election, voter_id): def election_voter_view(election, voter_id):
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_id = uuid.UUID(voter_id)
voter = next(voter for voter in election.voters if voter._id == 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.render_template('election/voter/view.html', election=election, voter=voter)
return flask.Response('Voters not public', 403)
@app.route('/election/<election_id>/view/trustees') @app.route('/election/<election_id>/view/trustees')
@using_election @using_election
def election_view_trustees(election): def election_view_trustees(election):

View File

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

View File

@ -1,6 +1,6 @@
{# {#
Eos - Verifiable elections 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 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 it under the terms of the GNU Affero General Public License as published by
@ -19,5 +19,11 @@
{% block tabs %} {% block tabs %}
{{ tab('Overview', 'election_view') }} {{ tab('Overview', 'election_view') }}
{{ tab('Questions', 'election_view_questions') }} {{ tab('Questions', 'election_view_questions') }}
{% 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') }} {{ tab('Voters and ballots', 'election_view_ballots') }}
{% else %}
{{ tab('Voters', 'election_view_ballots') }}
{% endif %}
{% endif %}
{% endblock %} {% endblock %}

View File

@ -2,7 +2,7 @@
{# {#
Eos - Verifiable elections 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 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 it under the terms of the GNU Affero General Public License as published by
@ -23,12 +23,15 @@
<thead> <thead>
<tr> <tr>
<th>Voter</th> <th>Voter</th>
{% if election.is_votes_public or (session.user and session.user.is_admin()) %}
<th>Ballot fingerprint</th> <th>Ballot fingerprint</th>
{% endif %}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for voter in election.voters %} {% for voter in election.voters %}
<tr> <tr>
{% 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> <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() %} {% set votes = voter.votes.get_all() %}
<td class="selectable"><a href="{{ url_for('election_voter_view', election_id=election._id, voter_id=voter._id) }}"> <td class="selectable"><a href="{{ url_for('election_voter_view', election_id=election._id, voter_id=voter._id) }}">
@ -38,6 +41,9 @@
&nbsp; &nbsp;
{% endif %} {% endif %}
</a></td> </a></td>
{% else %}
<td>{{ voter.name }}</td>
{% endif %}
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>