diff --git a/.gitignore b/.gitignore index ae24445..cc8ba48 100755 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,11 @@ *.pyc *.sqlite *.sqlite3 +package-lock.json +node_modules/ __pycache__ migrations/ build /venv*/ -/.idea/ \ No newline at end of file +/.idea/ diff --git a/Node/package-lock.json b/Node/package-lock.json deleted file mode 100755 index 6beeadc..0000000 --- a/Node/package-lock.json +++ /dev/null @@ -1,529 +0,0 @@ -{ - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "accepts": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", - "requires": { - "mime-types": "2.1.17", - "negotiator": "0.6.1" - } - }, - "append-field": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-0.1.0.tgz", - "integrity": "sha1-bdxY+gg8e8VF08WZWygwzCNm1Eo=" - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "requires": { - "bytes": "3.0.0", - "content-type": "1.0.4", - "debug": "2.6.9", - "depd": "1.1.1", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "on-finished": "2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "1.6.15" - } - }, - "busboy": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", - "requires": { - "dicer": "0.2.5", - "readable-stream": "1.1.14" - } - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" - }, - "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "typedarray": "0.0.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" - }, - "cookie-parser": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz", - "integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=", - "requires": { - "cookie": "0.3.1", - "cookie-signature": "1.0.6" - } - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cors": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", - "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", - "requires": { - "object-assign": "4.1.1", - "vary": "1.1.2" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - } - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "dicer": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", - "requires": { - "readable-stream": "1.1.14", - "streamsearch": "0.1.2" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "encodeurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "express": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", - "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", - "requires": { - "accepts": "1.3.4", - "array-flatten": "1.1.1", - "body-parser": "1.18.2", - "content-disposition": "0.5.2", - "content-type": "1.0.4", - "cookie": "0.3.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "1.1.1", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "etag": "1.8.1", - "finalhandler": "1.1.0", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.2", - "qs": "6.5.1", - "range-parser": "1.2.0", - "safe-buffer": "5.1.1", - "send": "0.16.1", - "serve-static": "1.13.1", - "setprototypeof": "1.1.0", - "statuses": "1.3.1", - "type-is": "1.6.15", - "utils-merge": "1.0.1", - "vary": "1.1.2" - } - }, - "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", - "requires": { - "debug": "2.6.9", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.3.1", - "unpipe": "1.0.0" - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.3.1" - }, - "dependencies": { - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" - } - } - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ipaddr.js": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", - "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=" - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "milagro-crypto-js": { - "version": "file:milagro-crypto-js" - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" - }, - "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" - }, - "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "requires": { - "mime-db": "1.30.0" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "multer": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.3.0.tgz", - "integrity": "sha1-CSsmcPaEb6SRSWXvyM+Uwg/sbNI=", - "requires": { - "append-field": "0.1.0", - "busboy": "0.2.14", - "concat-stream": "1.6.0", - "mkdirp": "0.5.1", - "object-assign": "3.0.0", - "on-finished": "2.3.0", - "type-is": "1.6.15", - "xtend": "4.0.1" - } - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" - }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" - }, - "proxy-addr": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", - "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", - "requires": { - "forwarded": "0.1.2", - "ipaddr.js": "1.5.2" - } - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" - }, - "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "unpipe": "1.0.0" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" - }, - "send": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", - "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", - "requires": { - "debug": "2.6.9", - "depd": "1.1.1", - "destroy": "1.0.4", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "etag": "1.8.1", - "fresh": "0.5.2", - "http-errors": "1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.3.1" - } - }, - "serve-static": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", - "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", - "requires": { - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "parseurl": "1.3.2", - "send": "0.16.1" - } - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" - }, - "streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "type-is": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", - "requires": { - "media-typer": "0.3.0", - "mime-types": "2.1.17" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - } - } -} diff --git a/Node/package.json b/Node/package.json new file mode 100644 index 0000000..8eda884 --- /dev/null +++ b/Node/package.json @@ -0,0 +1,23 @@ +{ + "name": "Node DEMOS2 Cryptography Server", + "version": "1.0.0", + "description": "Exposes Cryptographic Functionality from Various Endpoints", + "main": "index.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/vincentmdealmeida/DEMOS2" + }, + "keywords": [], + "author": "Bingsheng Zang, Thomas Smith", + "license": "ISC", + "dependencies": { + "express": "^4.16.3", + "milagro-crypto-js": "git+https://github.com/milagro-crypto/milagro-crypto-js.git" + } +} diff --git a/README.md b/README.md index f13a4ea..c59b7f4 100755 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # DEMOS2 -Prototype Django based e-voting application, to demonstrate DEMOS2's client-side encryption e-voting. +Prototype Django-based e-voting application, to demonstrate DEMOS2's client-side encryption e-voting. The previous repository for DEMOS2 by Carey Williams can be found at: https://github.com/CareyJWilliams/DEMOS2 -### Dependencies +### Main Application Dependencies Python: Version 2.7 (Anything higher than this will not currently work) Python packages: Specified in 'requirements.txt' - PyCharm will detect these dependencies and offer installation @@ -17,9 +17,23 @@ Finally, with all the above dependencies in place, you can simply issue the foll python manage.py migrate 'aullauthdemo/settings.py' specifies the Google reCAPTCHA site key and private key which will need changing when deployed -onto a new domain. +onto a new domain. There is also a DOMAIN setting within the file that needs updating during deployment as things +like email functionality depend on this setting for correct URL generation during event preparation etc. -### Running the server and creating a new user account +Emails from the application are currently sent from the following email account which can be updated within the settings: + + demos2.no.reply@gmail.com + +### NodeJS Dependencies + +The Node.js crypto server depends on the milagro-crypto-js and express modules. A package.json file can be found in the +Node/ directory with these dependency requirements and therefore from this folder you can run: + + npm install + +Once the dependencies have been installed, you can then run the node server as per the below instructions. + +### Step 1: Running the Python app and creating a new user account You can run the server with the following command: @@ -33,8 +47,16 @@ You can then click on 'Join' to create a new user account. Currently, a server e email account saying something like 'Too Many Attempts'. Rest assured that the account will have been created. Navigate back to the home page and you should be able to log in. This will hopefully be fixed in a future version. -### Other +### Step 2: Running Celery -This was included in the previous readme and may be required: +Celery is used to run tasks asynchronously and the DEMOS2 application can't run without this application. A bash script +called 'start_celery_worker.sh' is provided to make starting a worker as easy as possible: -The Node.js encryption server depends on the milagro-crypto-js library. Download the source and follow the instructions for installation: https://github.com/milagro-crypto/milagro-crypto-js. To install, place the package's files (`package.json` level) into the directory Node/milagro-crypto-js (a new folder) then run `npm install` in the Node folder. This should install dependencies including the local package you just added. + ./start_celery_worker.sh + +### Step 3: Running the NodeJS Server + +The NodeJS server exposes a lot of cryptographic operations that the application depends on throughout. To run the +server, issue the following command line request from the Node/ folder: + + node index.js diff --git a/allauthdemo/polls/cpp_calls.py b/allauthdemo/polls/crypto_rpc.py similarity index 79% rename from allauthdemo/polls/cpp_calls.py rename to allauthdemo/polls/crypto_rpc.py index c95029f..a85cc8a 100755 --- a/allauthdemo/polls/cpp_calls.py +++ b/allauthdemo/polls/crypto_rpc.py @@ -4,18 +4,21 @@ import subprocess import json import urllib2 -#change this file name etc., temporary change to get it working for the meantime ''' All functions in this file have been re-implemenented by Thomas Smith +File then updated by Vincent de Almeida. Changes include: + -Update filename to 'crypto_rpc' to reflect the RPC nature of the methods + ''' def param(): - jsondict = json.load(urllib2.urlopen('http://localhost:8080/param')) + url = 'http://localhost:8080/param' # RPC URL + jsondict = json.load(urllib2.urlopen(url)) return json.dumps(jsondict) def combpk(amount, pks): - url = 'http://localhost:8080/cmpkstring' + url = 'http://localhost:8080/cmpkstring' # RPC URL querystring = '?number='+str(amount) for pk in pks: querystring += '&PK='+pk @@ -26,7 +29,7 @@ def combpk(amount, pks): return json.dumps(jsondict) def addec(amount, ciphers): - url = 'http://localhost:8080/addec' + url = 'http://localhost:8080/addec' # RPC URL querystring = '?number='+str(amount) c1s = ciphers['c1s'] c2s = ciphers['c2s'] @@ -40,7 +43,7 @@ def addec(amount, ciphers): return json.dumps(jsondict) def tally(amount, param, decs, cipher): - url = 'http://localhost:8080/tally' + url = 'http://localhost:8080/tally' # RPC URL querystring = '?number='+str(amount) querystring += '¶m='+urllib2.quote(str(param)) diff --git a/allauthdemo/polls/models.py b/allauthdemo/polls/models.py index 01c7512..84a7524 100755 --- a/allauthdemo/polls/models.py +++ b/allauthdemo/polls/models.py @@ -1,7 +1,8 @@ from __future__ import unicode_literals -from datetime import datetime +import json +from django.core.mail import send_mail from django.db import models from django.utils import timezone @@ -9,9 +10,17 @@ from allauthdemo.auth.models import DemoUser class EmailUser(models.Model): email = models.CharField(max_length=80, unique=True) + + def send_email(self, subject, message, from_email=None): + """ + Sends an email to this User. + """ + send_mail(subject, message, from_email, [self.email]) + def __unicode__(self): return self.email + class Event(models.Model): users_organisers = models.ManyToManyField(DemoUser, blank=True, related_name="organisers") users_trustees = models.ManyToManyField(EmailUser, blank=True, related_name="trustees") @@ -26,11 +35,32 @@ class Event(models.Model): c_email = models.CharField(max_length=512, blank=True) trustees = models.CharField(max_length=4096) + def EID_hr(self): + EID_json = json.loads(self.EID) + return EID_json['hr'] + + def EID_crypto(self): + EID_json = json.loads(self.EID) + EID_crypto_str = EID_json['crypto'] + return json.loads(EID_crypto_str) + def duration(self): - duration_str = self.start_time.strftime("%d-%m-%y %H:%M") - duration_str = duration_str + " - " + self.end_time.strftime("%d-%m-%y %H:%M %Z") + duration_str = self.start_time_formatted() + duration_str = duration_str + " - " + self.end_time_formatted_utc() return duration_str + def start_time_formatted(self): + return self.start_time.strftime("%d-%m-%y %H:%M") + + def start_time_formatted_utc(self): + return self.start_time.strftime("%d-%m-%y %H:%M %Z") + + def end_time_formatted(self): + return self.end_time.strftime("%d-%m-%y %H:%M") + + def end_time_formatted_utc(self): + return self.end_time.strftime("%d-%m-%y %H:%M %Z") + def status(self): status_str = "" @@ -113,14 +143,4 @@ class Organiser(models.Model): email = models.CharField(max_length=100, blank=False, null=False) event = models.ForeignKey(Event, on_delete=models.CASCADE) -''' -class Organiser(models.Model): - user = models.ForeignKey(DemoUser, on_delete=models.CASCADE) - event = models.ForeignKey(Event, on_delete=models.CASCADE) -class Trustee(models.Model): - user = models.ForeignKey(DemoUser, on_delete=models.CASCADE) - event = models.ForeignKey(Event, on_delete=models.CASCADE) - ''' -#class EventOrganisers(): - #event = models.ForeignKey(Event, on_delete=models.CASCADE) diff --git a/allauthdemo/polls/tasks.py b/allauthdemo/polls/tasks.py index 39aaa4e..0390b28 100755 --- a/allauthdemo/polls/tasks.py +++ b/allauthdemo/polls/tasks.py @@ -1,14 +1,29 @@ from __future__ import absolute_import -import csv -from os import urandom + import base64 -from io import StringIO +import json +from os import urandom from celery import task + from django.core.exceptions import ValidationError from django.core.validators import EmailValidator from django.core.mail import send_mail -from allauthdemo.polls.models import Ballot, Event, EmailUser, AccessKey -from .cpp_calls import param, combpk, addec, tally +from django.conf import settings + +from allauthdemo.polls.models import AccessKey + +from .crypto_rpc import param, combpk, addec, tally + +''' + Goal: This py file defines celery tasks that can be initiated + + The following tasks were re-implemented by Thomas Smith: generate_event_param, tally_results, generate_combpk, generate_enc + + This file was also updated by Vincent de Almeida +''' + +# Will store the result of the initial cal to param() from .cpp_calls +group_param = None def is_valid_email(email): try: @@ -23,36 +38,59 @@ def create_ballots(poll): for voter in poll.event.voters.all(): ballot = poll.ballots.create(voter=voter, poll=poll) -@task() -def create_voters(csvfile, event): - print("Creating voters for event " + event.title) - reader = csv.reader(csvfile, delimiter=',') - string = "" - for row in reader: - email = string.join(row) - print(email) - #testvoter = EmailUser.objects.get_or_create(email='notarealemail@live.com')[0] - #event.voters.add(testvoter) - if (is_valid_email(email)): - voter = EmailUser.objects.get_or_create(email=email)[0] - event.voters.add(voter) - key = base64.urlsafe_b64encode(urandom(16)).decode('utf-8') - AccessKey.objects.create(user=voter, event=event, key=key) - send_mail( - 'Your Voting Key', - 'Key: ' + key, - 'from@example.com', - [string.join(row)], - fail_silently=False, - ) ''' - -Starting here: functions re-implemented by Thomas Smith + Will generate a key for accessing either the event preparation page or the voting page +''' +def gen_access_key(): + return base64.urlsafe_b64encode(urandom(16)).decode('utf-8') +''' + Emails an event preparation URL containing an access key for all of the trustees for an event ''' @task() -def generate_event_param(event): - event.EID = param() +def email_trustees_prep(trustees, event): + email_subject = "Key Generation and Preparation for Event '" + event.title + "'" + + # Plain text email - this could be replaced for a HTML-based email in the future + email_body = "Please visit the following URL to prepare the event and generate your trustee secret key:\n\n" + url_base = "http://" + settings.DOMAIN + "/event/" + str(event.pk) + "/prepare/?key=" + email_body = email_body + url_base + + for trustee in trustees: + # Generate a key and create an AccessKey object + key = gen_access_key() + AccessKey.objects.create(user=trustee, event=event, key=key) + + trustee.send_email(email_subject, email_body + key) + +''' + Emails the access keys for all of the voters for an event +''' +@task() +def email_voters_a_key(voters, event): + email_subject = "Voting Access for Event '" + event.title + "'" + email_body = 'Key: ' + + for voter in voters: + # Generate a key and create an AccessKey object + key = gen_access_key() + AccessKey.objects.create(user=voter, event=event, key=key) + + voter.send_email(email_subject, email_body + key) + +''' + Updates the EID of an event to contain 2 event IDs: a human readable one (hr) and a crypto one (GP from param()) +''' +@task() +def update_EID(event): + global group_param + if group_param is None: + group_param = param() + + EID = {} + EID['hr'] = event.EID + EID['crypto'] = group_param + event.EID = json.dumps(EID) event.save() @task() @@ -98,20 +136,4 @@ def generate_enc(poll): poll.enc = addec(amount, ciphers) poll.save() -''' -End of re-implemented code - -''' - -@task() -def add(x, y): - return x + y - -@task() -def mul(x, y): - return x * y - -@task() -def xsum(numbers): - return sum(numbers) diff --git a/allauthdemo/polls/utils/EventModelAdaptor.py b/allauthdemo/polls/utils/EventModelAdaptor.py index a4e1d1d..5b5c968 100644 --- a/allauthdemo/polls/utils/EventModelAdaptor.py +++ b/allauthdemo/polls/utils/EventModelAdaptor.py @@ -1,13 +1,9 @@ import re - from datetime import datetime from django.utils.dateparse import parse_datetime -from allauthdemo.polls.models import Event -from allauthdemo.polls.models import Poll -from allauthdemo.polls.models import PollOption -from allauthdemo.polls.models import EmailUser +from allauthdemo.polls.models import Event, Poll, PollOption, EmailUser from allauthdemo.auth.models import DemoUser ''' @@ -382,6 +378,7 @@ class EventModelAdaptor: errors_summary = errors_summary + str(i + 1) + " " self.invalid_form_fields['polls_data'] = {'val': polls_json} + self.invalid_form_fields['poll_count'] = {'val': poll_count} if not valid and len(errors_summary) > 34: errors_summary = errors_summary + "and can be corrected by editing them." @@ -536,7 +533,7 @@ class EventModelAdaptor: organisers_list = self.form_data.pop('organiser-email-input') for organiser in organisers_list: - if organiser != '' and DemoUser.objects.filter(email=organiser).count() == 1: + if organiser != '' and DemoUser.objects.filter(email=organiser).exists(): self.organisers.append(DemoUser.objects.filter(email=organiser).get()) # Extract the list of trustees @@ -544,7 +541,7 @@ class EventModelAdaptor: for trustee in trustees_list: if trustee != '': - if EmailUser.objects.filter(email=trustee).count() == 1: + if EmailUser.objects.filter(email=trustee).exists(): self.trustees.append(EmailUser.objects.filter(email=trustee).get()) else: self.trustees.append(EmailUser(email=trustee)) @@ -555,7 +552,7 @@ class EventModelAdaptor: for voter_email in voters_email_list: if voter_email != '': - if EmailUser.objects.filter(email=voter_email).count() == 1: + if EmailUser.objects.filter(email=voter_email).exists(): self.voters.append(EmailUser.objects.filter(email=voter_email).get()) else: self.voters.append(EmailUser(email=voter_email)) @@ -634,14 +631,15 @@ class EventModelAdaptor: # Add the list of trustees to the event, making sure they're instantiated for trustee in self.trustees: - if EmailUser.objects.filter(email=trustee.email).count() == 0: + if not EmailUser.objects.filter(email=trustee.email).exists(): trustee.save() self.event.users_trustees = self.trustees # Add the list of voters to the event, making sure they're instantiated + # Additionally, generating the AccessKey for voters for voter in self.voters: - if EmailUser.objects.filter(email=voter.email).count() == 0: + if not EmailUser.objects.filter(email=voter.email).exists(): voter.save() self.event.voters = self.voters @@ -655,10 +653,10 @@ class EventModelAdaptor: self.event.save() - # Finally perform a data clean up - self.__clear_data() + # Finally return a reference to the event + return self.event - def __clear_data(self): + def clear_data(self): self.form_data = None self.form_data_validation = None self.invalid_form_fields = {} diff --git a/allauthdemo/polls/views.py b/allauthdemo/polls/views.py index 39fca8e..a12f20d 100755 --- a/allauthdemo/polls/views.py +++ b/allauthdemo/polls/views.py @@ -17,8 +17,7 @@ from .forms import EventForm, PollForm, OptionFormset, QuestionFormset, Organise from .models import Event, Poll, PollOption, EmailUser, Ballot, TrusteeKey, Decryption from allauthdemo.auth.models import DemoUser -from .tasks import create_voters, create_ballots, generate_event_param, generate_combpk, generate_enc, tally_results -from .cpp_calls import param, addec, combpk, tally +from .tasks import email_trustees_prep, update_EID, generate_combpk, generate_enc, tally_results from .utils.EventModelAdaptor import EventModelAdaptor @@ -38,6 +37,7 @@ class EventDetailView(generic.DetailView): def get_context_data(self, **kwargs): context = super(EventDetailView, self).get_context_data(**kwargs) context['is_organiser'] = ((not self.request.user.is_anonymous()) and (self.object.users_organisers.filter(email=self.request.user.email).exists())) + #context['now'] = timezone.now() return context @@ -153,28 +153,42 @@ def view_poll(request, event_id, poll_num): }) def event_trustee_setup(request, event_id): + # Obtain the event and the event preparation access key that's been supplied event = get_object_or_404(Event, pk=event_id) access_key = request.GET.get('key', None) - if (access_key): + + # If the a_key is present, check it's valid and related to a trustee EmailUser instance for this event + if access_key: email_key = event.keys.filter(key=access_key) - if (email_key.exists() and event.users_trustees.filter(email=email_key[0].user.email).exists()): - if (TrusteeKey.objects.filter(event=event, user=email_key[0].user).exists()): + if email_key.exists() and event.users_trustees.filter(email=email_key[0].user.email).exists(): + if TrusteeKey.objects.filter(event=event, user=email_key[0].user).exists(): messages.add_message(request, messages.WARNING, 'You have already submitted your key for this event') return HttpResponseRedirect(reverse("user_home")) - if (request.method == "POST"): + if request.method == "POST": form = EventSetupForm(request.POST) - if (form.is_valid()): + + # If form data is valid, create a TrusteeKey object with the supplied public key + if form.is_valid(): public_key = request.POST["public_key"] key = TrusteeKey.objects.get_or_create(event=event, user=email_key[0].user)[0] key.key = public_key key.save() - if (event.trustee_keys.count() == event.users_trustees.count()): # ready for combpk + + # When all trustees have supplied their public key, we can combine them to create a master key + # The event will now be ready to receive votes on the various polls that have been defined - + # voters therefore need to be informed + if event.trustee_keys.count() == event.users_trustees.count(): generate_combpk.delay(event) - messages.add_message(request, messages.SUCCESS, 'You have successfully submitted your public key for this event') + # TODO: Create Celery task that generates voting URLs for voters as well as creates the ballots + + success_msg = 'You have successfully submitted your public key for this event' + messages.add_message(request, messages.SUCCESS, success_msg) + + # This re-direct may not be appropriate for trustees that don't have logins return HttpResponseRedirect(reverse("user_home")) else: form = EventSetupForm() - return render(request, "polls/event_setup.html", {"event": event, "form": form }) + return render(request, "polls/event_setup.html", {"event": event, "form": form}) #if no key or is invalid? messages.add_message(request, messages.WARNING, 'You do not have permission to access: ' + request.path) @@ -247,11 +261,11 @@ def manage_questions(request, event_id): poll.save() formset = OptionFormset(request.POST, prefix="formset_organiser", instance=poll) if formset.is_valid(): - for form in formset: - formset.save() - create_ballots.delay(poll) - messages.add_message(request, messages.SUCCESS, 'Poll created successfully') - return HttpResponseRedirect(reverse('polls:view-poll', kwargs={'event_id': poll.event_id, 'poll_num': event.polls.count() })) + formset.save() + #create_ballots.delay(poll) + messages.add_message(request, messages.SUCCESS, 'Poll created successfully') + return HttpResponseRedirect(reverse('polls:event-polls', args=[poll.event_id])) + return render(request, "polls/create_poll.html", {"event": event, "question_form": form, "option_formset": formset}) elif request.method == "GET": @@ -296,17 +310,28 @@ def create_event(request): '''Process form data based on above results''' if result['success']: if form_data_valid: + # Create the new event using the form data adaptor.extractData() - adaptor.updateModel() + new_event = adaptor.updateModel() + + # Update the EID to include the GP in its EID + update_EID.delay(new_event) + + # Send an email to all trustees for event preparation + trustees = new_event.users_trustees.all() + email_trustees_prep.delay(trustees, new_event) + + adaptor.clear_data() return HttpResponseRedirect(reverse('polls:index')) else: invalid_fields = adaptor.getInvalidFormFields() + adaptor.clear_data() return render_invalid(request, events, demo_users, invalid_fields) - else: invalid_fields = adaptor.getInvalidFormFields() invalid_fields['recaptcha'] = {'error': 'The reCAPTCHA server validation failed, please try again.'} + adaptor.clear_data() return render_invalid(request, events, demo_users, invalid_fields) elif request.method == "GET": diff --git a/allauthdemo/settings.py b/allauthdemo/settings.py index 73eadf7..eefc15e 100755 --- a/allauthdemo/settings.py +++ b/allauthdemo/settings.py @@ -26,6 +26,9 @@ TEMPLATE_DEBUG = True ALLOWED_HOSTS = ['web.server.com'] +# Domain the application is deployed on (Needs changing for production) +# This must not include the protocol nor any trailing slashes as application code should just add this in +DOMAIN = "127.0.0.1:8000" # Application definition @@ -163,8 +166,8 @@ MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' #EMAIL_PORT = 1025 EMAIL_HOST = 'smtp.gmail.com' -EMAIL_HOST_USER = 'username@gmail.com' -EMAIL_HOST_PASSWORD = 'password' +EMAIL_HOST_USER = 'demos2.no.reply@gmail.com' +EMAIL_HOST_PASSWORD = 'Demos2LancsUni' EMAIL_PORT = 587 EMAIL_USE_TLS = True diff --git a/allauthdemo/templates/bases/bootstrap-jquery.html b/allauthdemo/templates/bases/bootstrap-jquery.html index 14fedfc..5ee398b 100755 --- a/allauthdemo/templates/bases/bootstrap-jquery.html +++ b/allauthdemo/templates/bases/bootstrap-jquery.html @@ -150,7 +150,7 @@ //new function demosEncrypt.generateKeys = function() { parameter = $("#event-param").val(); - var tempParams = JSON.parse(parameter); + var tempParams = JSON.parse(JSON.parse(parameter).crypto); //the full objects need to be initalised as per the library, then copy the values we need into it //I follow Bingsheng's code as to what objects are used in the parameter object var ctx = new CTX("BN254CX"); //new context we can use diff --git a/allauthdemo/templates/polls/create_event.html b/allauthdemo/templates/polls/create_event.html index 18e732c..3728649 100755 --- a/allauthdemo/templates/polls/create_event.html +++ b/allauthdemo/templates/polls/create_event.html @@ -26,11 +26,13 @@ } {% endfor %} ]; + + {% if invalid_fields.poll_count %}pollCount = {{ invalid_fields.poll_count.val }};{% endif %} - +
By {{object.users_organisers.all}}
- - {% block event_content %}{% endblock %} +No organisers for this Event.
{% endif %} -No trustees for this Event.
{% endif %} -Minimum Number of Option Selections: {{ poll.min_num_selections }}. Maximum Number of Option Selections: {{ poll.max_num_selections }}.
+No polls are available for this Event.
{% endif %} {% if is_organiser %} -Make a backup of this secret key before submitting your public key. This can NOT be recalculated if forgotten!
- - Download + {% load crispy_forms_tags %} +