Add setup flow
Project: http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/commit/67ed8ebe Tree: http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/tree/67ed8ebe Diff: http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/diff/67ed8ebe Branch: refs/heads/add-documentation Commit: 67ed8ebe81139f677f3038c03fb21d761e2c51e3 Parents: 10266af Author: Boyan Bakov <[email protected]> Authored: Fri Nov 20 17:45:56 2015 +0200 Committer: Vladislav Mitov <[email protected]> Committed: Fri Dec 18 18:55:25 2015 +0200 ---------------------------------------------------------------------- .gitignore | 6 + Gruntfile.js | 48 +++++++ bower.json | 14 ++ index.js | 1 + lib/mpin.js | 216 +++++++++++++++++++++++++++++ package.json | 41 ++++++ test/coverage.html | 360 ++++++++++++++++++++++++++++++++++++++++++++++++ test/index.js | 153 ++++++++++++++++++++ test/mocha.opts | 2 + 9 files changed, 841 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/blob/67ed8ebe/.gitignore ---------------------------------------------------------------------- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..727ae60 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +dist/ +npm-debug.log +bower_components/ +nbproject/ +index.html http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/blob/67ed8ebe/Gruntfile.js ---------------------------------------------------------------------- diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..78d9edb --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,48 @@ +module.exports = function(grunt) { + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + concat: { + options: { + separator: ';' + }, + mergeJs: { + src: ['bower_components/clint/DBIG.js','bower_components/clint/BIG.js', 'bower_components/clint/FP.js', 'bower_components/clint/ROM.js', 'bower_components/clint/HASH.js', 'bower_components/clint/RAND.js', 'bower_components/clint/AES.js', 'bower_components/clint/GPM.js', 'bower_components/clint/ECP.js', 'bower_components/clint/FP2.js', 'bower_components/clint/ECP2.js', 'bower_components/clint/FP4.js', 'bower_components/clint/FP12.js', 'bower_components/clint/PAIR.js', 'bower_components/clint/MPIN.js', 'bower_components/clint/MPINAuth.js', 'lib/mpin.js'], + dest: './dist/mpinjs.js' + } + }, + bgShell: { + createDir: { + cmd: "mkdir -p ./dist", + options: { + stdout: true + } + }, + test: { + cmd: 'mocha', + options: { + stdout: true + } + }, + testCoverage: { + cmd: 'mocha test --require blanket --reporter html-cov > test/coverage.html', + options: { + stdout: true + } + }, + bowerInstall: { + cmd: 'bower install --allow-root', + options: { + stdout: true + } + } + } + }); + + grunt.loadNpmTasks('grunt-bg-shell'); + grunt.loadNpmTasks('grunt-contrib-concat'); + + grunt.registerTask('build', ['bgShell:createDir', 'bgShell:bowerInstall', 'concat']); + grunt.registerTask('chk', ['bgShell:createDir', 'bgShell:bowerInstall', 'concat']); + grunt.registerTask('test', ['bgShell:test']); + grunt.registerTask('testCover', ['bgShell:testCoverage']); +}; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/blob/67ed8ebe/bower.json ---------------------------------------------------------------------- diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..bf93c48 --- /dev/null +++ b/bower.json @@ -0,0 +1,14 @@ +{ + "name": "Mpin lib", + "version": "1.0.0", + "description": "Mpin lib front-end project", + "authors": [ + "Miracl ltd." + ], + "dependencies": { + "clint": "https://builds.certivox.com/mpin_libs/js/latest/js.tar.gz" + }, + "moduleType": "globals", + "main": "lib/mpin.js", + "homepage": "http://miracl.com" +} http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/blob/67ed8ebe/index.js ---------------------------------------------------------------------- diff --git a/index.js b/index.js new file mode 100644 index 0000000..3a12526 --- /dev/null +++ b/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/mpin'); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/blob/67ed8ebe/lib/mpin.js ---------------------------------------------------------------------- diff --git a/lib/mpin.js b/lib/mpin.js new file mode 100644 index 0000000..285d749 --- /dev/null +++ b/lib/mpin.js @@ -0,0 +1,216 @@ +var mpinjs = (function () { + var Mpin, Users = {}, Errors = []; + + Errors[1] = "Invalid userId."; + Errors[2] = "UserId does not exist."; + Errors[3] = "Missing parameter."; + + Errors[4] = "UserId are not verified."; + + Mpin = function (options) { + if (!options || !options.settingsUrl) { + return new Error("Missing settings URL"); + } + + this.opts = options; + }; + + Mpin.prototype.debug = true; + + Mpin.prototype.init = function (cb) { + var self = this; + + this.request({url: this.opts.settingsUrl}, function (err, data) { + if (err && cb) { + return cb(err, null); + } + + self.ready = true; + self.opts = data; + + cb && cb(null, data); + }); + }; + + Mpin.prototype.makeNewUser = function (userId, deviceId) { + if (!userId) { + return {error: 1}; + } + + Users[userId] = { + userId: userId, + deviceId: deviceId || "", + status: "INVALID" + }; + + return this; + }; + + Mpin.prototype.startRegistration = function (userId, cb) { + var _reqData = {}, self = this; + if (!userId || typeof userId != "string") { + return cb ? cb({error: 1}, null) : {error: 1}; + } else if (!this.checkUser(userId)) { + return cb({error: 2}, null); + } else if (!this.opts.registerURL) { + return cb({error: 3, message: "Missing registerURL"}, null); + } + + _reqData.url = this.opts.registerURL; + _reqData.type = "PUT"; + _reqData.data = { + userId: userId, + mobile: 0 + }; + + this.request(_reqData, function (err, data) { + if (err) { + return cb(err, null); + } + + self.addToUser(userId, {regOTT: data.regOTT, mpinId: data.mpinId,status: "STARTED"}); + + //force activate + if (data.active) { + self.addToUser(userId, {status: "ACTIVATED"}); + } + + cb && cb(null, true); + }); + }; + + + //request cs1 + cs2 + Mpin.prototype.confirmRegistration = function (userId, cb) { + var _cs1Url = "", self = this; + + _cs1Url = this.opts.signatureURL + "/"; + _cs1Url += Users[userId].mpinId; //identity + _cs1Url += "?regOTT=" + Users[userId].regOTT; + + //req cs1 + this.request({url: _cs1Url}, function (err, cs1Data) { + var _cs2Url = ""; + if (err) { + if (err.status == 401) { + return cb({error: 4, message: "Identity not activate."}, null); + } + } + + self.addToUser(userId, {cs1: cs1Data.clientSecretShare, csParams: cs1Data.params, status: "ACTIVATED"}); + _cs2Url = self.opts.certivoxURL + "clientSecret?" + cs1Data.params; + + //req cs2 + self.request({url: _cs2Url}, function (err, cs2Data) { + var csHex; + self.addToUser(userId, {cs2: cs2Data.clientSecret}); + csHex = MPINAuth.addShares(cs2Data.clientSecret, cs1Data.clientSecretShare); + + self.addToUser(userId, {csHex: csHex}); + + cb(null, true); + }); + }); + }; + + + + Mpin.prototype.finishRegistration = function (userId, pin) { + var _user, tokenHex; + + _user = this.getUser(userId); + + if (_user.status !== "ACTIVATED") { + return {error: 3}; + } + + tokenHex = MPINAuth.calculateMPinToken(Users[userId].mpinId, pin, Users[userId].csHex); + this.addToUser(userId, {tokenHex: tokenHex, status: "REGISTER"}); + + return tokenHex; + }; + + //Put user / mpinId + Mpin.prototype.restartRegistration = function (userId, deviceId, cb) { + var err = null, data = {}; + cb(err, data); + }; + + + Mpin.prototype.listUsers = function () { + var listUsers = {}; + for (var uKey in Users) { + listUsers[uKey] = { + userId: Users[uKey].userId, + deviceId: Users[uKey].deviceId, + status: Users[uKey].status + }; + } + return listUsers; + }; + + Mpin.prototype.checkUser = function (userId) { + return (Users[userId]) ? true : false; + }; + + + Mpin.prototype.getUser = function (userId) { + var _user = {}; + if (!userId) { + return {error: 0}; + } else if (!this.checkUser(userId)) { + return {error: 2}; + } + + _user = { + userId: Users[userId].userId, + deviceId: Users[userId].deviceId, + status: Users[userId].status + }; + + return _user; + }; + + Mpin.prototype.addToUser = function (userId, userProps) { + if (!this.checkUser(userId)) { + return false; + } + + for (var uKey in userProps) { + Users[userId][uKey] = userProps[uKey]; + } + }; + + Mpin.prototype.restore = function () { + Users = {}; + }; + +//{url: url, type: "get post put", data: data} + Mpin.prototype.request = function (options, cb) { + var _request = new XMLHttpRequest(), _url, _type, _data; + _url = options.url || ""; + _type = options.type || "GET"; + _data = options.data || ""; + + _request.onreadystatechange = function () { + if (_request.readyState === 4 && _request.status === 200) { + cb(null, JSON.parse(_request.responseText)); + } else if (_request.readyState === 4) { + cb({status: _request.status}, null); + } + }; + + _request.open(_type, _url, true); + _request.send(JSON.stringify(_data || "")); + }; + + return Mpin; +})(); + + +//module.exports = mpinjs; +//http://www.matteoagosti.com/blog/2013/02/24/writing-javascript-modules-for-both-browser-and-node/ +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') + module.exports = mpinjs; +else + window.mpinjs = mpinjs; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/blob/67ed8ebe/package.json ---------------------------------------------------------------------- diff --git a/package.json b/package.json new file mode 100644 index 0000000..d3c1a1b --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "mpinjs", + "version": "1.0.0", + "description": "Mpin frontend library.", + "main": "index.js", + "scripts": { + "test": "mocha", + "test2": "mocha test --require blanket --reporter html-cov > test/coverage.html" + }, + "repository": { + "type": "git", + "url": "http://10.10.23.8:7990/scm/mpin/mpinjs.git" + }, + "keywords": [ + "Mpin", + "frontend" + ], + "author": "Mpin", + "license": "ISC", + "devDependencies": { + "blanket": "^1.2.1", + "chai": "^3.4.1", + "mocha": "^2.3.4", + "sinon": "^1.17.2", + "sinon-chai": "^2.8.0" + }, + "config": { + "blanket": { + "pattern": [ + "mpin.js" + ], + "data-cover-never": "node_modules" + } + }, + "dependencies": { + "bower": "^1.6.5", + "grunt": "^0.4.5", + "grunt-bg-shell": "^2.3.1", + "grunt-contrib-concat": "^0.5.1" + } +} http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/blob/67ed8ebe/test/coverage.html ---------------------------------------------------------------------- diff --git a/test/coverage.html b/test/coverage.html new file mode 100644 index 0000000..8d6f974 --- /dev/null +++ b/test/coverage.html @@ -0,0 +1,360 @@ +err { error: 3, message: 'Missing registerURL' } null +<!DOCTYPE html><html><head><title>Coverage</title><meta charset="utf-8"><script> + +headings = []; + +onload = function(){ + headings = document.querySelectorAll('h2'); +}; + +onscroll = function(e){ + var heading = find(window.scrollY); + if (!heading) return; + var links = document.querySelectorAll('#menu a') + , link; + + for (var i = 0, len = links.length; i < len; ++i) { + link = links[i]; + link.className = link.getAttribute('href') == '#' + heading.id + ? 'active' + : ''; + } +}; + +function find(y) { + var i = headings.length + , heading; + + while (i--) { + heading = headings[i]; + if (y >= heading.offsetTop) { + return heading; + } + } +} +</script> +<style> + +body { + font: 14px/1.6 "Helvetica Neue", Helvetica, Arial, sans-serif; + margin: 0; + color: #2C2C2C; + border-top: 2px solid #ddd; +} + +#coverage { + padding: 60px 400px 60px 60px; +} + +h1 a { + color: inherit; + font-weight: inherit; +} + +h1 a:hover { + text-decoration: none; +} + +.onload h1 { + opacity: 1; +} + +h2 { + width: 80%; + margin-top: 80px; + margin-bottom: 0; + font-weight: 100; + letter-spacing: 1px; + border-bottom: 1px solid #eee; +} + +a { + color: #8A6343; + font-weight: bold; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +ul { + margin-top: 20px; + padding: 0 15px; + width: 100%; +} + +ul li { + float: left; + width: 40%; + margin-top: 5px; + margin-right: 60px; + list-style: none; + border-bottom: 1px solid #eee; + padding: 5px 0; + font-size: 12px; +} + +ul::after { + content: '.'; + height: 0; + display: block; + visibility: hidden; + clear: both; +} + +code { + font: 12px monaco, monospace; +} + +pre { + margin: 30px; + padding: 30px; + border: 1px solid #eee; + border-bottom-color: #ddd; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; + -webkit-box-shadow: inset 0 0 10px #eee; + -moz-box-shadow: inset 0 0 10px #eee; + box-shadow: inset 0 0 10px #eee; + overflow-x: auto; +} + +img { + margin: 30px; + padding: 1px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888; + -moz-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888; + box-shadow: 0 3px 10px #dedede, 0 1px 5px #888; + max-width: 100%; +} + +footer { + background: #eee; + width: 100%; + padding: 50px 0; + text-align: right; + border-top: 1px solid #ddd; +} + +footer span { + display: block; + margin-right: 30px; + color: #888; + font-size: 12px; +} + +#menu { + position: fixed; + font-size: 12px; + overflow-y: auto; + top: 0; + right: 0; + margin: 0; + height: 100%; + padding: 15px 0; + text-align: right; + border-left: 1px solid #eee; + max-width: 400px; + overflow: auto; + white-space: nowrap; + + -moz-box-shadow: 0 0 2px #888 + , inset 5px 0 20px rgba(0,0,0,.5) + , inset 5px 0 3px rgba(0,0,0,.3); + -webkit-box-shadow: 0 0 2px #888 + , inset 5px 0 20px rgba(0,0,0,.5) + , inset 5px 0 3px rgba(0,0,0,.3); + box-shadow: 0 0 2px #888 + , inset 5px 0 20px rgba(0,0,0,.5) + , inset 5px 0 3px rgba(0,0,0,.3); + -webkit-font-smoothing: antialiased; + background: url("data:image/png;base64,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"); +} + +#menu::after { + display: block; + content: ''; + padding-top: 80px; +} + +#logo { + position: fixed; + bottom: 10px; + right: 10px; + background: rgba(255,255,255,.1); + font-size: 11px; + display: block; + width: 20px; + height: 20px; + line-height: 20px; + text-align: center; + -webkit-border-radius: 20px; + -moz-border-radius: 20px; + border-radius: 20px; + -webkit-box-shadow: 0 0 3px rgba(0,0,0,.2); + -moz-box-shadow: 0 0 3px rgba(0,0,0,.2); + box-shadow: 0 0 3px rgba(0,0,0,.2); + color: inherit; +} + +#menu li a { + display: block; + color: white; + padding: 0 35px 0 25px; + -webkit-transition: background 300ms; + -moz-transition: background 300ms; +} + +#menu li { + position: relative; + list-style: none; +} + +#menu a:hover, +#menu a.active { + text-decoration: none; + background: rgba(255,255,255,.1); +} + +#menu li:hover .cov { + opacity: 1; +} + +#menu li .dirname { + opacity: .60; + padding-right: 2px; +} + +#menu li .basename { + opacity: 1; +} + +#menu .cov { + background: rgba(0,0,0,.4); + position: absolute; + top: 0; + right: 8px; + font-size: 9px; + opacity: .6; + text-align: left; + width: 17px; + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + border-radius: 10px; + padding: 2px 3px; + text-align: center; +} + +#stats:nth-child(2n) { + display: inline-block; + margin-top: 15px; + border: 1px solid #eee; + padding: 10px; + -webkit-box-shadow: inset 0 0 2px #eee; + -moz-box-shadow: inset 0 0 2px #eee; + box-shadow: inset 0 0 2px #eee; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +#stats div { + float: left; + padding: 0 5px; +} + +#stats::after { + display: block; + content: ''; + clear: both; +} + +#stats .sloc::after { + content: ' SLOC'; + color: #b6b6b6; +} + +#stats .percentage::after { + content: ' coverage'; + color: #b6b6b6; +} + +#stats .hits, +#stats .misses { + display: none; +} + +.high { + color: #00d4b4; +} +.medium { + color: #e87d0d; +} +.low { + color: #d4081a; +} +.terrible { + color: #d4081a; + font-weight: bold; +} + +table { + width: 80%; + margin-top: 10px; + border-collapse: collapse; + border: 1px solid #cbcbcb; + color: #363636; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +table thead { + display: none; +} + +table td.line, +table td.hits { + width: 20px; + background: #eaeaea; + text-align: center; + font-size: 11px; + padding: 0 10px; + color: #949494; +} + +table td.hits { + width: 10px; + padding: 2px 5px; + color: rgba(0,0,0,.2); + background: #f0f0f0; +} + +tr.miss td.line, +tr.miss td.hits { + background: #e6c3c7; +} + +tr.miss td { + background: #f8d5d8; +} + +td.source { + padding-left: 15px; + line-height: 15px; + white-space: pre; + font: 12px monaco, monospace; +} + +code .comment { color: #ddd } +code .init { color: #2F6FAD } +code .string { color: #5890AD } +code .keyword { color: #8A6343 } +code .number { color: #2F6FAD } +</style> +</head><body><div id="coverage"><h1 id="overview">Coverage</h1><div id="menu"><li><a href="#overview">overview</a></li><li><span class="cov medium">52</span><a href="#/var/www/mpinjs/lib/mpin.js"><span class="dirname">/var/www/mpinjs/lib/</span><span class="basename">mpin.js</span></a></li><a id="logo" href="http://mochajs.org/">m</a></div><div id="stats" class="medium"><div class="percentage">52%</div><div class="sloc">109</div><div class="hits">57</div><div class="misses">52</div></div><div id="files"><div class="file"><h2 id="/var/www/mpinjs/lib/mpin.js">/var/www/mpinjs/lib/mpin.js</h2><div id="stats" class="medium"><div class="percentage">52%</div><div class="sloc">109</div><div class="hits">57</div><div class="misses">52</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr class="hit"><td class="line">1</td><td class="hits">1</td><td class="source">var mpinjs = (function () {</td></tr><tr class="hit"><td class="line">2</td><t d class="hits">1</td><td class="source"> var Mpin, Users = {}, Errors = [];</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">4</td><td class="hits">1</td><td class="source"> Errors[1] = "Invalid userId.";</td></tr><tr class="hit"><td class="line">5</td><td class="hits">1</td><td class="source"> Errors[2] = "UserId does not exist.";</td></tr><tr class="hit"><td class="line">6</td><td class="hits">1</td><td class="source"> Errors[3] = "Missing parameter.";</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">8</td><td class="hits">1</td><td class="source"> Errors[4] = "UserId are not verified.";</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">10</td><td class="hits">1</td><td class="source"> Mpin = function (options) {</td></tr><t r class="hit"><td class="line">11</td><td class="hits">5</td><td class="source"> if (!options || !options.settingsUrl) {</td></tr><tr class="hit"><td class="line">12</td><td class="hits">1</td><td class="source"> return new Error("Missing settings URL");</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">15</td><td class="hits">4</td><td class="source"> this.opts = options;</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">18</td><td class="hits">1</td><td class="source"> Mpin.prototype.debug = true;</td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">20</td><td class="hits">1</td><td cla ss="source"> Mpin.prototype.init = function (cb) {</td></tr><tr class="hit"><td class="line">21</td><td class="hits">5</td><td class="source"> var self = this;</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">23</td><td class="hits">5</td><td class="source"> this.request({url: this.opts.settingsUrl}, function (err, data) {</td></tr><tr class="hit"><td class="line">24</td><td class="hits">3</td><td class="source"> if (err && cb) {</td></tr><tr class="hit"><td class="line">25</td><td class="hits">1</td><td class="source"> return cb(err, null);</td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">28</td><td class="hits">2</td><td class="source"> self.ready = true;</td></tr><tr class="hit"><td class="line">29</td><td class="hits">2 </td><td class="source"> self.opts = data;</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">31</td><td class="hits">2</td><td class="source"> cb && cb(null, data);</td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">35</td><td class="hits">1</td><td class="source"> Mpin.prototype.makeNewUser = function (userId, deviceId) {</td></tr><tr class="hit"><td class="line">36</td><td class="hits">4</td><td class="source"> if (!userId) {</td></tr><tr class="hit"><td class="line">37</td><td class="hits">1</td><td class="source"> return {error: 1};</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">3 9</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">40</td><td class="hits">3</td><td class="source"> Users[userId] = {</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> userId: userId,</td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> deviceId: deviceId || "",</td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> status: "STARTED"</td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">45</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">46</td><td class="hits">3</td><td class="source"> return this;</td></tr><tr><td class="line">47</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">49</td><td class="hits">1 </td><td class="source"> Mpin.prototype.startRegistration = function (userId, cb) {</td></tr><tr class="hit"><td class="line">50</td><td class="hits">4</td><td class="source"> var _reqData = {}, self = this;</td></tr><tr class="hit"><td class="line">51</td><td class="hits">4</td><td class="source"> if (!userId || typeof userId != "string") {</td></tr><tr class="hit"><td class="line">52</td><td class="hits">1</td><td class="source"> return cb ? cb({error: 1}, null) : {error: 1};</td></tr><tr class="hit"><td class="line">53</td><td class="hits">3</td><td class="source"> } else if (!this.checkUser(userId)) {</td></tr><tr class="hit"><td class="line">54</td><td class="hits">1</td><td class="source"> return cb({error: 2}, null);</td></tr><tr class="hit"><td class="line">55</td><td class="hits">2</td><td class="source"> } else if (!this.opts.registerURL) {</td></tr><tr class="hit"><td class="line">56</td><td class="hits">1</td><td class="source"> retu rn cb({error: 3, message: "Missing registerURL"}, null);</td></tr><tr><td class="line">57</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">58</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">59</td><td class="hits">1</td><td class="source"> _reqData.url = this.opts.registerURL;</td></tr><tr class="hit"><td class="line">60</td><td class="hits">1</td><td class="source"> _reqData.type = "PUT";</td></tr><tr class="hit"><td class="line">61</td><td class="hits">1</td><td class="source"> _reqData.data = {</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> userId: userId,</td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> mobile: 0</td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">65</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td clas s="line">66</td><td class="hits">1</td><td class="source"> this.request(_reqData, function (err, data) {</td></tr><tr class="hit"><td class="line">67</td><td class="hits">1</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">68</td><td class="hits">0</td><td class="source"> return cb(err, null);</td></tr><tr><td class="line">69</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">70</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">71</td><td class="hits">1</td><td class="source"> self.addToUser(userId, {regOTT: data.regOTT, mpinId: data.mpinId});</td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> //force activate</td></tr><tr class="hit"><td class="line">74</td><td class="hits">1</td><td class="source"> if (data.active) {</td></tr><tr class="miss"><td c lass="line">75</td><td class="hits">0</td><td class="source"> self.addToUser(userId, {status: "ACTIVATED"});</td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">78</td><td class="hits">1</td><td class="source"> cb && cb(null, true);</td></tr><tr><td class="line">79</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">80</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">81</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">82</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">83</td><td class="hits"></td><td class="source"> //request cs1 + cs2</td></tr><tr class="hit"><td class="line">84</td><td class="hits">1</td><td class="source"> Mpin.prototype.confirmRegistration = function (userId, c b) {</td></tr><tr class="miss"><td class="line">85</td><td class="hits">0</td><td class="source"> var _cs1Url = "", self = this;</td></tr><tr><td class="line">86</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">87</td><td class="hits">0</td><td class="source"> _cs1Url = this.opts.signatureURL + "/";</td></tr><tr class="miss"><td class="line">88</td><td class="hits">0</td><td class="source"> _cs1Url += Users[userId].mpinId; //identity</td></tr><tr class="miss"><td class="line">89</td><td class="hits">0</td><td class="source"> _cs1Url += "?regOTT=" + Users[userId].regOTT;</td></tr><tr><td class="line">90</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source"> //req cs1</td></tr><tr class="miss"><td class="line">92</td><td class="hits">0</td><td class="source"> this.request({url: _cs1Url}, function (err, cs1Data) {</td></tr><tr c lass="miss"><td class="line">93</td><td class="hits">0</td><td class="source"> var _cs2Url = "";</td></tr><tr class="miss"><td class="line">94</td><td class="hits">0</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">95</td><td class="hits">0</td><td class="source"> if (err.status == 401) {</td></tr><tr class="miss"><td class="line">96</td><td class="hits">0</td><td class="source"> return cb({error: 2, message: "Identity not activate."}, null);</td></tr><tr><td class="line">97</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">98</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">99</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">100</td><td class="hits">0</td><td class="source"> self.addToUser(userId, {cs1: cs1Data.clientSecretShare, csParams: cs1Data.params, status: "ACTIVATED"});</td></t r><tr class="miss"><td class="line">101</td><td class="hits">0</td><td class="source"> _cs2Url = self.opts.certivoxURL + "clientSecret?" + cs1Data.params;</td></tr><tr><td class="line">102</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">103</td><td class="hits"></td><td class="source"> //req cs2</td></tr><tr class="miss"><td class="line">104</td><td class="hits">0</td><td class="source"> self.request({url: _cs2Url}, function (err, cs2Data) {</td></tr><tr class="miss"><td class="line">105</td><td class="hits">0</td><td class="source"> var csHex;</td></tr><tr class="miss"><td class="line">106</td><td class="hits">0</td><td class="source"> self.addToUser(userId, {cs2: cs2Data.clientSecret});</td></tr><tr class="miss"><td class="line">107</td><td class="hits">0</td><td class="source"> csHex = MPINAuth.addShares(cs2Data.clientSecret, cs1Data.clientSecretShare);</td></tr><tr><td class="line">108</td><td class="hits "></td><td class="source"> </td></tr><tr class="miss"><td class="line">109</td><td class="hits">0</td><td class="source"> self.addToUser(userId, {csHex: csHex});</td></tr><tr><td class="line">110</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">111</td><td class="hits">0</td><td class="source"> cb(null, true);</td></tr><tr><td class="line">112</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">113</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">114</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">115</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">116</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">117</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">118</td><td class="hits">1</td><td class="source"> Mpin.prototype.finishRegistration = function (userId, pin) {</td></tr><tr class="miss"><td class="line">119</td><td class="hits">0</td><td class="source"> var _user, tokenHex;</td></tr><tr><td class="line">120</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">121</td><td class="hits">0</td><td class="source"> _user = this.getUser(userId);</td></tr><tr><td class="line">122</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">123</td><td class="hits">0</td><td class="source"> if (_user.status !== "ACTIVATED") {</td></tr><tr class="miss"><td class="line">124</td><td class="hits">0</td><td class="source"> return {error: 3};</td></tr><tr><td class="line">125</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">126</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">127</td><td class="hits">0</td><td class="source"> tokenHex = MPINAuth.calculateMPinToken (Users[userId].mpinId, pin, Users[userId].csHex);</td></tr><tr class="miss"><td class="line">128</td><td class="hits">0</td><td class="source"> this.addToUser(userId, {tokenHex: tokenHex, status: "REGISTER"});</td></tr><tr><td class="line">129</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">130</td><td class="hits">0</td><td class="source"> return tokenHex;</td></tr><tr><td class="line">131</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">132</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">133</td><td class="hits"></td><td class="source"> //Put user / mpinId</td></tr><tr class="hit"><td class="line">134</td><td class="hits">1</td><td class="source"> Mpin.prototype.restartRegistration = function (userId, deviceId, cb) {</td></tr><tr class="miss"><td class="line">135</td><td class="hits">0</td><td class="source"> var err = null, data = {};</td></tr><tr class="miss "><td class="line">136</td><td class="hits">0</td><td class="source"> cb(err, data);</td></tr><tr><td class="line">137</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">138</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">139</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">140</td><td class="hits">1</td><td class="source"> Mpin.prototype.listUsers = function () {</td></tr><tr class="miss"><td class="line">141</td><td class="hits">0</td><td class="source"> var listUsers = {};</td></tr><tr class="miss"><td class="line">142</td><td class="hits">0</td><td class="source"> for (var uKey in Users) {</td></tr><tr class="miss"><td class="line">143</td><td class="hits">0</td><td class="source"> listUsers[uKey] = {</td></tr><tr><td class="line">144</td><td class="hits"></td><td class="source"> userId: Users[uKey].userId,</td></tr><tr><td class="line">145</td><td class="hits" ></td><td class="source"> deviceId: >Users[uKey].deviceId,</td></tr><tr><td class="line">146</td><td >class="hits"></td><td class="source"> status: >Users[uKey].status</td></tr><tr><td class="line">147</td><td >class="hits"></td><td class="source"> };</td></tr><tr><td >class="line">148</td><td class="hits"></td><td class="source"> >}</td></tr><tr class="miss"><td class="line">149</td><td >class="hits">0</td><td class="source"> return listUsers;</td></tr><tr><td >class="line">150</td><td class="hits"></td><td class="source"> >};</td></tr><tr><td class="line">151</td><td class="hits"></td><td >class="source"> </td></tr><tr class="hit"><td class="line">152</td><td >class="hits">1</td><td class="source"> Mpin.prototype.checkUser = function >(userId) {</td></tr><tr class="hit"><td class="line">153</td><td >class="hits">5</td><td class="source"> return (Users[userId]) ? true : >false;</td></tr><tr><td class="line">154</td><td class="hits"></td><td >class="source"> };</td>< /tr><tr><td class="line">155</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">156</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">157</td><td class="hits">1</td><td class="source"> Mpin.prototype.getUser = function (userId) {</td></tr><tr class="miss"><td class="line">158</td><td class="hits">0</td><td class="source"> var _user = {};</td></tr><tr class="miss"><td class="line">159</td><td class="hits">0</td><td class="source"> if (!userId) {</td></tr><tr class="miss"><td class="line">160</td><td class="hits">0</td><td class="source"> return {error: 4};</td></tr><tr class="miss"><td class="line">161</td><td class="hits">0</td><td class="source"> } else if (!this.checkUser(userId)) {</td></tr><tr class="miss"><td class="line">162</td><td class="hits">0</td><td class="source"> return {error: 2};</td></tr><tr><td class="line">163</td><td class="hits"></td><td class="source"> }</td></tr><tr><td cla ss="line">164</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">165</td><td class="hits">0</td><td class="source"> _user = {</td></tr><tr><td class="line">166</td><td class="hits"></td><td class="source"> userId: Users[userId].userId,</td></tr><tr><td class="line">167</td><td class="hits"></td><td class="source"> deviceId: Users[userId].deviceId,</td></tr><tr><td class="line">168</td><td class="hits"></td><td class="source"> status: Users[userId].status</td></tr><tr><td class="line">169</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">170</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">171</td><td class="hits">0</td><td class="source"> return _user;</td></tr><tr><td class="line">172</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">173</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="li ne">174</td><td class="hits">1</td><td class="source"> Mpin.prototype.addToUser = function (userId, userProps) {</td></tr><tr class="hit"><td class="line">175</td><td class="hits">1</td><td class="source"> if (!this.checkUser(userId)) {</td></tr><tr class="miss"><td class="line">176</td><td class="hits">0</td><td class="source"> return false;</td></tr><tr><td class="line">177</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">178</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">179</td><td class="hits">1</td><td class="source"> for (var uKey in userProps) {</td></tr><tr class="hit"><td class="line">180</td><td class="hits">2</td><td class="source"> Users[userId][uKey] = userProps[uKey];</td></tr><tr><td class="line">181</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">182</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">183</td><td cla ss="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">184</td><td class="hits">1</td><td class="source"> Mpin.prototype.restore = function () {</td></tr><tr class="hit"><td class="line">185</td><td class="hits">1</td><td class="source"> Users = {};</td></tr><tr><td class="line">186</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">187</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">188</td><td class="hits"></td><td class="source">//{url: url, type: "get post put", data: data}</td></tr><tr class="hit"><td class="line">189</td><td class="hits">1</td><td class="source"> Mpin.prototype.request = function (options, cb) {</td></tr><tr class="miss"><td class="line">190</td><td class="hits">0</td><td class="source"> var _request = new XMLHttpRequest(), _url, _type, _data;</td></tr><tr class="miss"><td class="line">191</td><td class="hits">0</td><td class="source"> _url = options.url || &q uot;";</td></tr><tr class="miss"><td class="line">192</td><td class="hits">0</td><td class="source"> _type = options.type || "GET";</td></tr><tr class="miss"><td class="line">193</td><td class="hits">0</td><td class="source"> _data = options.data || "";</td></tr><tr><td class="line">194</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">195</td><td class="hits">0</td><td class="source"> _request.onreadystatechange = function () {</td></tr><tr class="miss"><td class="line">196</td><td class="hits">0</td><td class="source"> if (_request.readyState === 4 && _request.status === 200) {</td></tr><tr class="miss"><td class="line">197</td><td class="hits">0</td><td class="source"> cb(null, JSON.parse(_request.responseText));</td></tr><tr class="miss"><td class="line">198</td><td class="hits">0</td><td class="source"> } else if (_request.readyState === 4) {</td></tr><tr class="miss"><td class="l ine">199</td><td class="hits">0</td><td class="source"> cb({status: _request.status}, null);</td></tr><tr><td class="line">200</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">201</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">202</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">203</td><td class="hits">0</td><td class="source"> _request.open(_type, _url, true);</td></tr><tr class="miss"><td class="line">204</td><td class="hits">0</td><td class="source"> _request.send(JSON.stringify(_data || ""));</td></tr><tr><td class="line">205</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">206</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">207</td><td class="hits">1</td><td class="source"> return Mpin;</td></tr><tr><td class="line">208</td><td class="hits"></td><td class="source">})();</td> </tr><tr><td class="line">209</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">210</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">211</td><td class="hits"></td><td class="source">//module.exports = mpinjs;</td></tr><tr><td class="line">212</td><td class="hits"></td><td class="source">//http://www.matteoagosti.com/blog/2013/02/24/writing-javascript-modules-for-both-browser-and-node/</td></tr><tr class="hit"><td class="line">213</td><td class="hits">1</td><td class="source">if (typeof module !== 'undefined' && typeof module.exports !== 'undefined')</td></tr><tr class="hit"><td class="line">214</td><td class="hits">1</td><td class="source"> module.exports = mpinjs;</td></tr><tr><td class="line">215</td><td class="hits"></td><td class="source">else</td></tr><tr class="miss"><td class="line">216</td><td class="hits">0</td><td class="source"> window.mpinjs = mpinjs;</td></tr></tbody></table></div></div></div></body></html > \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/blob/67ed8ebe/test/index.js ---------------------------------------------------------------------- diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..55ea634 --- /dev/null +++ b/test/index.js @@ -0,0 +1,153 @@ +//if browser +if (typeof require !== 'undefined') { + var expect = require('chai').expect; + var mpinjs = require('../index'); + var sinon = require('sinon'); + var sinonChai = require('sinon-chai'); +} + +describe('# Constructor initialization without settingsUrl.', function () { + it('should throw Error', function () { + var mpin = new mpinjs(); + expect(mpin).to.be.an.instanceof(Error); + }); +}); + +//spy cases +describe('# Normal iniatilization.', function () { + var mpin, spy, settingsUrl = "http://192.168.10.63:8005/rps/clientSettings"; + + before(function () { + mpin = new mpinjs({settingsUrl: settingsUrl}); + spy = sinon.spy(); + + mpin.request = spy; + }); + + it('should call request method once', function () { + mpin.init(); + expect(spy.calledOnce).to.be.true; + }); + + it('should call request method with settingsUrl params', function () { + mpin.init(); + expect(spy.calledWith({url: settingsUrl})).to.be.true; + }); +}); + +describe('# Init method > clientSettings request.', function () { + var mpin, settingsUrl = "http://192.168.10.63:8005/rps/clientSettings"; + + before(function () { + mpin = new mpinjs({settingsUrl: settingsUrl}); + + this.fakeRes = { + requestOTP: false, + mpinAuthServerURL: "http://192.168.10.63:8011/rps", + registerUrl: "http://192.168.10.63:8011/rps/user" + }; + }); + +//restore request + afterEach(function (done) { + mpin.request.restore(); + done(); + }); + + it('should return error if init response is wrong', function (done) { + sinon.stub(mpin, 'request').yields({}, null); + mpin.init(function (err, data) { + expect(err).to.exist; + done(); + }); + }); + + it('should store init response into internal property', function (done) { + sinon.stub(mpin, 'request').yields(null, JSON.stringify(this.fakeRes)); + mpin.init(function (err, data) { + expect(mpin.opts).to.deep.equal(data); + done(); + }); + }); + +}); + +describe('# makeNewUser checks.', function () { + var mpin, settingsUrl = "http://192.168.10.63:8005/rps/clientSettings"; + + before(function () { + mpin = new mpinjs({settingsUrl: settingsUrl}); + }); + + after(function () { + mpin.restore(); + }); + + it('should makeNewUser return error when call without userId', function () { + var user = mpin.makeNewUser(); + expect(user).to.deep.equal({error: 1}); + }); + + it('should store user into internal list', function () { + var userId = "[email protected]"; + mpin.makeNewUser(userId); + expect(mpin.checkUser(userId)).to.be.true; + }); +}); + +describe('# startRegistration.', function () { + var mpin, settingsUrl = "http://192.168.10.63:8005/rps/clientSettings"; + + before(function () { + mpin = new mpinjs({settingsUrl: settingsUrl}); + + this.fakeRes = { + requestOTP: false, + mpinAuthServerURL: "http://192.168.10.63:8011/rps", + registerURL: "http://192.168.10.63:8011/rps/user" + }; + }); + + it('should return error 1, call without userId', function (done) { + mpin.startRegistration(null, function (err, data) { + expect(err).to.deep.equal({error: 1}); + done(); + }); + }); + + it('should return error 2 if skip makeNewUser method.', function (done) { + var userId = "[email protected]"; + mpin.startRegistration(userId, function (err, data) { + expect(err).to.deep.equal({error: 2}); + done(); + }); + }); + + it('should return error 3 if skip init method.', function (done) { + var userId = "[email protected]"; + mpin.makeNewUser(userId); + mpin.startRegistration(userId, function (err, data) { + expect(err).to.exist; + done(); + }); + }); + + it('should return OK.', function (done) { + var userId = "[email protected]"; + + //mock for init method + sinon.stub(mpin, 'request').yields(null, this.fakeRes); + + mpin.init(function (err, data) { + + mpin.makeNewUser(userId); + mpin.startRegistration(userId, function (err1, data1) { + expect(data).to.exist; + done(); + }); + }); + }); + + + +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/blob/67ed8ebe/test/mocha.opts ---------------------------------------------------------------------- diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 0000000..7179157 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1,2 @@ +--recursive +--timeout 5000 \ No newline at end of file
