diff --git a/browserid/lib/db.js b/browserid/lib/db.js index 4dfef67b704f99e6e94269ecb9dd3a74a47d3e58..891e50e062cfc30c8a0e06ec828151e0c646ad1e 100644 --- a/browserid/lib/db.js +++ b/browserid/lib/db.js @@ -99,6 +99,7 @@ exports.onReady = function(f) { 'stageUser', 'stageEmail', 'gotVerificationSecret', + 'haveVerificationSecret', 'checkAuth', 'listEmails', 'removeEmail', diff --git a/browserid/lib/db_json.js b/browserid/lib/db_json.js index 2a2c21859055b1cc08215aa42030e6a3ba6c23cf..89cc299fec1cd2a95668976ec4c42916e34cdc4a 100644 --- a/browserid/lib/db_json.js +++ b/browserid/lib/db_json.js @@ -151,17 +151,16 @@ function addEmailToAccount(existing_email, email, cb) { }); } -exports.stageUser = function(obj, cb) { +exports.stageUser = function(email, cb) { var secret = secrets.generate(48); // overwrite previously staged users staged[secret] = { type: "add_account", - email: obj.email, - pass: obj.hash + email: email }; - stagedEmails[obj.email] = secret; + stagedEmails[email] = secret; setTimeout(function() { cb(secret); }, 0); }; @@ -177,7 +176,12 @@ exports.stageEmail = function(existing_email, new_email, cb) { setTimeout(function() { cb(secret); }, 0); }; -exports.gotVerificationSecret = function(secret, cb) { + +exports.haveVerificationSecret = function(secret, cb) { + setTimeout(function() { cb(staged.hasOwnProperty(secret)); }, 0); +}; + +exports.gotVerificationSecret = function(secret, hash, cb) { if (!staged.hasOwnProperty(secret)) return cb("unknown secret"); // simply move from staged over to the emails "database" @@ -188,7 +192,7 @@ exports.gotVerificationSecret = function(secret, cb) { exports.emailKnown(o.email, function(known) { function createAccount() { db.push({ - password: o.pass, + password: hash, emails: [ o.email ] }); flush(); diff --git a/browserid/lib/db_mysql.js b/browserid/lib/db_mysql.js index a42489b1ccc28b37631a69788adc1dcac3cca8ec..4f1264ce27a9f07d3ebddbc32a2137c2d81037d4 100644 --- a/browserid/lib/db_mysql.js +++ b/browserid/lib/db_mysql.js @@ -53,7 +53,6 @@ * | bool new_acct | * | string existing | * |*string email | - * | string passwd | * | timestamp ts | * +------------------------+ */ @@ -71,7 +70,7 @@ var drop_on_close = undefined; const schemas = [ "CREATE TABLE IF NOT EXISTS user ( id INTEGER AUTO_INCREMENT PRIMARY KEY, passwd VARCHAR(64) );", "CREATE TABLE IF NOT EXISTS email ( id INTEGER AUTO_INCREMENT PRIMARY KEY, user INTEGER, address VARCHAR(255) UNIQUE, INDEX(address) );", - "CREATE TABLE IF NOT EXISTS staged ( secret VARCHAR(48) PRIMARY KEY, new_acct BOOL, existing VARCHAR(255), email VARCHAR(255) UNIQUE, INDEX(email), passwd VARCHAR(64), ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP);" + "CREATE TABLE IF NOT EXISTS staged ( secret VARCHAR(48) PRIMARY KEY, new_acct BOOL, existing VARCHAR(255), email VARCHAR(255) UNIQUE, INDEX(email), ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP);" ]; // log an unexpected database error @@ -184,12 +183,12 @@ exports.isStaged = function(email, cb) { ); } -exports.stageUser = function(obj, cb) { +exports.stageUser = function(email, cb) { var secret = secrets.generate(48); // overwrite previously staged users - client.query('INSERT INTO staged (secret, new_acct, email, passwd) VALUES(?,TRUE,?,?) ' + - 'ON DUPLICATE KEY UPDATE secret=?, existing="", new_acct=TRUE, passwd=?', - [ secret, obj.email, obj.hash, secret, obj.hash], + client.query('INSERT INTO staged (secret, new_acct, email) VALUES(?,TRUE,?) ' + + 'ON DUPLICATE KEY UPDATE secret=?, existing="", new_acct=TRUE', + [ secret, email, secret], function(err) { if (err) { logUnexpectedError(err); @@ -198,7 +197,16 @@ exports.stageUser = function(obj, cb) { }); } -exports.gotVerificationSecret = function(secret, cb) { +exports.haveVerificationSecret = function(secret, cb) { + client.query( + "SELECT COUNT(*) as N FROM staged WHERE secret = ?", [ email ], + function(err, rows) { + if (err) logUnexpectedError(err); + cb(rows && rows.length > 0 && rows[0].N > 0); + }); +}; + +exports.gotVerificationSecret = function(secret, hash, cb) { client.query( "SELECT * FROM staged WHERE secret = ?", [ secret ], function(err, rows) { @@ -240,7 +248,7 @@ exports.gotVerificationSecret = function(secret, cb) { // we're creating a new account, add appropriate entries into user and email tables. client.query( "INSERT INTO user(passwd) VALUES(?)", - [ o.passwd ], + [ hash ], function(err, info) { if (err) { logUnexpectedError(err); cb(err); return; } addEmailToUser(info.insertId); @@ -277,7 +285,7 @@ exports.stageEmail = function(existing_email, new_email, cb) { var secret = secrets.generate(48); // overwrite previously staged users client.query('INSERT INTO staged (secret, new_acct, existing, email) VALUES(?,FALSE,?,?) ' + - 'ON DUPLICATE KEY UPDATE secret=?, existing=?, new_acct=FALSE, passwd=""', + 'ON DUPLICATE KEY UPDATE secret=?, existing=?, new_acct=FALSE', [ secret, existing_email, new_email, secret, existing_email], function(err) { if (err) { @@ -347,8 +355,11 @@ exports.cancelAccount = function(email, cb) { function (err, rows) { if (err) { logUnexpectedError(err) - cb(err); - return + return cb(err); + } else if (!rows || !rows.length === 1 || typeof rows[0] !== 'object') { + var e = "no user with given account: " + email ; + logUnexpectedError(e) + return cb(e); } var uid = rows[0].user; client.query("DELETE LOW_PRIORITY FROM email WHERE user = ?", [ uid ], reportErr); diff --git a/browserid/tests/db-test.js b/browserid/tests/db-test.js index 156e56020e0d6ff8bb56d46864e3e1202b1e85af..558bc0f901621fcc8264ce677345a9bce045e304 100755 --- a/browserid/tests/db-test.js +++ b/browserid/tests/db-test.js @@ -99,11 +99,7 @@ suite.addBatch({ suite.addBatch({ "stage a user for creation pending verification": { topic: function() { - db.stageUser({ - email: 'lloyd@nowhe.re', - pubkey: 'fakepubkey', - hash: 'fakepasswordhash' - }, this.callback); + db.stageUser('lloyd@nowhe.re', this.callback); }, "staging returns a valid secret": function(r) { secret = r; @@ -135,7 +131,7 @@ suite.addBatch({ suite.addBatch({ "upon receipt of a secret": { topic: function() { - db.gotVerificationSecret(secret, this.callback); + db.gotVerificationSecret(secret, 'fakepasswordhash', this.callback); }, "gotVerificationSecret completes without error": function (r) { assert.strictEqual(r, undefined); @@ -190,7 +186,7 @@ suite.addBatch({ "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); + db.gotVerificationSecret(secret, undefined, this.callback); }, "successfully": function(r) { assert.isUndefined(r);