Eos/eosweb/core/static/nunjucks/booth/cast.html

217 lines
8.1 KiB
HTML

{% extends templates['booth/base.html'] %}
{#
Eos - Verifiable elections
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
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 content %}
<div id="cast_prompt">
<p>Your vote has <span class="superem">not</span> yet been cast.{% if election.can_audit() %} Please make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>.{% endif %}</p>
<div class="ui negative message">
<p>Your vote has <span class="superem">not</span> yet been cast. Please follow the instructions to continue.</p>
</div>
<p>This election requires you to log in to vote. If you disconnected your internet connection earlier, you must now reconnect it before proceeding.</p>
{% if username %}
<p><span id="booth_logged_in_as">You are currently logged in as {{ username }}.</span> Please select an option from the list below if you would like to switch accounts. Otherwise, click ‘Cast ballot’ to continue.</p>
{% else %}
<p><span id="booth_logged_in_as">You are not currently logged in.</a> Please select an option from the list below to log in. Your ballot will be automatically cast once you have logged in.</p>
{% endif %}
<ul class="ui list">
{% for auth_method in auth_methods %}
<li><a href="/auth/{{ auth_method[0] }}/login" target="_blank" onclick="login(this);return false;">{{ auth_method[1] }}</a></li>
{% endfor %}
</ul>
<div class="ui hidden error message" id="error_invalid_id">
<i class="close icon"></i>
<div class="header">Error</div>
<p>The log in details you entered are not valid for this {{ election.kind }}. Please check your username and password and try again. If the issue persists, contact your {{ election.kind }} administrator.</p>
</div>
<div class="ui hidden error message" id="error_unknown">
<i class="close icon"></i>
<div class="header">Error</div>
<p>An unknown error occurred while attempting to cast your ballot. You may click the ‘Cast ballot’ button below to try again. If the issue persists, contact your {{ election.kind }} administrator.</p>
<p id="error_unknown_tech"></p>
</div>
</div>
<div class="ui basic segment" id="casting" style="display: none; min-height: 4em;">
<div class="ui active text loader">Casting your ballot. Please wait.</div>
</div>
{% endblock %}
{% block buttons %}
{% if is_cast %}
<a class="ui left floated button" href="{{ election_base_url }}booth">Reset</a>
<button class="ui right floated primary button" id="cast_button" onclick="castBallot();"{% if not username %} style="display: none;"{% endif %}>Cast ballot</button>
{% else %}
<button class="ui left floated button" onclick="prevTemplate(2);">Back</button>
<button class="ui right floated primary button" id="cast_button" onclick="stageBallot(castBallot);"{% if not username %} style="display: none;"{% endif %}>Cast ballot</button>
{% endif %}
{% endblock %}
{% block after %}
{% if election.can_audit() %}
<div class="ui tiny message" style="margin-top: 3em;">
<div class="header">Information for advanced users</div>
<p>Your full ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64() }}</span>.</p>
</div>
{% endif %}
<script>
$(".message .close").on("click", function() {
$(this).closest(".message").addClass("hidden");
});
function login(el) {
// Stage the vote for casting in case we change page
stageBallot(function(data) {
// Stage the next page in case we change page
stageNext("{{ election_base_url }}booth?cast", function(data) {
window.open(el.getAttribute("href"), "eos_login_window", "width=400,height=600");
});
});
}
function callback_complete(username) {
$("#cast_button").show();
$("#booth_logged_in_as").text("You are currently logged in as " + username + ".");
// Ballot was staged when we clicked the login button
castBallot();
return true;
}
function stageBallot(callback) {
// Prepare ballot
var deauditedBallot = booth.ballot.deaudit();
$.ajax({
url: "{{ election_base_url }}stage_ballot",
type: "POST",
data: eosjs.eos.core.objects.EosObject.to_json({
"ballot": eosjs.eos.core.objects.EosObject.serialise_and_wrap(deauditedBallot, null),
"fingerprint": booth.fingerprint || null
}),
contentType: "application/json",
dataType: "text",
async: false // so window.open happens in main thread
})
.done(function(data) {
callback(data);
})
.fail(function(xhr, status, err) {
if (xhr.responseText && xhr.responseText.length < 100) {
$("#error_unknown_tech").text("Technical details: " + err + " – " + xhr.responseText);
} else {
$("#error_unknown_tech").text("Technical details: " + err);
}
$("#error_unknown").removeClass("hidden");
$("#error_invalid_id").addClass("hidden");
console.error(xhr);
throw err;
});
}
function stageNext(url, callback) {
$.ajax({
url: "/auth/stage_next",
type: "POST",
data: url,
contentType: "text/plain",
dataType: "text",
async: false // so window.open happens in main thread
})
.done(function(data) {
callback(data);
})
.fail(function(xhr, status, err) {
if (xhr.responseText && xhr.responseText.length < 100) {
$("#error_unknown_tech").text("Technical details: " + err + " – " + xhr.responseText);
} else {
$("#error_unknown_tech").text("Technical details: " + err);
}
$("#error_unknown").removeClass("hidden");
$("#error_invalid_id").addClass("hidden");
console.error(xhr);
throw err;
});
}
function castBallot() {
$("#cast_prompt").hide();
$("#casting").show();
$.ajax({
url: "{{ election_base_url }}cast_ballot",
type: "POST",
dataType: "text"
})
.done(function(data) {
response = eosjs.eos.core.objects.EosObject.from_json(data);
booth.voter = eosjs.eos.core.objects.EosObject.deserialise_and_unwrap(response.voter);
booth.vote = eosjs.eos.core.objects.EosObject.deserialise_and_unwrap(response.vote);
// Clear plaintexts
booth.answers = null;
nextTemplate();
})
.fail(function(xhr, status, err) {
if (xhr.status === 403) { // Forbidden
$("#error_invalid_id").removeClass("hidden");
$("#error_unknown").addClass("hidden");
} else {
if (xhr.responseText && xhr.responseText.length < 100) {
$("#error_unknown_tech").text("Technical details: " + err + " – " + xhr.responseText);
} else {
$("#error_unknown_tech").text("Technical details: " + err);
}
$("#error_unknown").removeClass("hidden");
$("#error_invalid_id").addClass("hidden");
}
$("#casting").hide();
$("#cast_prompt").show();
console.error(xhr);
throw err;
});
}
{% if is_cast %}
castBallot();
{% endif %}
</script>
{% endblock %}
{% block help %}
<p>You are now ready to cast your ballot. If you disconnected your internet connection earlier, you must now reconnect it before proceeding.</p>
<p>Click the ‘OK’ button below to close this help screen, then click the blue ‘Cast ballot’ button. If there is no ‘Cast ballot’ button, select your login method from the list shown, and enter your voter details. These details may be found in the email or message instructing you to vote.</p>
<p>Once you have logged in, your vote will be automatically cast.</p>
<p>If you require further assistance, contact your election administrator.</p>
{% endblock %}