Initial commit of DEMOS2 with the upgraded 'Create Event' UI. However, there is no input validation currently
This commit is contained in:
commit
7084bd1b16
155 changed files with 8102 additions and 0 deletions
1
static/js/.gitignore
vendored
Executable file
1
static/js/.gitignore
vendored
Executable file
|
@ -0,0 +1 @@
|
|||
core
|
237
static/js/create-event-poll.js
Executable file
237
static/js/create-event-poll.js
Executable file
|
@ -0,0 +1,237 @@
|
|||
// File handling
|
||||
|
||||
function processFileChange(event) {
|
||||
var files = event.target.files;
|
||||
|
||||
// By parsing the file we ensure that it's valid CSV at the client side. Papa parse
|
||||
// also allows us to aggregate emails from multiple rows in a file.
|
||||
if(files !== undefined
|
||||
&& files[0] !== undefined) {
|
||||
Papa.parse(files[0], {
|
||||
complete: function(results) {
|
||||
var errors = results.errors;
|
||||
|
||||
if(errors.length === 0) {
|
||||
var data = results.data;
|
||||
var numRows = data.length;
|
||||
var totalNumEmails = 0;
|
||||
var emails = [];
|
||||
|
||||
if(numRows > 1) {
|
||||
for(var i = 0; i < numRows; i++) {
|
||||
var numEmails = data[i].length;
|
||||
totalNumEmails += numEmails;
|
||||
|
||||
for(var j = 0; j < numEmails; j++) {
|
||||
emails.push(data[i][j]);
|
||||
}
|
||||
}
|
||||
} else if(numRows === 1) {
|
||||
totalNumEmails = data[0].length;
|
||||
|
||||
for(var i = 0; i < totalNumEmails; i++) {
|
||||
emails.push(data[0][i]);
|
||||
}
|
||||
}
|
||||
|
||||
$('#result').removeClass("hidden").html(
|
||||
totalNumEmails + " email(s) have been successfully uploaded.");
|
||||
|
||||
$('#voters-list-input').html(emails.join(', '));
|
||||
} else {
|
||||
// There were errors, so inform the user
|
||||
$('#result')
|
||||
.removeClass("hidden")
|
||||
.html("Error reading uploaded file! Check the format and try again")
|
||||
.addClass("errorText");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('files').addEventListener('change', processFileChange, false);
|
||||
|
||||
// reCAPTCHA
|
||||
|
||||
function recaptchaCallback(){
|
||||
$('#submit-event-create').removeAttr('disabled');
|
||||
}
|
||||
|
||||
// Slug field.
|
||||
|
||||
function slugify(value) {
|
||||
return value.toString()
|
||||
.replace(/[^\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\w\s-]+/g, '')
|
||||
.replace(/^[-\s]+/, '')
|
||||
.replace(/[-\s]+$/, '')
|
||||
.replace(/[-\s]+/g, '-')
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
$('#name-input').on('input', function (e) {
|
||||
var slugField = $('#identifier-input');
|
||||
if (!slugField.data('changed')) {
|
||||
var name = $(this).val();
|
||||
var maxLength = parseInt(slugField.attr('maxlength'));
|
||||
var slug = slugify(name).substring(0, maxLength);
|
||||
slugField.val(slug);
|
||||
slugField.trigger('input');
|
||||
}
|
||||
});
|
||||
|
||||
$('#identifier-input').change(function (e) {
|
||||
$(this).data('changed', $(this).val().length > 0);
|
||||
});
|
||||
|
||||
// Poll start and end
|
||||
|
||||
var datetime_now = window.moment().seconds(0);
|
||||
var datetime_format = "YYYY-MM-DD H:mm";
|
||||
$("#vote-start-input, #vote-end-input").each(function(index, element) {
|
||||
|
||||
// Set datetimepickers' current, default and minimum date/time
|
||||
|
||||
var datetime_picker = $(element);
|
||||
var datetime_iso8601 = datetime_picker.siblings(".datetime-iso8601-input").val();
|
||||
var datetime_local = moment(datetime_iso8601);
|
||||
|
||||
datetime_picker.datetimepicker({
|
||||
sideBySide: false,
|
||||
minDate: datetime_now.clone().startOf("day"),
|
||||
format: datetime_format,
|
||||
widgetParent: $(datetime_picker)
|
||||
});
|
||||
|
||||
var minutes = (Math.ceil(datetime_now.minute() / 5) * 5) + 5 * index;
|
||||
var datetime_default = datetime_now.clone().minutes(minutes);
|
||||
|
||||
datetime_picker.data("DateTimePicker").defaultDate(datetime_default);
|
||||
|
||||
datetime_local = datetime_local.isValid() ? datetime_local.format(datetime_format) : "";
|
||||
datetime_picker.children("input").val(datetime_local);
|
||||
});
|
||||
|
||||
$('#vote-start-input, #vote-end-input').parent('.date').datetimepicker({
|
||||
allowInputToggle: true,
|
||||
icons: {
|
||||
time: 'fa fa-clock-o',
|
||||
date: 'fa fa-calendar',
|
||||
up: 'fa fa-chevron-up',
|
||||
down: 'fa fa-chevron-down',
|
||||
previous: 'fa fa-chevron-left',
|
||||
next: 'fa fa-chevron-right'
|
||||
},
|
||||
minDate: moment().startOf('day'),
|
||||
useCurrent: false,
|
||||
});
|
||||
|
||||
// Form management and Sortable rows
|
||||
|
||||
function update(event, ui) {
|
||||
var formsetPrefix = $(event.target.lastElementChild).attr('data-formset-prefix');
|
||||
var formset = $('.formset[data-formset-prefix="' + formsetPrefix + '"]');
|
||||
updateFormset(formset);
|
||||
}
|
||||
|
||||
/*$('#options-input-table').rowSorter({
|
||||
"handler" : null, // drag handler selector (default: null)
|
||||
"tbody" : true, // True if you want to sort only tbody > tr. (default: true)
|
||||
"tableClass" : "sorting-table", // This is added to the table during sorting
|
||||
"dragClass": "sorting-row", // dragging row's class name (default: "sorting-row").
|
||||
"stickTopRows": 0, // count of top sticky rows (default: 0)
|
||||
"stickBottomRows": 0, // count of bottom sticky rows (default: 0)
|
||||
"onDragStart": dragStart, // (default: null)
|
||||
"onDragEnd": dragEnd, // (default: null)
|
||||
"onDrop": drop // (default: null)
|
||||
});*/
|
||||
|
||||
$("#options-input-table, #organisers-input-table, #trustees-input-table").sortable({
|
||||
items: "tr",
|
||||
update: update
|
||||
});
|
||||
|
||||
|
||||
function updateFormset(formset) { // Ported from DEMOS 1. Updates the row number for the # and performs any removals.
|
||||
var forms = formset.children('.formset-form:not(.formset-form-empty, .formset-form-removed)');
|
||||
var removedForms = formset.children('.formset-form.formset-form-removed');
|
||||
forms.each(function(index) {
|
||||
updateForm($(this), index);
|
||||
});
|
||||
removedForms.each(function(index) {
|
||||
updateForm($(this), forms.length + index);
|
||||
});
|
||||
}
|
||||
|
||||
function updateForm(form, formIndex) { // Ported from DEMOS 1.
|
||||
// Specific update for option forms
|
||||
var mayBeTextInput = form.find('input:text')[0];
|
||||
if(mayBeTextInput.placeholder !== undefined
|
||||
&& mayBeTextInput.placeholder.indexOf("Candidate") > -1) {
|
||||
mayBeTextInput.placeholder = "Example: Candidate " + (formIndex + 1);
|
||||
}
|
||||
|
||||
var formset = form.parent('.formset');
|
||||
var formsetPrefix = formset.attr('data-formset-prefix');
|
||||
var formPrefix = formsetPrefix + '-' + formIndex;
|
||||
var formPrefixRegex = new RegExp(formsetPrefix + '-(?:__prefix__|\\d+)');
|
||||
form.find('*').addBack().each(function(index, element) {
|
||||
$.each(this.attributes, function(index, attr) {
|
||||
$(element).attr(attr.nodeName, function(index, attrValue) {
|
||||
return attrValue.replace(formPrefixRegex, formPrefix);
|
||||
});
|
||||
});
|
||||
});
|
||||
form.find('input[name="' + formPrefix + '-ORDER"]').val(formIndex);
|
||||
form.find('.formset-form-index:first').text(formIndex + 1);
|
||||
}
|
||||
|
||||
function manageTotalForms(formset, value) { // Ported from DEMOS1.
|
||||
var formsetPrefix = formset.attr('data-formset-prefix');
|
||||
var totalForms = $('#id_' + formsetPrefix + '-TOTAL_FORMS');
|
||||
var maxNumForms = $('#id_' + formsetPrefix + '-MAX_NUM_FORMS');
|
||||
totalForms.val(parseInt(totalForms.val()) + value);
|
||||
var addButton = $('.formset-add[data-formset-prefix="' + formsetPrefix + '"]');
|
||||
var removedForms = formset.children('.formset-form.formset-form-removed');
|
||||
addButton.prop('disabled', parseInt(totalForms.val()) - removedForms.length >= parseInt(maxNumForms.val()));
|
||||
}
|
||||
|
||||
$('.formset-add').click(function (e) { // Ported from DEMOS1
|
||||
var formsetPrefix = $(this).attr('data-formset-prefix');
|
||||
var formset = $('.formset[data-formset-prefix="' + formsetPrefix + '"]');
|
||||
var emptyForm = formset.children('.formset-form-empty');
|
||||
var emptyFormCheckedInputs = emptyForm.find('input:checkbox:checked, input:radio:checked');
|
||||
var form = emptyForm.clone(true).removeClass('formset-form-empty');
|
||||
var formIndex = formset.children('.formset-form:not(.formset-form-empty)').length;
|
||||
|
||||
formset.append(form);
|
||||
updateForm(form, formIndex);
|
||||
emptyFormCheckedInputs.each(function (index) {
|
||||
$(this).prop('checked', true);
|
||||
});
|
||||
switch (formset.attr('data-formset-type')) {
|
||||
case 'modal':
|
||||
$('#formset-modal').data('form', form).data('formAdd', true).modal('show');
|
||||
break;
|
||||
case 'inline':
|
||||
manageTotalForms(formset, +1);
|
||||
form.removeClass('hidden');
|
||||
formset.trigger('formsetFormAdded', [form]);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
$('.formset-form-remove').click(function (e) { // Ported from DEMOS1
|
||||
var form = $(this).closest('.formset-form');
|
||||
var formPrefix = form.attr('data-formset-form-prefix');
|
||||
var formset = form.parent('.formset');
|
||||
if ($('#id_' + formPrefix + '-id').val()) {
|
||||
$('#id_' + formPrefix + '-DELETE').prop('checked', true);
|
||||
form.addClass('formset-form-removed hidden');
|
||||
} else {
|
||||
form.remove();
|
||||
manageTotalForms(formset, -1);
|
||||
}
|
||||
updateFormset(formset);
|
||||
formset.trigger('formsetFormRemoved');
|
||||
});
|
231
static/js/demos2-booth.js
Executable file
231
static/js/demos2-booth.js
Executable file
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
|
||||
Cryptography functions written by Bingsheng Zhang
|
||||
|
||||
Uses the milagro-crypto-js library at:
|
||||
https://github.com/milagro-crypto/milagro-crypto-js
|
||||
|
||||
*/
|
||||
|
||||
//Group parameter generator: returns rng object and generators g1,g2 for G1,G2 as well as order
|
||||
gpGen = function(){
|
||||
//init, and base generators
|
||||
var ctx = new CTX("BN254CX");
|
||||
|
||||
var n=new ctx.BIG(0); n.rcopy(ctx.ROM_CURVE.CURVE_Order);
|
||||
|
||||
//get generator P for G1
|
||||
P = new ctx.ECP(0);
|
||||
gx = new ctx.BIG(0);
|
||||
gx.rcopy(ctx.ROM_CURVE.CURVE_Gx);
|
||||
if (ctx.ECP.CURVETYPE != ctx.ECP.MONTGOMERY) {
|
||||
gy = new ctx.BIG(0);
|
||||
gy.rcopy(ctx.ROM_CURVE.CURVE_Gy);
|
||||
P.setxy(gx, gy);
|
||||
} else P.setx(gx);
|
||||
|
||||
//get generator Q for G2
|
||||
var A=new ctx.BIG(0);
|
||||
var B=new ctx.BIG(0);
|
||||
A.rcopy(ctx.ROM_CURVE.CURVE_Pxa);
|
||||
B.rcopy(ctx.ROM_CURVE.CURVE_Pxb);
|
||||
var Qx=new ctx.FP2(0); Qx.bset(A,B);
|
||||
A.rcopy(ctx.ROM_CURVE.CURVE_Pya);
|
||||
B.rcopy(ctx.ROM_CURVE.CURVE_Pyb);
|
||||
var Qy=new ctx.FP2(0); Qy.bset(A,B);
|
||||
var Q=new ctx.ECP2();
|
||||
Q.setxy(Qy,Qy);
|
||||
|
||||
return{
|
||||
n:n,
|
||||
g1:P,
|
||||
g2:Q
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//creates ElGamal public and secret key
|
||||
keyGen=function(params){
|
||||
var ctx = new CTX("BN254CX");
|
||||
//set rng
|
||||
var RAW = [];
|
||||
var d = new Date();//time for seed, not secure
|
||||
var rng = new ctx.RAND();
|
||||
rng.clean();
|
||||
RAW[0] = d.getSeconds();
|
||||
RAW[1] = d.getMinutes();
|
||||
RAW[2] = d.getMilliseconds();
|
||||
rng.seed(3, RAW);
|
||||
|
||||
//ElGamal
|
||||
var sk = new ctx.BIG(0);
|
||||
sk = ctx.BIG.randomnum(params.n,rng);
|
||||
var pk = new ctx.ECP(0);
|
||||
pk = ctx.PAIR.G1mul(params.g1,sk);
|
||||
|
||||
|
||||
return{
|
||||
PK:pk,
|
||||
SK:sk
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//combine multiple public key together
|
||||
//the input is an array of PKs
|
||||
combine=function(PKs){
|
||||
var ctx = new CTX("BN254CX");
|
||||
var pk=new ctx.ECP();
|
||||
//copy the first pk
|
||||
pk.copy(PKs[0]);
|
||||
//multiple the rest PKs
|
||||
for(i=1;i<PKs.length;i++){
|
||||
pk.add(PKs[i]);
|
||||
}
|
||||
|
||||
return{
|
||||
PK:pk
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//ElGamal encryption
|
||||
encrypt=function(params,PK, m){
|
||||
var ctx = new CTX("BN254CX");
|
||||
//set rand
|
||||
var RAW = [];
|
||||
var d = new Date();//time for seed, not secure
|
||||
var rng = new ctx.RAND();
|
||||
rng.clean();
|
||||
RAW[0] = d.getSeconds();
|
||||
RAW[1] = d.getMinutes();
|
||||
RAW[2] = d.getMilliseconds();
|
||||
rng.seed(3, RAW);
|
||||
|
||||
var r=new ctx.BIG.randomnum(params.n,rng);
|
||||
var M=new ctx.BIG(m);
|
||||
|
||||
var C1=new ctx.ECP();
|
||||
C1 = ctx.PAIR.G1mul(params.g1,r);
|
||||
|
||||
var gM=new ctx.ECP();
|
||||
gM = ctx.PAIR.G1mul(params.g1,M);
|
||||
|
||||
var C2=new ctx.ECP();
|
||||
C2 = ctx.PAIR.G1mul(PK,r);
|
||||
C2.mul(r);
|
||||
C2.add(gM);
|
||||
|
||||
return{
|
||||
C1:C1,
|
||||
C2:C2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//add ciphertexts
|
||||
add=function(Ciphers){
|
||||
var ctx = new CTX("BN254CX");
|
||||
var s1=new ctx.ECP();
|
||||
var s2=new ctx.ECP();
|
||||
//copy the first cipher
|
||||
s1.copy(Ciphers[0].C1);
|
||||
s2.copy(Ciphers[0].C2);
|
||||
//multiple the rest ciphertexts
|
||||
for(i=1;i<Ciphers.length;i++){
|
||||
s1.add(Ciphers[i].C1);
|
||||
}
|
||||
//no idea why I need two loops
|
||||
for(j=1;j<Ciphers.length;j++){
|
||||
s2.add(Ciphers[j].C2);
|
||||
}
|
||||
|
||||
return{
|
||||
C1:s1,
|
||||
C2:s2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//ElGamal decryption
|
||||
decrypt=function(params,SK, C){
|
||||
var ctx = new CTX("BN254CX");
|
||||
var D=new ctx.ECP();
|
||||
D = ctx.PAIR.G1mul(C.C1,SK);
|
||||
|
||||
var gM=new ctx.ECP();
|
||||
gM.copy(C.C2);
|
||||
gM.sub(D);
|
||||
|
||||
//search for message by brute force
|
||||
var B;
|
||||
for (j = 0; j < 1000; j++) {
|
||||
//use D as temp var
|
||||
B = new ctx.BIG(j);
|
||||
D = ctx.PAIR.G1mul(params.g1,B);
|
||||
if (D.equals(gM))
|
||||
return{
|
||||
M:j
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
return{
|
||||
M: "Error"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//ElGamal partial decryption
|
||||
partDec=function(SK, C){
|
||||
var ctx = new CTX("BN254CX");
|
||||
var D=new ctx.ECP();
|
||||
D = ctx.PAIR.G1mul(C.C1,SK);
|
||||
|
||||
return{
|
||||
D: D
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Tally, combine partial decryption
|
||||
//Ds is the array of partial decryptions; C is the ciphertext.
|
||||
tally=function(params,Ds, C){
|
||||
var ctx = new CTX("BN254CX");
|
||||
var D=new ctx.ECP();
|
||||
D.copy(Ds[0].D);
|
||||
|
||||
//combine D
|
||||
for(i=1;i<Ds.length;i++){
|
||||
D.add(Ds[i].D);
|
||||
}
|
||||
|
||||
|
||||
var gM=new ctx.ECP();
|
||||
gM.copy(C.C2);
|
||||
gM.sub(D);
|
||||
|
||||
//search for message by brute force
|
||||
var B;
|
||||
for (j = 0; j < 1000; j++) {
|
||||
//use D as temp var
|
||||
B = new ctx.BIG(j);
|
||||
D = ctx.PAIR.G1mul(params.g1,B);
|
||||
if (D.equals(gM))
|
||||
return{
|
||||
M:j
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
return{
|
||||
M: "Error"
|
||||
}
|
||||
}
|
||||
|
22
static/js/encrypt-prev.js
Executable file
22
static/js/encrypt-prev.js
Executable file
File diff suppressed because one or more lines are too long
22
static/js/encrypt.js
Executable file
22
static/js/encrypt.js
Executable file
File diff suppressed because one or more lines are too long
7
static/js/papaparse.min.js
vendored
Executable file
7
static/js/papaparse.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
BIN
static/js/trustee.js.mem
Executable file
BIN
static/js/trustee.js.mem
Executable file
Binary file not shown.
Reference in a new issue