Merge pull request #463 from dannycoates/normalizeEmail

normalize email on create account using mysql lower()
This commit is contained in:
Danny Coates 2014-01-06 16:46:23 -08:00
Родитель 451ca9b853 9529d929e7
Коммит 1cbbca3206
9 изменённых файлов: 75 добавлений и 19 удалений

Просмотреть файл

@ -63,6 +63,8 @@ module.exports = function (
email: data && data.email
}
)
data.rawEmail = data.email
data.email = data.email.toLowerCase()
this.accounts[data.uid.toString('hex')] = data
this.emailRecords[data.email] = data.uid.toString('hex')
data.devices = {}
@ -134,7 +136,7 @@ module.exports = function (
Heap.prototype.accountExists = function (email) {
log.trace({ op: 'Heap.accountExists', email: email })
return P(!!this.emailRecords[email])
return P(!!this.emailRecords[email.toLowerCase()])
}
Heap.prototype.accountDevices = function (uid) {
@ -201,7 +203,7 @@ module.exports = function (
Heap.prototype.emailRecord = function (email) {
log.trace({ op: 'Heap.emailRecord', email: email })
var uid = this.emailRecords[email]
var uid = this.emailRecords[email.toLowerCase()]
if (!uid) { return P.reject(error.unknownAccount(email)) }
return this.account(uid)
}

Просмотреть файл

@ -134,7 +134,8 @@ module.exports = function (
email: data && data.email
}
)
var sql = 'INSERT INTO accounts (uid, email, emailCode, verified, kA, wrapWrapKb, authSalt, verifyHash) VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
data.rawEmail = data.email
var sql = 'INSERT INTO accounts (uid, email, rawEmail, emailCode, verified, kA, wrapWrapKb, authSalt, verifyHash) VALUES (?, LOWER(?), ?, ?, ?, ?, ?, ?, ?)'
return this.getMasterConnection()
.then(function(con) {
var d = P.defer()
@ -143,6 +144,7 @@ module.exports = function (
[
data.uid,
data.email,
data.rawEmail,
data.emailCode,
data.verified,
data.kA,
@ -296,7 +298,7 @@ module.exports = function (
MySql.prototype.accountExists = function (email) {
log.trace({ op: 'MySql.accountExists', email: email })
var sql = 'SELECT uid FROM accounts WHERE email = ?'
var sql = 'SELECT uid FROM accounts WHERE email = LOWER(?)'
return this.getSlaveConnection()
.then(function(con) {
@ -335,7 +337,7 @@ module.exports = function (
MySql.prototype.sessionToken = function (id) {
log.trace({ op: 'MySql.sessionToken', id: id })
var sql = 'SELECT t.tokendata, t.uid, a.verified, a.email, a.emailCode' +
var sql = 'SELECT t.tokendata, t.uid, a.verified, a.email, a.rawEmail, a.emailCode' +
' FROM sessionTokens t, accounts a WHERE t.tokenid = ? AND t.uid = a.uid'
return this.getSlaveConnection()
.then(function(con) {
@ -415,7 +417,7 @@ module.exports = function (
MySql.prototype.passwordForgotToken = function (id) {
log.trace({ op: 'MySql.passwordForgotToken', id: id })
var sql = 'SELECT t.tokendata, t.uid, a.email, t.passcode, t.created, t.tries ' +
var sql = 'SELECT t.tokendata, t.uid, a.email, a.rawEmail, t.passcode, t.created, t.tries ' +
' FROM passwordForgotTokens t, accounts a WHERE t.tokenid = ? AND t.uid = a.uid'
return this.getSlaveConnection()
.then(function(con) {
@ -469,7 +471,7 @@ module.exports = function (
MySql.prototype.emailRecord = function (email) {
log.trace({ op: 'MySql.emailRecord', email: email })
var sql = 'SELECT uid, verified, emailCode, kA, wrapWrapKb, verifyHash, authSalt FROM accounts WHERE email = ?'
var sql = 'SELECT uid, email, rawEmail, verified, emailCode, kA, wrapWrapKb, verifyHash, authSalt FROM accounts WHERE email = LOWER(?)'
return this.getSlaveConnection()
.then(function(con) {
var d = P.defer()
@ -483,7 +485,8 @@ module.exports = function (
var result = results[0]
return d.resolve({
uid: result.uid,
email: email,
email: result.email,
rawEmail: result.rawEmail,
emailCode: result.emailCode,
verified: !!result.verified,
kA: result.kA,
@ -500,7 +503,7 @@ module.exports = function (
MySql.prototype.account = function (uid) {
log.trace({ op: 'MySql.account', uid: uid })
var sql = 'SELECT email, emailCode, verified, kA, wrapWrapKb, verifyHash, authSalt ' +
var sql = 'SELECT email, rawEmail, emailCode, verified, kA, wrapWrapKb, verifyHash, authSalt ' +
' FROM accounts WHERE uid = ?'
return this.getSlaveConnection()
.then(function(con) {
@ -516,6 +519,7 @@ module.exports = function (
return d.resolve({
uid: uid,
email: result.email,
rawEmail: result.rawEmail,
emailCode: result.emailCode,
verified: !!result.verified,
kA: result.kA,

Просмотреть файл

@ -2,6 +2,7 @@
CREATE TABLE IF NOT EXISTS accounts (
uid BINARY(16) PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE KEY,
rawEmail VARCHAR(255) NOT NULL,
emailCode CHAR(8) NOT NULL,
verified BOOLEAN NOT NULL DEFAULT FALSE,
kA BINARY(32) NOT NULL,

Просмотреть файл

@ -108,11 +108,12 @@ module.exports = function(log) {
})
}
errors.incorrectPassword = function () {
errors.incorrectPassword = function (rawEmail) {
return errors.wrap({
code: 400,
errno: 103,
message: 'Incorrect password'
message: 'Incorrect password',
email: rawEmail
})
}
@ -157,7 +158,7 @@ module.exports = function(log) {
param: param
})
}
errors.invalidSignature = function (message) {
return errors.wrap({
code: 401,

Просмотреть файл

@ -82,7 +82,7 @@ module.exports = function (config, i18n, log) {
}
Mailer.prototype.sendVerifyCode = function (account, code, service, preferredLang) {
log.trace({ op: 'mailer.sendVerifyCode', email: account.email, uid: account.uid })
log.trace({ op: 'mailer.sendVerifyCode', email: account.rawEmail, uid: account.uid })
var template = templates.verify
var link = this.verificationUrl + '?uid=' + account.uid.toString('hex')
if (service) {
@ -98,7 +98,7 @@ module.exports = function (config, i18n, log) {
}
var message = {
sender: this.sender,
to: account.email,
to: account.rawEmail,
subject: values.l10n.gettext(template.subject),
text: template.text(values),
html: template.html(values),
@ -113,7 +113,7 @@ module.exports = function (config, i18n, log) {
}
Mailer.prototype.sendRecoveryCode = function (account, code, preferredLang) {
log.trace({ op: 'mailer.sendRecoveryCode', email: account.email })
log.trace({ op: 'mailer.sendRecoveryCode', email: account.rawEmail })
var template = templates.reset
var values = {
l10n: i18n.localizationContext(preferredLang),
@ -121,7 +121,7 @@ module.exports = function (config, i18n, log) {
}
var message = {
sender: this.sender,
to: account.email,
to: account.rawEmail,
subject: values.l10n.gettext(template.subject),
text: template.text(values),
html: template.html(values),

Просмотреть файл

@ -158,12 +158,13 @@ module.exports = function (log, crypto, P, uuid, isA, error, db, mailer, isProdu
.then(
function (verifyHash) {
if (!buffersAreEqual(verifyHash, emailRecord.verifyHash)) {
throw error.incorrectPassword()
throw error.incorrectPassword(emailRecord.rawEmail)
}
return db.createSessionToken(
{
uid: emailRecord.uid,
email: emailRecord.email,
rawEmail: emailRecord.rawEmail,
emailCode: emailRecord.emailCode,
verified: emailRecord.verified
}

Просмотреть файл

@ -19,7 +19,7 @@ TestServer.start(config.publicUrl)
var email = crypto.randomBytes(10).toString('hex') + '@example.com'
var password = '123456'
var client = null
return Client.create('http://127.0.0.1:9000', email, password, {preVerified: true})
return Client.create(config.publicUrl, email, password, {preVerified: true})
.then(
function (c) {
client = c
@ -91,7 +91,52 @@ TestServer.start(config.publicUrl)
}
)
/*/
test(
test(
'signup with same email, different case',
function (t) {
var email = 'TEST@EXAMPLE.COM'
var email2 = 'test@example.com'
var password = 'abcdef'
return Client.create(config.publicUrl, email, password, { preVerified: true })
.then(
function (c) {
return Client.create(config.publicUrl, email2, password, { preVerified: true })
}
)
.then(
fail,
function (err) {
t.equal(err.code, 400)
t.equal(err.errno, 101, 'Account already exists')
}
)
}
)
test(
'the rawEmail is returned in the error on Incorrect Password errors',
function (t) {
var signupEmail = 'TestX@example.com'
var loginEmail = 'testx@example.com'
var password = 'abcdef'
return Client.create(config.publicUrl, signupEmail, password, { preVerified: true})
.then(
function (c) {
return Client.login(config.publicUrl, loginEmail, password)
}
)
.then(
fail,
function (err) {
t.equal(err.code, 400)
t.equal(err.errno, 103)
t.equal(err.email, signupEmail)
}
)
}
)
test(
'teardown',
function (t) {
server.stop()

Просмотреть файл

@ -9,6 +9,7 @@ module.exports = function (log, inherits, now, Token, crypto) {
function PasswordForgotToken(keys, details) {
Token.call(this, keys, details)
this.email = details.email || null
this.rawEmail = details.rawEmail || null
this.created = details.created || null
this.passcode = details.passcode || null
this.tries = details.tries || null

Просмотреть файл

@ -7,6 +7,7 @@ module.exports = function (log, inherits, Token) {
function SessionToken(keys, details) {
Token.call(this, keys, details)
this.email = details.email || null
this.rawEmail = details.rawEmail || null
this.emailCode = details.emailCode || null
this.verified = !!details.verified
}