From 6ebf83ed962cc5e1d12a9eb2b108cc9d844e28d4 Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Wed, 22 Nov 2017 23:23:24 +1100 Subject: [PATCH] Get started on a basic web UI --- eos/core/objects/__init__.py | 8 ++ eosweb/__init__.py | 4 +- eosweb/{eosweb.py => core/__init__.py} | 16 ---- eosweb/{ => core}/bower.json | 0 eosweb/core/main.py | 92 +++++++++++++++++++ eosweb/core/static/css/main.css | 22 +++++ eosweb/{ => core}/templates/base.html | 0 eosweb/core/templates/election/base.html | 56 +++++++++++ eosweb/core/templates/election/view.html | 51 ++++++++++ eosweb/{ => core}/templates/index.html | 7 +- .../{ => core}/templates/semantic_base.html | 0 11 files changed, 237 insertions(+), 19 deletions(-) rename eosweb/{eosweb.py => core/__init__.py} (70%) rename eosweb/{ => core}/bower.json (100%) create mode 100644 eosweb/core/main.py create mode 100644 eosweb/core/static/css/main.css rename eosweb/{ => core}/templates/base.html (100%) create mode 100644 eosweb/core/templates/election/base.html create mode 100644 eosweb/core/templates/election/view.html rename eosweb/{ => core}/templates/index.html (76%) rename eosweb/{ => core}/templates/semantic_base.html (100%) diff --git a/eos/core/objects/__init__.py b/eos/core/objects/__init__.py index 0d102b2..1dad605 100644 --- a/eos/core/objects/__init__.py +++ b/eos/core/objects/__init__.py @@ -307,6 +307,14 @@ class TopLevelObject(DocumentObject): def save(self): #res = db[self._name].replace_one({'_id': self.serialise()['_id']}, self.serialise(), upsert=True) res = db[self._db_name].replace_one({'_id': self._fields['_id'].serialise(self._id)}, EosObject.serialise_and_wrap(self), upsert=True) + + @classmethod + def get_all(cls): + return [EosObject.deserialise_and_unwrap(x) for x in db[cls._db_name].find()] + + @classmethod + def get_by_id(cls, _id): + return EosObject.deserialise_and_unwrap(db[cls._db_name].find_one(_id)) class EmbeddedObject(DocumentObject): pass diff --git a/eosweb/__init__.py b/eosweb/__init__.py index c9e4d20..8c46f98 100644 --- a/eosweb/__init__.py +++ b/eosweb/__init__.py @@ -14,5 +14,5 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -# Allow FLASK_APP=eosweb instead of eosweb.eosweb -from .eosweb import app +# Allow FLASK_APP=eosweb instead of eosweb.core.main +from .core.main import app diff --git a/eosweb/eosweb.py b/eosweb/core/__init__.py similarity index 70% rename from eosweb/eosweb.py rename to eosweb/core/__init__.py index b37bcc5..776ecb2 100644 --- a/eosweb/eosweb.py +++ b/eosweb/core/__init__.py @@ -13,19 +13,3 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . - -import click -import flask - -app = flask.Flask(__name__) - -@app.cli.command('test') -@click.option('--prefix', default=None) -@click.option('--lang', default=None) -def run_tests(prefix, lang): - import eos.tests - eos.tests.run_tests(prefix, lang) - -@app.route('/') -def index(): - return flask.render_template('index.html') diff --git a/eosweb/bower.json b/eosweb/core/bower.json similarity index 100% rename from eosweb/bower.json rename to eosweb/core/bower.json diff --git a/eosweb/core/main.py b/eosweb/core/main.py new file mode 100644 index 0000000..cc9b5eb --- /dev/null +++ b/eosweb/core/main.py @@ -0,0 +1,92 @@ +# Eos - Verifiable elections +# Copyright © 2017 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import click +import flask + +from eos.base.election import * +from eos.psr.crypto import * +from eos.psr.election import * +from eos.psr.mixnet import * +from eos.psr.workflow import * + +import eos.core.hashing + +app = flask.Flask(__name__) + +@app.cli.command('test') +@click.option('--prefix', default=None) +@click.option('--lang', default=None) +def run_tests(prefix, lang): + import eos.tests + eos.tests.run_tests(prefix, lang) + +# TODO: Will remove this once we have a web UI +@app.cli.command('drop_db_and_setup') +def setup_test_election(): + # DANGER! + client.drop_database('test') + + # Set up election + election = PSRElection() + election.workflow = PSRWorkflow() + + # Set election details + election.name = 'Test Election' + + for i in range(3): + voter = Voter() + election.voters.append(voter) + + election.mixing_trustees.append(MixingTrustee()) + + election.sk = EGPrivateKey.generate() + election.public_key = election.sk.public_key + + question = ApprovalQuestion(prompt='President', choices=['John Smith', 'Joe Bloggs', 'John Q. Public']) + election.questions.append(question) + + question = ApprovalQuestion(prompt='Chairman', choices=['John Doe', 'Andrew Citizen']) + election.questions.append(question) + + election.save() + + # Freeze election + election.workflow.get_task('eos.base.workflow.TaskConfigureElection').enter() + + # Open voting + election.workflow.get_task('eos.base.workflow.TaskOpenVoting').enter() + + election.save() + +@app.context_processor +def inject_globals(): + return {'eos': eos, 'SHA256': eos.core.hashing.SHA256} + +@app.route('/') +def index(): + return flask.render_template('index.html') + +def using_election(func): + def wrapped(election_id): + election = Election.get_by_id(election_id) + return func(election) + return wrapped + +@app.route('/election//view') +@using_election +def election_view(election): + return flask.render_template('election/view.html', election=election) diff --git a/eosweb/core/static/css/main.css b/eosweb/core/static/css/main.css new file mode 100644 index 0000000..1d6fd67 --- /dev/null +++ b/eosweb/core/static/css/main.css @@ -0,0 +1,22 @@ +/* + Eos - Verifiable elections + Copyright © 2017 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +.hash { + font-family: monospace; + word-wrap: break-word; +} diff --git a/eosweb/templates/base.html b/eosweb/core/templates/base.html similarity index 100% rename from eosweb/templates/base.html rename to eosweb/core/templates/base.html diff --git a/eosweb/core/templates/election/base.html b/eosweb/core/templates/election/base.html new file mode 100644 index 0000000..f0d0922 --- /dev/null +++ b/eosweb/core/templates/election/base.html @@ -0,0 +1,56 @@ +{% extends 'base.html' %} + +{# + Eos - Verifiable elections + Copyright © 2017 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +#} + +{% block title %}{{ election.name }}{% endblock %} + +{% block content %} +

