Basic administrator view

This commit is contained in:
RunasSudo 2017-12-07 15:03:11 +10:30
parent 5918cde53b
commit 95e6a56f81
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
13 changed files with 82 additions and 16 deletions

View File

@ -54,7 +54,16 @@ class Voter(EmbeddedObject):
votes = EmbeddedObjectListField()
class User(EmbeddedObject):
pass
admins = []
def matched_by(self, other):
return self == other
def is_admin(self):
for admin in User.admins:
if admin.matched_by(self):
return True
return False
def generate_password():
if is_python:

View File

@ -117,17 +117,21 @@ class Workflow(EmbeddedObject):
# ==============
class TaskConfigureElection(WorkflowTask):
label = 'Configure the election and freeze the election'
#def on_enter(self):
# self.status = WorkflowTask.Status.COMPLETE
pass
class TaskOpenVoting(WorkflowTask):
label = 'Open voting'
depends_on = ['eos.base.workflow.TaskConfigureElection']
class TaskCloseVoting(WorkflowTask):
label = 'Close voting'
depends_on = ['eos.base.workflow.TaskOpenVoting']
class TaskDecryptVotes(WorkflowTask):
label = 'Decrypt the votes'
depends_on = ['eos.base.workflow.TaskCloseVoting']
def on_enter(self):
@ -148,6 +152,7 @@ class TaskDecryptVotes(WorkflowTask):
self.exit()
class TaskReleaseResults(WorkflowTask):
label = 'Release the results'
depends_on = ['eos.base.workflow.TaskDecryptVotes']
# Concrete workflows

View File

@ -22,6 +22,7 @@ import eos.base.workflow
# ==============
class TaskMixVotes(WorkflowTask):
label = 'Mix the votes'
depends_on = ['eos.base.workflow.TaskCloseVoting']
def on_enter(self):
@ -40,6 +41,7 @@ class TaskMixVotes(WorkflowTask):
self.exit()
class TaskProveMixes(WorkflowTask):
label = 'Prove the mixes'
depends_on = ['eos.psr.workflow.TaskMixVotes']
def on_enter(self):

View File

@ -33,6 +33,7 @@ import functools
import importlib
import json
import os
import subprocess
app = flask.Flask(__name__, static_folder=None)
@ -50,6 +51,9 @@ if 'EOSWEB_SETTINGS' in os.environ:
# Connect to database
db_connect(app.config['DB_NAME'], app.config['DB_URI'], app.config['DB_TYPE'])
# Set configs
User.admins = app.config['ADMINS']
# Make Flask's serialisation, e.g. for sessions, EosObject aware
class EosObjectJSONEncoder(flask.json.JSONEncoder):
def default(self, obj):
@ -126,14 +130,6 @@ def setup_test_election():
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.cli.command('close_election')
@click.option('--electionid', default=None)
@ -194,6 +190,15 @@ def using_election(func):
return func(election)
return wrapped
def election_admin(func):
@functools.wraps(func)
def wrapped(election):
if 'user' in flask.session and flask.session['user'].is_admin():
return func(election)
else:
return flask.Response('Administrator credentials required', 403)
return wrapped
@app.route('/election/<election_id>/')
@using_election
def election_api_json(election):
@ -202,7 +207,7 @@ def election_api_json(election):
@app.route('/election/<election_id>/view')
@using_election
def election_view(election):
return flask.render_template('election/view.html', election=election)
return flask.render_template('election/view/view.html', election=election)
@app.route('/election/<election_id>/booth')
@using_election
@ -210,22 +215,28 @@ def election_booth(election):
selection_model_view_map = EosObject.to_json({key._name: val for key, val in model_view_map.items()}) # ewww
auth_methods = EosObject.to_json(app.config['AUTH_METHODS'])
return flask.render_template('election/booth.html', election=election, selection_model_view_map=selection_model_view_map, auth_methods=auth_methods)
return flask.render_template('election/view/booth.html', election=election, selection_model_view_map=selection_model_view_map, auth_methods=auth_methods)
@app.route('/election/<election_id>/view/questions')
@using_election
def election_view_questions(election):
return flask.render_template('election/questions.html', election=election)
return flask.render_template('election/view/questions.html', election=election)
@app.route('/election/<election_id>/view/ballots')
@using_election
def election_view_ballots(election):
return flask.render_template('election/ballots.html', election=election)
return flask.render_template('election/view/ballots.html', election=election)
@app.route('/election/<election_id>/view/trustees')
@using_election
def election_view_trustees(election):
return flask.render_template('election/trustees.html', election=election)
return flask.render_template('election/view/trustees.html', election=election)
@app.route('/election/<election_id>/admin')
@using_election
@election_admin
def election_admin_summary(election):
return flask.render_template('election/admin/admin.html', election=election)
@app.route('/election/<election_id>/cast_ballot', methods=['POST'])
@using_election

View File

@ -29,7 +29,7 @@
<a href="https://github.com/RunasSudo/Eos" class="item">Source Code</a>
{% if session.user %}
<div class="ui simple dropdown item right">
{{ session.user.name }} <i class="dropdown icon"></i>
<i class="{% if session.user.is_admin() %}legal{% else %}user circle{% endif %} icon"></i> {{ session.user.name }} <i class="dropdown icon"></i>
<div class="menu">
<a href="{{ url_for('logout') }}?next={{ request.full_path|urlencode }}" class="item">Log out</a>
</div>

View File

@ -0,0 +1,31 @@
{% 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 <http://www.gnu.org/licenses/>.
#}
{% block electioncontent %}
<h2>Next tasks</h2>
<ul>
{% for task in election.workflow.tasks %}
{% if task.status == eos.base.workflow.WorkflowTask.Status.READY %}
<li>{{ task.label }}</li>
{% endif %}
{% endfor %}
</ul>
{% endblock %}

View File

@ -31,6 +31,9 @@
<div class="ui secondary pointing menu" id="election-tab-menu">
{% include eosweb.core.main.model_view_map[election.__class__]['tabs'] %}
{% if session.user and session.user.is_admin() %}
<a href="{{ url_for('election_admin_summary', election_id=election._id) }}" class="election-tab-ajax item{% if request.endpoint == 'election_admin' %} active{% endif %} right"><i class="configure icon"></i> Administrate this election</a>
{% endif %}
</div>
<div class="ui container" id="election-tab-content">
{% block electioncontent %}

View File

@ -9,6 +9,11 @@ AUTH_METHODS = [
('reddit', 'Reddit')
]
import eos.redditauth.election
ADMINS = [
#eos.redditauth.election.RedditUser(username='xxxxxxxx')
]
# MongoDB
DB_TYPE = 'mongodb'