Email admins about task failures
This commit is contained in:
parent
e061ba7c3c
commit
3a44890803
@ -1,5 +1,5 @@
|
|||||||
# Eos - Verifiable elections
|
# Eos - Verifiable elections
|
||||||
# Copyright © 2017 RunasSudo (Yingtong Li)
|
# Copyright © 2017-18 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
|
||||||
@ -27,6 +27,8 @@ class Task(TopLevelObject):
|
|||||||
FAILED = -10
|
FAILED = -10
|
||||||
TIMEOUT = -20
|
TIMEOUT = -20
|
||||||
|
|
||||||
|
label = 'Unknown task'
|
||||||
|
|
||||||
_id = UUIDField()
|
_id = UUIDField()
|
||||||
run_strategy = EmbeddedObjectField()
|
run_strategy = EmbeddedObjectField()
|
||||||
|
|
||||||
@ -44,6 +46,12 @@ class Task(TopLevelObject):
|
|||||||
def _run(self):
|
def _run(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def complete(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def error(self):
|
||||||
|
pass
|
||||||
|
|
||||||
class DummyTask(Task):
|
class DummyTask(Task):
|
||||||
_db_name = Task._db_name
|
_db_name = Task._db_name
|
||||||
label = 'A dummy task'
|
label = 'A dummy task'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Eos - Verifiable elections
|
# Eos - Verifiable elections
|
||||||
# Copyright © 2017 RunasSudo (Yingtong Li)
|
# Copyright © 2017-18 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
|
||||||
@ -28,6 +28,8 @@ class DirectRunStrategy(RunStrategy):
|
|||||||
task.status = Task.Status.COMPLETE
|
task.status = Task.Status.COMPLETE
|
||||||
task.completed_at = DateTimeField.now()
|
task.completed_at = DateTimeField.now()
|
||||||
task.save()
|
task.save()
|
||||||
|
|
||||||
|
task.complete()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
task.status = Task.Status.FAILED
|
task.status = Task.Status.FAILED
|
||||||
task.completed_at = DateTimeField.now()
|
task.completed_at = DateTimeField.now()
|
||||||
@ -39,3 +41,5 @@ class DirectRunStrategy(RunStrategy):
|
|||||||
else:
|
else:
|
||||||
task.messages.append(repr(e))
|
task.messages.append(repr(e))
|
||||||
task.save()
|
task.save()
|
||||||
|
|
||||||
|
task.error()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Eos - Verifiable elections
|
# Eos - Verifiable elections
|
||||||
# Copyright © 2017 RunasSudo (Yingtong Li)
|
# Copyright © 2017-18 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
|
||||||
@ -28,6 +28,8 @@ from eos.psr.election import *
|
|||||||
from eos.psr.mixnet import *
|
from eos.psr.mixnet import *
|
||||||
from eos.psr.workflow import *
|
from eos.psr.workflow import *
|
||||||
|
|
||||||
|
from eosweb.core.tasks import *
|
||||||
|
|
||||||
import eos.core.hashing
|
import eos.core.hashing
|
||||||
import eosweb
|
import eosweb
|
||||||
|
|
||||||
@ -259,7 +261,7 @@ def election_admin_enter_task(election):
|
|||||||
if workflow_task.status != WorkflowTask.Status.READY:
|
if workflow_task.status != WorkflowTask.Status.READY:
|
||||||
return flask.Response('Task is not yet ready or has already exited', 409)
|
return flask.Response('Task is not yet ready or has already exited', 409)
|
||||||
|
|
||||||
task = WorkflowTaskEntryTask(
|
task = WorkflowTaskEntryWebTask(
|
||||||
election_id=election._id,
|
election_id=election._id,
|
||||||
workflow_task=workflow_task._name,
|
workflow_task=workflow_task._name,
|
||||||
status=Task.Status.READY,
|
status=Task.Status.READY,
|
||||||
@ -275,7 +277,7 @@ def election_admin_enter_task(election):
|
|||||||
def election_admin_schedule_task(election):
|
def election_admin_schedule_task(election):
|
||||||
workflow_task = election.workflow.get_task(flask.request.form['task_name'])
|
workflow_task = election.workflow.get_task(flask.request.form['task_name'])
|
||||||
|
|
||||||
task = WorkflowTaskEntryTask(
|
task = WorkflowTaskEntryWebTask(
|
||||||
election_id=election._id,
|
election_id=election._id,
|
||||||
workflow_task=workflow_task._name,
|
workflow_task=workflow_task._name,
|
||||||
run_at=DateTimeField().deserialise(flask.request.form['datetime']),
|
run_at=DateTimeField().deserialise(flask.request.form['datetime']),
|
||||||
@ -387,12 +389,6 @@ def email_authenticate():
|
|||||||
|
|
||||||
return flask.redirect(flask.url_for('login_complete'))
|
return flask.redirect(flask.url_for('login_complete'))
|
||||||
|
|
||||||
@app.route('/email')
|
|
||||||
def tmp():
|
|
||||||
import sass
|
|
||||||
css = sass.compile(string=flask.render_template('email/base.scss'))
|
|
||||||
return flask.render_template('email/base.html', title='Hello World', text='<p>Dear voter,</p><p>You are registered to vote in the election Election Name.</p>', css=css)
|
|
||||||
|
|
||||||
# === Apps ===
|
# === Apps ===
|
||||||
|
|
||||||
for app_name in app.config['APPS']:
|
for app_name in app.config['APPS']:
|
||||||
|
60
eosweb/core/tasks.py
Normal file
60
eosweb/core/tasks.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# Eos - Verifiable elections
|
||||||
|
# Copyright © 2017-18 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/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import premailer
|
||||||
|
import sass
|
||||||
|
|
||||||
|
import flask
|
||||||
|
import flask_mail
|
||||||
|
|
||||||
|
from eos.core.tasks import *
|
||||||
|
from eos.base.election import *
|
||||||
|
|
||||||
|
class WebTask(Task):
|
||||||
|
def error(self):
|
||||||
|
import eosweb
|
||||||
|
|
||||||
|
# Prepare email
|
||||||
|
title = 'Task failed: {}'.format(self.label)
|
||||||
|
|
||||||
|
css = sass.compile(string=flask.render_template('email/base.scss'))
|
||||||
|
html = flask.render_template(
|
||||||
|
'email/base.html',
|
||||||
|
title=title,
|
||||||
|
css=css,
|
||||||
|
text='<p>The task <i>{}</i> failed execution. The output was:</p><pre>{}</pre>'.format(self.label, '\n'.join(self.messages))
|
||||||
|
)
|
||||||
|
html = premailer.Premailer(html).transform()
|
||||||
|
|
||||||
|
body = flask.render_template(
|
||||||
|
'email/base.txt',
|
||||||
|
title=title,
|
||||||
|
text='The task "{}" failed execution. The output was:\n\n{}'.format(self.label, '\n'.join(self.messages))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Send email
|
||||||
|
mail = flask_mail.Mail(eosweb.app)
|
||||||
|
msg = flask_mail.Message(
|
||||||
|
title,
|
||||||
|
recipients=[admin.email for admin in eosweb.app.config['ADMINS'] if isinstance(admin, EmailUser)],
|
||||||
|
body=body,
|
||||||
|
html=html
|
||||||
|
)
|
||||||
|
mail.send(msg)
|
||||||
|
|
||||||
|
class WorkflowTaskEntryWebTask(WorkflowTaskEntryTask, WebTask):
|
||||||
|
pass
|
@ -1,6 +1,6 @@
|
|||||||
{#
|
{#
|
||||||
Eos - Verifiable elections
|
Eos - Verifiable elections
|
||||||
Copyright © 2017 RunasSudo (Yingtong Li)
|
Copyright © 2017-18 RunasSudo (Yingtong Li)
|
||||||
|
|
||||||
This file adapted from https://github.com/leemunroe/responsive-html-email-template, licensed under the MIT licence.
|
This file adapted from https://github.com/leemunroe/responsive-html-email-template, licensed under the MIT licence.
|
||||||
|
|
||||||
@ -25,7 +25,7 @@
|
|||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
<title>{{ title }}</title>
|
<title>{{ title }}</title>
|
||||||
<style>
|
<style>
|
||||||
{{ css }}
|
{{ css|safe }}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="">
|
<body class="">
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{#
|
{#
|
||||||
Eos - Verifiable elections
|
Eos - Verifiable elections
|
||||||
Copyright © 2017 RunasSudo (Yingtong Li)
|
Copyright © 2017-18 RunasSudo (Yingtong Li)
|
||||||
|
|
||||||
This file adapted from https://github.com/leemunroe/responsive-html-email-template, licensed under the MIT licence.
|
This file adapted from https://github.com/leemunroe/responsive-html-email-template, licensed under the MIT licence.
|
||||||
|
|
||||||
|
26
eosweb/core/templates/email/base.txt
Normal file
26
eosweb/core/templates/email/base.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{#
|
||||||
|
Eos - Verifiable elections
|
||||||
|
Copyright © 2017-18 RunasSudo (Yingtong Li)
|
||||||
|
|
||||||
|
This file adapted from https://github.com/leemunroe/responsive-html-email-template, licensed under the MIT licence.
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
#}
|
||||||
|
|
||||||
|
{{ text|safe }}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Eos Voting for {{ eosweb.app.config['ORG_NAME'] }}
|
||||||
|
{{ eosweb.app.config['BASE_URI'] }}
|
@ -32,9 +32,9 @@ DB_NAME = 'eos'
|
|||||||
|
|
||||||
# Email
|
# Email
|
||||||
|
|
||||||
SMTP_HOST, SMTP_PORT = 'localhost', 25
|
MAIL_SERVER, MAIL_PORT = 'localhost', 25
|
||||||
SMTP_USER, SMTP_PASS = None, None
|
MAIL_USERNAME, MAIL_PASSWORD = None, None
|
||||||
SMTP_FROM = 'eos@localhost'
|
MAIL_DEFAULT_SENDER = 'eos@localhost'
|
||||||
|
|
||||||
# Reddit
|
# Reddit
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
coverage==4.4.1
|
coverage==4.4.1
|
||||||
Flask==0.12.2
|
Flask==0.12.2
|
||||||
|
Flask-Mail==0.9.1
|
||||||
Flask-OAuthlib==0.9.4
|
Flask-OAuthlib==0.9.4
|
||||||
gunicorn==19.7.1
|
gunicorn==19.7.1
|
||||||
libsass==0.13.4
|
libsass==0.13.4
|
||||||
|
premailer==3.1.1
|
||||||
psycopg2==2.7.3.2
|
psycopg2==2.7.3.2
|
||||||
PyExecJS==1.4.1
|
PyExecJS==1.4.1
|
||||||
pymongo==3.5.1
|
pymongo==3.5.1
|
||||||
|
Loading…
Reference in New Issue
Block a user