{{ election.name }}

+ +

Election fingerprint: {{ SHA256().update_obj(election).hash_as_b64() }}

+ + +
+ {% block electioncontent %} + {% endblock %} +
+{% endblock %} + +{% block basecontent %} + {{ super() }} + + +{% endblock %} diff --git a/eosweb/core/templates/election/view.html b/eosweb/core/templates/election/view.html new file mode 100644 index 0000000..74b8668 --- /dev/null +++ b/eosweb/core/templates/election/view.html @@ -0,0 +1,51 @@ +{% extends 'election/base.html' %} + +{# + Eos - Verifiable elections + Copyright © 2017 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +#} + +{% set Status = eos.base.workflow.WorkflowTask.Status %} + +{% block electioncontent %} + {% if election.workflow.get_task('eos.base.workflow.TaskConfigureElection').status == Status.EXITED %} + {% if election.workflow.get_task('eos.base.workflow.TaskOpenVoting').status == Status.EXITED %} +

Click here to vote in this election

+ {% else %} +

+ {% endif %} + +

+ Voting in this election + {% if election.workflow.get_task('eos.base.workflow.TaskOpenVoting').status == Status.EXITED %} + opened + {% else %} + is scheduled to open + {% endif %} + at the administrators' discretion, and + {% if election.workflow.get_task('eos.base.workflow.TaskCloseVoting').status == Status.EXITED %} + closed + {% else %} + is scheduled to close + {% endif %} + at the administrators' discretion. +

+ {% else %} +

+ +

The administrator of this election has not yet finished setting the election parameters. The details of the election may change at any time.

+ {% endif %} +{% endblock %} diff --git a/eosweb/templates/index.html b/eosweb/core/templates/index.html similarity index 76% rename from eosweb/templates/index.html rename to eosweb/core/templates/index.html index 323de68..63d8ab3 100644 --- a/eosweb/templates/index.html +++ b/eosweb/core/templates/index.html @@ -21,5 +21,10 @@ {% block title %}Home{% endblock %} {% block content %} - Hello World! +

Please choose an election from the list below:

+
    + {% for election in eos.base.election.Election.get_all() %} +
  • {{ election.name }}
  • + {% endfor %} +
{% endblock %} diff --git a/eosweb/templates/semantic_base.html b/eosweb/core/templates/semantic_base.html similarity index 100% rename from eosweb/templates/semantic_base.html rename to eosweb/core/templates/semantic_base.html