diff --git a/browserid/lib/db.js b/browserid/lib/db.js index 482fad4c1d92afa2b94ae982959d540a6f880571..6f235b33f026154ad4e221e1316c4b5060db3db1 100644 --- a/browserid/lib/db.js +++ b/browserid/lib/db.js @@ -103,9 +103,12 @@ exports.emailKnown = function(email, cb) { }); }; -// XXX: should be moved to async. -exports.isStaged = function(email) { - return g_stagedEmails.hasOwnProperty(email); +exports.isStaged = function(email, cb) { + if (cb) { + setTimeout(function() { + cb(g_stagedEmails.hasOwnProperty(email)); + }, 0); + } }; function generateSecret() { @@ -174,7 +177,7 @@ exports.addKeyToEmail = function(existing_email, email, pubkey, cb) { } /* takes an argument object including email, password hash, and pubkey. */ -exports.stageUser = function(obj) { +exports.stageUser = function(obj, cb) { var secret = generateSecret(); // overwrite previously staged users @@ -186,12 +189,11 @@ exports.stageUser = function(obj) { }; g_stagedEmails[obj.email] = secret; - return secret; + setTimeout(function() { cb(secret); }, 0); }; /* takes an argument object including email, pass, and pubkey. */ -// XXX: change to async -exports.stageEmail = function(existing_email, new_email, pubkey) { +exports.stageEmail = function(existing_email, new_email, pubkey, cb) { var secret = generateSecret(); // overwrite previously staged users g_staged[secret] = { @@ -201,7 +203,7 @@ exports.stageEmail = function(existing_email, new_email, pubkey) { pubkey: pubkey }; g_stagedEmails[new_email] = secret; - return secret; + setTimeout(function() { cb(secret); }, 0); }; /* invoked when a user clicks on a verification URL in their email */ diff --git a/browserid/lib/wsapi.js b/browserid/lib/wsapi.js index 981d12c0f2027f1af5fa59b2afae28ec0eeb1e9f..a2a92233830ebaa4358d36e773c2850271072761 100644 --- a/browserid/lib/wsapi.js +++ b/browserid/lib/wsapi.js @@ -72,27 +72,26 @@ function setup(app) { try { // upon success, stage_user returns a secret (that'll get baked into a url // and given to the user), on failure it throws - var secret = db.stageUser(stageParams); - - // store the email being registered in the session data - if (!req.session) req.session = {}; - - // store inside the session the details of this pending verification - req.session.pendingVerification = { - email: stageParams.email, - hash: stageParams.hash // we must store both email and password to handle the case where - // a user re-creates an account - specifically, registration status - // must ensure the new credentials work to properly verify that - // the user has clicked throught the email link. note, this salted, bcrypted - // representation of a user's password will get thrust into an encrypted cookie - // served over an encrypted (SSL) session. guten, yah. - }; + db.stageUser(stageParams, function(secret) { + // store the email being registered in the session data + if (!req.session) req.session = {}; - httputils.jsonResponse(resp, true); + // store inside the session the details of this pending verification + req.session.pendingVerification = { + email: stageParams.email, + hash: stageParams.hash // we must store both email and password to handle the case where + // a user re-creates an account - specifically, registration status + // must ensure the new credentials work to properly verify that + // the user has clicked throught the email link. note, this salted, bcrypted + // representation of a user's password will get thrust into an encrypted cookie + // served over an encrypted (SSL) session. guten, yah. + }; - // let's now kick out a verification email! - email.sendVerificationEmail(stageParams.email, stageParams.site, secret); + httputils.jsonResponse(resp, true); + // let's now kick out a verification email! + email.sendVerificationEmail(stageParams.email, stageParams.site, secret); + }); } catch(e) { // we should differentiate tween' 400 and 500 here. httputils.badRequest(resp, e.toString()); @@ -130,7 +129,6 @@ function setup(app) { } else { // this is a pending registration, let's check if the creds stored on the // session are good yet. - var v = req.session.pendingVerification; db.checkAuth(v.email, function(hash) { if (hash === v.hash) { @@ -162,17 +160,17 @@ function setup(app) { app.post('/wsapi/add_email', checkAuthed, checkParams(["email", "pubkey", "site"]), function (req, resp) { try { - // upon success, stage_user returns a secret (that'll get baked into a url - // and given to the user), on failure it throws - var secret = db.stageEmail(req.session.authenticatedUser, req.body.email, req.body.pubkey); + // on failure stageEmail may throw + db.stageEmail(req.session.authenticatedUser, req.body.email, req.body.pubkey, function(secret) { - // store the email being added in session data - req.session.pendingAddition = req.body.email; + // store the email being added in session data + req.session.pendingAddition = req.body.email; - httputils.jsonResponse(resp, true); + httputils.jsonResponse(resp, true); - // let's now kick out a verification email! - email.sendVerificationEmail(req.body.email, req.body.site, secret); + // let's now kick out a verification email! + email.sendVerificationEmail(req.body.email, req.body.site, secret); + }); } catch(e) { // we should differentiate tween' 400 and 500 here. httputils.badRequest(resp, e.toString()); diff --git a/browserid/tests/db-test.js b/browserid/tests/db-test.js index bd7afd9145bf30bb15b9d2d0f9c6a645b1c353be..04c72b350eb6e2c699d8905776e145889a3ca9e0 100755 --- a/browserid/tests/db-test.js +++ b/browserid/tests/db-test.js @@ -32,7 +32,7 @@ var secret = undefined; suite.addBatch({ "an email address is not reported as staged before it is": { topic: function() { - return db.isStaged('lloyd@nowhe.re'); + db.isStaged('lloyd@nowhe.re', this.callback); }, "isStaged returns false": function (r) { assert.strictEqual(r, false); @@ -51,13 +51,14 @@ suite.addBatch({ suite.addBatch({ "stage a user for creation pending verification": { topic: function() { - return secret = db.stageUser({ + db.stageUser({ email: 'lloyd@nowhe.re', pubkey: 'fakepubkey', hash: 'fakepasswordhash' - }); + }, this.callback); }, "staging returns a valid secret": function(r) { + secret = r; assert.isString(secret); assert.strictEqual(secret.length, 48); } @@ -67,7 +68,7 @@ suite.addBatch({ suite.addBatch({ "an email address is reported": { topic: function() { - return db.isStaged('lloyd@nowhe.re'); + db.isStaged('lloyd@nowhe.re', this.callback); }, " as staged after it is": function (r) { assert.strictEqual(r, true); @@ -97,7 +98,7 @@ suite.addBatch({ suite.addBatch({ "an email address is not reported": { topic: function() { - return db.isStaged('lloyd@nowhe.re'); + db.isStaged('lloyd@nowhe.re', this.callback); }, "as staged immediately after its verified": function (r) { assert.strictEqual(r, false); @@ -161,30 +162,33 @@ suite.addBatch({ suite.addBatch({ "staging an email": { topic: function() { - return db.stageEmail('lloyd@nowhe.re', 'lloyd@somewhe.re', 'fakepubkey4'); + db.stageEmail('lloyd@nowhe.re', 'lloyd@somewhe.re', 'fakepubkey4', this.callback); }, "yields a valid secret": function(secret) { assert.isString(secret); assert.strictEqual(secret.length, 48); }, - "makes email addr via isStaged": { - topic: function() { return db.isStaged('lloyd@somewhe.re'); }, - "visible": function(r) { assert.isTrue(r); } - }, - "and verifying it": { + "then": { topic: function(secret) { - db.gotVerificationSecret(secret, this.callback); - }, - "returns no error": function(r) { - assert.isUndefined(r); - }, - "makes email addr via knownEmail": { - topic: function() { db.emailKnown('lloyd@somewhe.re', this.callback); }, - "visible": function(r) { assert.isTrue(r); } + var cb = this.callback; + db.isStaged('lloyd@somewhe.re', function(r) { cb(secret, r); }); }, - "makes email addr via isStaged": { - topic: function() { return db.isStaged('lloyd@somewhe.re'); }, - "not visible": function(r) { assert.isFalse(r); } + "makes it visible via isStaged": function(sekret, r) { assert.isTrue(r); }, + "and lets you verify it": { + topic: function(secret, r) { + db.gotVerificationSecret(secret, this.callback); + }, + "successfully": function(r) { + assert.isUndefined(r); + }, + "and knownEmail": { + topic: function() { db.emailKnown('lloyd@somewhe.re', this.callback); }, + "returns true": function(r) { assert.isTrue(r); } + }, + "and isStaged": { + topic: function() { db.isStaged('lloyd@somewhe.re', this.callback); }, + "returns false": function(r) { assert.isFalse(r); } + } } } }