Adding missing functionality and fixing bugs
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/4231d489 Tree: http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/tree/4231d489 Diff: http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/diff/4231d489 Branch: refs/heads/add-documentation Commit: 4231d4890fe028eaf013a8df98a3ff7a205a8229 Parents: 3495d12 Author: Simeon Aladjem <[email protected]> Authored: Wed Dec 23 15:53:13 2015 +0200 Committer: Simeon Aladjem <[email protected]> Committed: Wed Dec 23 15:53:13 2015 +0200 ---------------------------------------------------------------------- lib/mpin.js | 190 ++++++++++++++++++++++++++++++----------------------- test/index.js | 8 +-- 2 files changed, 111 insertions(+), 87 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/blob/4231d489/lib/mpin.js ---------------------------------------------------------------------- diff --git a/lib/mpin.js b/lib/mpin.js index 86a110e..865d057 100644 --- a/lib/mpin.js +++ b/lib/mpin.js @@ -18,23 +18,23 @@ */ var mpinjs = (function () { - var Mpin, Users = {}, Error = {}, State = {}; - - Error.missingUserId = {code: 0, type: "MISSING_USERID"}; - Error.invalidUserId = {code: 1, type: "INVALID_USERID"}; - Error.missingParams = {code: 2, type: "MISSING_PARAMETERS"}; - Error.identityNotVerified = {code: 3, type: "IDENTITY_NOT_VERIFIED"}; - Error.identityMissing = {code: 4, type: "IDENTITY_MISSING"}; - Error.wrongPin = {code: 5, type: "WRONG_PIN"}; - Error.wrongFlow = {code: 6, type: "WRONG_FLOW"}; - Error.userRevoked = {code: 7, type: "USER_REVOKED"}; - Error.timeoutFinish = {code: 8, type: "TIMEOUT_FINISH"}; - - State.invalid = "INVALID"; - State.start = "STARTED"; - State.active = "ACTIVATED"; - State.register = "REGISTERED"; - State.block = "BLOCKED"; + var Mpin, Users = {}, Errors = {}, States = {}; + + Errors.missingUserId = {code: 0, type: "MISSING_USERID"}; + Errors.invalidUserId = {code: 1, type: "INVALID_USERID"}; + Errors.missingParams = {code: 2, type: "MISSING_PARAMETERS"}; + Errors.identityNotVerified = {code: 3, type: "IDENTITY_NOT_VERIFIED"}; + Errors.identityMissing = {code: 4, type: "IDENTITY_MISSING"}; + Errors.wrongPin = {code: 5, type: "WRONG_PIN"}; + Errors.wrongFlow = {code: 6, type: "WRONG_FLOW"}; + Errors.userRevoked = {code: 7, type: "USER_REVOKED"}; + Errors.timeoutFinish = {code: 8, type: "TIMEOUT_FINISH"}; + + States.invalid = "INVALID"; + States.start = "STARTED"; + States.active = "ACTIVATED"; + States.register = "REGISTERED"; + States.block = "BLOCKED"; Mpin = function (options) { if (!options || !options.server) { @@ -42,6 +42,7 @@ var mpinjs = (function () { } this.opts = options; + this.settings = {}; this.recover(); }; @@ -65,18 +66,18 @@ var mpinjs = (function () { } self.ready = true; - self.opts = data; + self.settings = data; - cb && cb(null, data); + cb && cb(null, true); }); }; Mpin.prototype.makeNewUser = function (userId, deviceId) { if (!userId) { - return Error.missingUserId; + return Errors.missingUserId; } - this.addToUser(userId, {userId: userId, deviceId: deviceId, state: State.invalid}); + this.addToUser(userId, {userId: userId, deviceId: deviceId, state: States.invalid}); return this; }; @@ -84,11 +85,11 @@ var mpinjs = (function () { Mpin.prototype.startRegistration = function (userId, cb) { var _reqData = {}, self = this; if (!userId) { - return cb ? cb(Error.missingUserId, null) : {error: 1}; + return cb ? cb(Errors.missingUserId, null) : {error: 1}; } else if (!this.checkUser(userId)) { - return cb(Error.invalidUserId, null); - } else if (!this.opts.registerURL) { - return cb({code: Error.missingParams.code, type: Error.missingParams.type, message: "Missing registerURL"}, null); + return cb(Errors.invalidUserId, null); + } else if (!this.settings.registerURL) { + return cb({code: Errors.missingParams.code, type: Errors.missingParams.type, message: "Missing registerURL"}, null); } _reqData.url = this.generateUrl("register"); @@ -103,11 +104,11 @@ var mpinjs = (function () { return cb(err, null); } - self.addToUser(userId, {regOTT: data.regOTT, mpinId: data.mpinId, state: State.start}); + self.addToUser(userId, {regOTT: data.regOTT, mpinId: data.mpinId, state: States.start}); //force activate if (data.active) { - self.addToUser(userId, {state: State.active}); + self.addToUser(userId, {state: States.active}); } cb && cb(null, true); @@ -118,17 +119,17 @@ var mpinjs = (function () { Mpin.prototype.confirmRegistration = function (userId, cb) { var _cs1Url = "", self = this, _userState; if (!userId) { - return cb ? cb(Error.missingUserId, null) : Error.missingUserId; + return cb ? cb(Errors.missingUserId, null) : Errors.missingUserId; } else if (!this.checkUser(userId)) { - return cb(Error.invalidUserId, null); - } else if (!this.opts.signatureURL) { - return cb({code: Error.missingParams.code, type: Error.missingParams.type, message: "Missing signatureURL option."}, null); + return cb(Errors.invalidUserId, null); + } else if (!this.settings.signatureURL) { + return cb({code: Errors.missingParams.code, type: Errors.missingParams.type, message: "Missing signatureURL option."}, null); } //started || activated _userState = this.getUser(userId, "state"); - if (_userState !== State.start && _userState !== State.active) { - return cb(Error.wrongFlow, null); + if (_userState !== States.start && _userState !== States.active) { + return cb(Errors.wrongFlow, null); } //already set. @@ -142,13 +143,13 @@ var mpinjs = (function () { var _cs2Url = ""; if (err) { if (err.status == 401) { - return cb(Error.identityNotVerified, null); + return cb(Errors.identityNotVerified, null); } else if (err.status == 400) { - return cb(Error.wrongFlow, null); + return cb(Errors.wrongFlow, null); } } - _cs2Url = self.opts.certivoxURL + "clientSecret?" + cs1Data.params; + _cs2Url = self.settings.certivoxURL + "clientSecret?" + cs1Data.params; //req cs2 self.request({url: _cs2Url}, function (err, cs2Data) { @@ -156,7 +157,7 @@ var mpinjs = (function () { csHex = MPINAuth.addShares(cs2Data.clientSecret, cs1Data.clientSecretShare); - self.addToUser(userId, {csHex: csHex, state: State.active}); + self.addToUser(userId, {csHex: csHex, state: States.active}); cb(null, true); }); @@ -169,19 +170,19 @@ var mpinjs = (function () { var _user, token; if (!userId) { - return Error.missingUserId; + return Errors.missingUserId; } _user = this.getUser(userId); - if (_user.state !== State.active) { - return Error.wrongFlow; + if (_user.state !== States.active || !Users[userId].csHex) { + return Errors.wrongFlow; } token = MPINAuth.calculateMPinToken(Users[userId].mpinId, pin, Users[userId].csHex); delete Users[userId].csHex; - this.addToUser(userId, {token: token, state: State.register}); + this.addToUser(userId, {token: token, state: States.register}); return true; }; @@ -198,31 +199,35 @@ var mpinjs = (function () { var _tp1Url, self = this, _userState; if (!userId) { - return cb ? cb(Error.missingUserId, null) : Error.missingUserId; + return cb ? cb(Errors.missingUserId, null) : Errors.missingUserId; } else if (!this.checkUser(userId)) { - return cb(Error.invalidUserId, null); - } else if (!this.opts.timePermitsURL || !this.opts.certivoxURL) { - return cb({code: Error.missingParams.code, type: Error.missingParams.type, message: "Missing timePermitsURL or/and certivoxURL option."}, null); + return cb(Errors.invalidUserId, null); + } else if (!this.settings.timePermitsURL || !this.settings.certivoxURL) { + return cb({code: Errors.missingParams.code, type: Errors.missingParams.type, message: "Missing timePermitsURL or/and certivoxURL option."}, null); } //registered _userState = this.getUser(userId, "state"); - if (_userState !== State.register) { - return cb(Error.wrongFlow, null); + if (_userState !== States.register) { + return cb(Errors.wrongFlow, null); } //checkUser _tp1Url = this.generateUrl('permit1', {userId: userId}); this.request({url: _tp1Url}, function (err, data) { + if (err) { + if (err.status === 401 || err.status === 403 || err.status === 410) { + return cb(Errors.userRevoked, null); + } + + return cb(err, null); + } var _signature, _tp2Url, _timePermit1, _storageUrl; _signature = data["signature"]; _timePermit1 = data["timePermit"]; self.addToUser(userId, {currentDate: data['date']}); - _tp2Url = self.generateUrl('permit2', {userId: userId}); - _tp2Url += "&signature=" + _signature; - //check cache if exist if (Users[userId].timePermitCache && Users[userId].timePermitCache.date === data.date) { var _timePermit2 = Users[userId].timePermitCache.timePermit; @@ -236,7 +241,11 @@ var mpinjs = (function () { self.request({url: _storageUrl}, function (storErr, storData) { if (storErr) { + _tp2Url = self.generateUrl('permit2', {userId: userId}); + _tp2Url += "&signature=" + _signature; + self._getTimePermit2({userId: userId, permit1: _timePermit1, permit2Url: _tp2Url, date: data.date}, cb); //continue + return; } @@ -253,7 +262,16 @@ var mpinjs = (function () { Mpin.prototype._getTimePermit2 = function (options, cb) { var self = this, _timePermit1 = options.permit1; + this.request({url: options.permit2Url}, function (err2, data2) { + if (err2) { + if (err2.status === 401 || err2.status === 403 || err2.status === 410) { + return cb(Errors.userRevoked, null); + } + + return cb(err2, null); + } + var _timePermit2, timePermitHex, _permitCache = {}; _timePermit2 = data2["timePermit"]; timePermitHex = MPINAuth.addShares(_timePermit1, _timePermit2); @@ -273,10 +291,10 @@ var mpinjs = (function () { //registered _userState = this.getUser(userId, "state"); - if (_userState !== State.register) { - return cb(Error.wrongFlow, null); + if (_userState !== States.register) { + return cb(Errors.wrongFlow, null); } else if (!Users[userId].timePermitHex) { - return cb({code: Error.wrongFlow.code, type: Error.wrongFlow.type, message: "Need to call startAuthentication method before this."}, null); + return cb({code: Errors.wrongFlow.code, type: Errors.wrongFlow.type, message: "Need to call startAuthentication method before this."}, null); } this._passRequests({userId: userId, aPin: aPin}, cb); @@ -287,10 +305,10 @@ var mpinjs = (function () { //registered _userState = this.getUser(userId, "state"); - if (_userState !== State.register) { - return cb(Error.wrongFlow, null); + if (_userState !== States.register) { + return cb(Errors.wrongFlow, null); } else if (!Users[userId].timePermitHex) { - return cb({code: Error.wrongFlow.code, type: Error.wrongFlow.type, message: "Need to call startAuthentication method before this."}, null); + return cb({code: Errors.wrongFlow.code, type: Errors.wrongFlow.type, message: "Need to call startAuthentication method before this."}, null); } this._passRequests({userId: userId, aPin: aPin, otp: true}, function (err, data) { @@ -360,12 +378,12 @@ var mpinjs = (function () { this.request(_authData, function (authErr, authData) { if (authErr) { if (authErr.status === 401) { - return cb(Error.wrongPin, null); + return cb(Errors.wrongPin, null); } else if (authErr.status === 410) { - opts.userId && self.addToUser(opts.userId, {state: State.block}); - return cb(Error.wrongPin, null); + opts.userId && self.addToUser(opts.userId, {state: States.block}); + return cb(Errors.wrongPin, null); } else { - return cb(Error.wrongPin, null); + return cb(Errors.wrongPin, null); } } @@ -417,16 +435,23 @@ var mpinjs = (function () { } self.webOTT = data.webOTT; - cb && cb(null, {accessNumber: data.accessNumber}); + returnData = { + accessNumber: data.accessNumber, + ttlSeconds: data.ttlSeconds, + localTimeStart: data.localTimeStart/1000, + localTimeEnd: data.localTimeEnd/1000 + }; + + cb && cb(null, returnData); }); }; Mpin.prototype.waitForMobileAuth = function (timeoutSeconds, requestSeconds, cb) { var self = this, _reqData = {}; if (!this.webOTT) { - return cb({code: Error.wrongFlow.code, type: Error.wrongFlow.type, message: "Need to call getAccessNumber method before this."}, null); + return cb({code: Errors.wrongFlow.code, type: Errors.wrongFlow.type, message: "Need to call getAccessNumber method before this."}, null); } else if (!timeoutSeconds) { - return cb({code: Error.missingParams.code, type: Error.missingParams.type, message: "Missing timeout/expiration period(in seconds)."}, null); + return cb({code: Errors.missingParams.code, type: Errors.missingParams.type, message: "Missing timeout/expiration period(in seconds)."}, null); } @@ -450,7 +475,7 @@ var mpinjs = (function () { }, _requestPeriod); return; } else if (self.timeoutPeriod <= 0) { - cb && cb(Error.timeoutFinish, null); + cb && cb(Errors.timeoutFinish, null); return; } } @@ -471,15 +496,15 @@ var mpinjs = (function () { switch (type) { case "register": - url = this.opts.registerURL; + url = this.settings.registerURL; break; case "signature": - url = this.opts.signatureURL + "/"; + url = this.settings.signatureURL + "/"; url += Users[options.userId].mpinId; url += "?regOTT=" + Users[options.userId].regOTT; break; case "permit1": - url = this.opts.timePermitsURL + "/"; + url = this.settings.timePermitsURL + "/"; url += Users[options.userId].mpinId; break; case "permit2": @@ -487,30 +512,29 @@ var mpinjs = (function () { mpin_id_bytes = MPIN.stringtobytes(mpData); hash_mpin_id_bytes = MPIN.HASH_ID(mpin_id_bytes); hash_mpin_id_hex = MPIN.bytestostring(hash_mpin_id_bytes); - url = this.opts.certivoxURL + "timePermit"; - url += "?app_id=" + this.opts.appID; + url = this.settings.certivoxURL + "timePermit"; + url += "?app_id=" + this.settings.appID; url += "&mobile=0"; url += "&hash_mpin_id=" + hash_mpin_id_hex; break; case "pass1": - url = this.opts.mpinAuthServerURL + "/pass1"; + url = this.settings.mpinAuthServerURL + "/pass1"; break; case "pass2": - url = this.opts.mpinAuthServerURL + "/pass2"; + url = this.settings.mpinAuthServerURL + "/pass2"; break; case "auth": - url = this.opts.authenticateURL; + url = this.settings.authenticateURL; break; case "getnumber": - url = this.opts.getAccessNumberURL; + url = this.settings.getAccessNumberURL; break; case "getaccess": - url = this.opts.accessNumberURL; + url = this.settings.accessNumberURL; break; case "storage": - url = this.opts.timePermitsStorageURL + "/" + this.opts.appID + "/"; + url = this.settings.timePermitsStorageURL + "/" + this.settings.appID + "/"; url += options.date + "/" + options.storageId; - //return that.opts.timePermitsStorageURL + "/" + that.opts.appID + "/" + date + "/" + storageId; break; } @@ -518,13 +542,13 @@ var mpinjs = (function () { }; Mpin.prototype.listUsers = function () { - var listUsers = {}; + var listUsers = []; for (var uKey in Users) { - listUsers[uKey] = { + listUsers.push({ userId: Users[uKey].userId, deviceId: Users[uKey].deviceId || "", state: Users[uKey].state || "" - }; + }); } return listUsers; }; @@ -536,9 +560,9 @@ var mpinjs = (function () { Mpin.prototype.getUser = function (userId, property) { var _user = {}; if (!userId) { - return Error.missingUserId; + return Errors.missingUserId; } else if (!this.checkUser(userId)) { - return Error.invalidUserId; + return Errors.invalidUserId; } _user = { @@ -559,9 +583,9 @@ var mpinjs = (function () { var mpinData = this.getData(), delMpinId; if (!userId) { - return Error.missingUserId; + return Errors.missingUserId; } else if (!this.checkUser(userId)) { - return Error.invalidUserId; + return Errors.invalidUserId; } delMpinId = Users[userId].mpinId; http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/blob/4231d489/test/index.js ---------------------------------------------------------------------- diff --git a/test/index.js b/test/index.js index b5e311e..0bb83b8 100644 --- a/test/index.js +++ b/test/index.js @@ -91,7 +91,7 @@ describe('# Init method > clientSettings request.', function () { 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); + expect(data).to.be.true; done(); }); }); @@ -265,7 +265,7 @@ describe('# confirmRegistration.', function () { mpin.init(function (err, data) { mpin.makeNewUser(userId); mpin.startRegistration(userId, function (err1, data1) { - mpin.confirmRegistration(userId, function (err2, data3) { + mpin.confirmRegistration(userId, function (err2, data2) { expect(err2).to.have.deep.property('type', Errors[3]); done(); }); @@ -286,8 +286,8 @@ describe('# confirmRegistration.', function () { mpin.init(function (err, data) { mpin.makeNewUser(userId); mpin.startRegistration(userId, function (err1, data1) { - mpin.confirmRegistration(userId, function (err2, data3) { - expect(data3).to.exist; + mpin.confirmRegistration(userId, function (err2, data2) { + expect(data2).to.exist; done(); }); });
