Implement IP and fingerprint logging
This commit is contained in:
parent
d264159237
commit
5740f33b7d
@ -47,9 +47,14 @@ class Ballot(EmbeddedObject):
|
||||
return Ballot(encrypted_answers=encrypted_answers_deaudit, election_id=self.election_id, election_hash=self.election_hash)
|
||||
|
||||
class Vote(EmbeddedObject):
|
||||
_ver = StringField(default='0.4')
|
||||
|
||||
ballot = EmbeddedObjectField()
|
||||
cast_at = DateTimeField()
|
||||
|
||||
cast_ip = StringField(is_protected=True)
|
||||
cast_fingerprint = BlobField(is_protected=True)
|
||||
|
||||
class Voter(EmbeddedObject):
|
||||
_id = UUIDField()
|
||||
votes = EmbeddedObjectListField()
|
||||
|
@ -84,6 +84,7 @@ DictField = PrimitiveField
|
||||
IntField = PrimitiveField
|
||||
StringField = PrimitiveField
|
||||
BooleanField = PrimitiveField
|
||||
BlobField = PrimitiveField
|
||||
|
||||
class EmbeddedObjectField(Field):
|
||||
def __init__(self, object_type=None, *args, **kwargs):
|
||||
|
@ -18,6 +18,7 @@
|
||||
"dependencies": {
|
||||
"semantic": "semantic-ui#^2.2.13",
|
||||
"nunjucks": "^3.0.1",
|
||||
"dragula.js": "dragula#^3.7.2"
|
||||
"dragula.js": "dragula#^3.7.2",
|
||||
"fingerprintjs2": "^1.5.1"
|
||||
}
|
||||
}
|
||||
|
@ -252,6 +252,16 @@ def election_api_cast_vote(election):
|
||||
# Cast the vote
|
||||
ballot = EosObject.deserialise_and_unwrap(data['ballot'])
|
||||
vote = Vote(ballot=ballot, cast_at=DateTimeField.now())
|
||||
|
||||
# Store data
|
||||
if app.config['CAST_FINGERPRINT']:
|
||||
vote.cast_fingerprint = data['fingerprint']
|
||||
if app.config['CAST_IP']:
|
||||
if os.path.exists('/app/.heroku'):
|
||||
vote.cast_ip = flask.request.headers['X-Forwarded-For'].split(',')[-1]
|
||||
else:
|
||||
vote.cast_ip = flask.request.remote_addr
|
||||
|
||||
voter.votes.append(vote)
|
||||
|
||||
election.save()
|
||||
|
@ -19,7 +19,7 @@
|
||||
window = self; // Workaround for libraries
|
||||
isLibrariesLoaded = false;
|
||||
|
||||
function generateEncryptedVote(election, answers) {
|
||||
function generateEncryptedVote(election, answers, should_do_fingerprint) {
|
||||
encrypted_answers = [];
|
||||
for (var q_num = 0; q_num < answers.length; q_num++) {
|
||||
answer_json = answers[q_num];
|
||||
@ -28,7 +28,9 @@ function generateEncryptedVote(election, answers) {
|
||||
encrypted_answers.push(eosjs.eos.core.objects.__all__.EosObject.serialise_and_wrap(encrypted_answer, null));
|
||||
}
|
||||
|
||||
postMessage(encrypted_answers);
|
||||
postMessage({
|
||||
encrypted_answers: encrypted_answers
|
||||
});
|
||||
}
|
||||
|
||||
onmessage = function(msg) {
|
||||
|
@ -90,7 +90,8 @@
|
||||
url: "{{ election_base_url }}cast_ballot",
|
||||
type: "POST",
|
||||
data: eosjs.eos.core.objects.__all__.EosObject.to_json({
|
||||
"ballot": eosjs.eos.core.objects.__all__.EosObject.serialise_and_wrap(booth.ballot, null)
|
||||
"ballot": eosjs.eos.core.objects.__all__.EosObject.serialise_and_wrap(booth.ballot, null),
|
||||
"fingerprint": booth.fingerprint || null
|
||||
}),
|
||||
contentType: "application/json",
|
||||
dataType: "text"
|
||||
|
@ -27,7 +27,7 @@
|
||||
}
|
||||
|
||||
encryptedAnswers = [];
|
||||
for (var encrypted_answer_json of msg.data) {
|
||||
for (var encrypted_answer_json of msg.data.encrypted_answers) {
|
||||
encryptedAnswers.push(eosjs.eos.core.objects.__all__.EosObject.deserialise_and_unwrap(encrypted_answer_json, null));
|
||||
}
|
||||
|
||||
@ -37,7 +37,18 @@
|
||||
booth.ballot.election_id = election._id;
|
||||
booth.ballot.election_hash = eosjs.eos.core.hashing.__all__.SHA256().update_obj(election).hash_as_b64();
|
||||
|
||||
nextTemplate();
|
||||
if (should_do_fingerprint) {
|
||||
// String.prototype.join confuses fingerprintjs2
|
||||
var strjoin = String.prototype.join;
|
||||
String.prototype.join = undefined;
|
||||
new Fingerprint2().get(function(result, components) {
|
||||
String.prototype.join = strjoin;
|
||||
booth.fingerprint = components;
|
||||
nextTemplate();
|
||||
});
|
||||
} else {
|
||||
nextTemplate();
|
||||
}
|
||||
} catch (err) {
|
||||
boothError(err);
|
||||
throw err;
|
||||
@ -52,7 +63,7 @@
|
||||
"action": "generateEncryptedVote",
|
||||
"static_base_url": "{{ static_base_url }}",
|
||||
"election": eosjs.eos.core.objects.__all__.EosObject.serialise_and_wrap(election, null),
|
||||
"answers": booth.answers,
|
||||
"answers": booth.answers
|
||||
});
|
||||
} catch (err) {
|
||||
boothError(err);
|
||||
|
@ -38,6 +38,9 @@
|
||||
<script src="{{ url_for('static', filename='js/eosjs.js') }}"></script>
|
||||
|
||||
<script src="{{ url_for('static', filename='bower_components/dragula.js/dist/dragula.min.js') }}"></script>
|
||||
{% if eosweb.app.config['CAST_FINGERPRINT'] %}
|
||||
<script src="{{ url_for('static', filename='bower_components/fingerprintjs2/dist/fingerprint2.min.js') }}"></script>
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
var templates = {};
|
||||
@ -50,12 +53,14 @@
|
||||
|
||||
var username = {% if session.user %}"{{ session.user.name }}"{% else %}null{% endif %};
|
||||
var auth_methods = {{ auth_methods|safe }};
|
||||
var should_do_fingerprint = {{ 'true' if eosweb.app.config['CAST_FINGERPRINT'] else 'false' }};
|
||||
|
||||
function resetBooth() {
|
||||
booth = {
|
||||
"questionNum": 0,
|
||||
"answers": [],
|
||||
"q_state": []
|
||||
"q_state": [],
|
||||
"fingerprint": []
|
||||
};
|
||||
}
|
||||
resetBooth();
|
||||
|
@ -37,3 +37,8 @@ SMTP_FROM = 'eos@localhost'
|
||||
REDDIT_OAUTH_CLIENT_ID = 'xxxxxxxxxxxxxx'
|
||||
REDDIT_OAUTH_CLIENT_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx'
|
||||
REDDIT_USER_AGENT = 'Application Title by /u/Your_Username'
|
||||
|
||||
# Security
|
||||
|
||||
CAST_IP = True
|
||||
CAST_FINGERPRINT = False
|
||||
|
Loading…
Reference in New Issue
Block a user