Merge pull request #1653 from mozilla/phil/auto-unbuffer

feat(server): auto-unbuffer binary data when crossing API boundaries
refactor(server): unify the unbuffering functions to one place

https://github.com/mozilla/fxa-auth-server/pull/1653

r=vbudhram
This commit is contained in:
Phil Booth 2017-02-11 11:47:10 +00:00 коммит произвёл GitHub
Родитель d9b6bd96cb a649b78d9a
Коммит 64b3a368bf
4 изменённых файлов: 89 добавлений и 103 удалений

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

@ -2,7 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var HEX = /^(?:[a-fA-F0-9]{2})+$/
'use strict'
const HEX = /^(?:[a-fA-F0-9]{2})+$/
module.exports.ONES = Buffer('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 'hex')
@ -32,14 +34,26 @@ module.exports.xorBuffers = function xorBuffers(buffer1, buffer2) {
return result
}
module.exports.unbuffer = function unbuffer(object, inplace) {
var keys = Object.keys(object)
var copy = inplace ? object : {}
for (var i = 0; i < keys.length; i++) {
var x = object[keys[i]]
copy[keys[i]] = Buffer.isBuffer(x) ? x.toString('hex') : x
module.exports.unbuffer = (object, inplace) => {
return Object.keys(object).reduce((unbuffered, key) => {
unbuffered[key] = unbufferDatum.call(object, key, object[key])
return unbuffered
}, inplace ? object : {})
}
module.exports.unbufferDatum = unbufferDatum
// Invoked as the `replacer` in calls to JSON.stringify.
// If you're going to call it elsewhere, `this` must be
// set as it would be then.
function unbufferDatum (key, value) {
const unstringifiedValue = this[key]
if (Buffer.isBuffer(unstringifiedValue)) {
return unstringifiedValue.toString('hex')
}
return copy
return value
}
module.exports.bufferize = function bufferize(object, options) {

125
lib/db.js
Просмотреть файл

@ -8,9 +8,7 @@ const P = require('./promise')
const Pool = require('./pool')
const userAgent = require('./userAgent')
const butil = require('./crypto/butil')
const bufferize = butil.bufferize
const unbuffer = butil.unbuffer
const bufferize = require('./crypto/butil').bufferize
const random = require('./crypto/random')
module.exports = function (
@ -71,7 +69,7 @@ module.exports = function (
data.normalizedEmail = data.email.toLowerCase()
return this.pool.put(
'/account/' + data.uid.toString('hex'),
unbuffer(data)
data
)
.then(
function () {
@ -93,22 +91,19 @@ module.exports = function (
function (sessionToken) {
return this.pool.put(
'/sessionToken/' + sessionToken.id,
unbuffer(
{
tokenId: sessionToken.tokenId,
data: sessionToken.data,
uid: sessionToken.uid,
createdAt: sessionToken.createdAt,
uaBrowser: sessionToken.uaBrowser,
uaBrowserVersion: sessionToken.uaBrowserVersion,
uaOS: sessionToken.uaOS,
uaOSVersion: sessionToken.uaOSVersion,
uaDeviceType: sessionToken.uaDeviceType,
mustVerify: sessionToken.mustVerify,
tokenVerificationId: sessionToken.tokenVerificationId
},
'inplace'
)
{
tokenId: sessionToken.tokenId,
data: sessionToken.data,
uid: sessionToken.uid,
createdAt: sessionToken.createdAt,
uaBrowser: sessionToken.uaBrowser,
uaBrowserVersion: sessionToken.uaBrowserVersion,
uaOS: sessionToken.uaOS,
uaOSVersion: sessionToken.uaOSVersion,
uaDeviceType: sessionToken.uaDeviceType,
mustVerify: sessionToken.mustVerify,
tokenVerificationId: sessionToken.tokenVerificationId
}
)
.then(
function () {
@ -126,17 +121,14 @@ module.exports = function (
function (keyFetchToken) {
return this.pool.put(
'/keyFetchToken/' + keyFetchToken.id,
unbuffer(
{
tokenId: keyFetchToken.tokenId,
authKey: keyFetchToken.authKey,
uid: keyFetchToken.uid,
keyBundle: keyFetchToken.keyBundle,
createdAt: keyFetchToken.createdAt,
tokenVerificationId: keyFetchToken.tokenVerificationId
},
'inplace'
)
{
tokenId: keyFetchToken.tokenId,
authKey: keyFetchToken.authKey,
uid: keyFetchToken.uid,
keyBundle: keyFetchToken.keyBundle,
createdAt: keyFetchToken.createdAt,
tokenVerificationId: keyFetchToken.tokenVerificationId
}
)
.then(
function () {
@ -154,17 +146,14 @@ module.exports = function (
function (passwordForgotToken) {
return this.pool.put(
'/passwordForgotToken/' + passwordForgotToken.id,
unbuffer(
{
tokenId: passwordForgotToken.tokenId,
data: passwordForgotToken.data,
uid: passwordForgotToken.uid,
passCode: passwordForgotToken.passCode,
createdAt: passwordForgotToken.createdAt,
tries: passwordForgotToken.tries
},
'inplace'
)
{
tokenId: passwordForgotToken.tokenId,
data: passwordForgotToken.data,
uid: passwordForgotToken.uid,
passCode: passwordForgotToken.passCode,
createdAt: passwordForgotToken.createdAt,
tries: passwordForgotToken.tries
}
)
.then(
function () {
@ -182,15 +171,12 @@ module.exports = function (
function (passwordChangeToken) {
return this.pool.put(
'/passwordChangeToken/' + passwordChangeToken.id,
unbuffer(
{
tokenId: passwordChangeToken.tokenId,
data: passwordChangeToken.data,
uid: passwordChangeToken.uid,
createdAt: passwordChangeToken.createdAt
},
'inplace'
)
{
tokenId: passwordChangeToken.tokenId,
data: passwordChangeToken.data,
uid: passwordChangeToken.uid,
createdAt: passwordChangeToken.createdAt
}
)
.then(
function () {
@ -527,7 +513,7 @@ module.exports = function (
return this.pool.put(
'/account/' + uid.toString('hex') +
'/device/' + deviceInfo.id.toString('hex'),
unbuffer({
{
sessionTokenId: sessionTokenId,
createdAt: deviceInfo.createdAt,
name: deviceInfo.name,
@ -535,7 +521,7 @@ module.exports = function (
callbackURL: deviceInfo.pushCallback,
callbackPublicKey: deviceInfo.pushPublicKey,
callbackAuthKey: deviceInfo.pushAuthKey
})
}
)
})
.then(
@ -572,14 +558,14 @@ module.exports = function (
return this.pool.post(
'/account/' + uid.toString('hex') +
'/device/' + deviceInfo.id.toString('hex') + '/update',
unbuffer({
{
sessionTokenId: sessionTokenId,
name: deviceInfo.name,
type: deviceInfo.type,
callbackURL: deviceInfo.pushCallback,
callbackPublicKey: deviceInfo.pushPublicKey,
callbackAuthKey: deviceInfo.pushAuthKey
})
}
)
.then(
function (result) {
@ -687,7 +673,7 @@ module.exports = function (
data.verifierSetAt = Date.now()
return this.pool.post(
'/account/' + accountResetToken.uid.toString('hex') + '/reset',
unbuffer(data)
data
)
}
@ -698,13 +684,9 @@ module.exports = function (
DB.prototype.verifyTokens = function (tokenVerificationId, accountData) {
log.trace({ op: 'DB.verifyTokens', tokenVerificationId: tokenVerificationId })
return this.pool.post('/tokens/' + tokenVerificationId.toString('hex') + '/verify',
unbuffer(
{
uid: accountData.uid
},
'inplace'
)
return this.pool.post(
'/tokens/' + tokenVerificationId.toString('hex') + '/verify',
{ uid: accountData.uid }
)
.then(
function (body) {
@ -726,15 +708,12 @@ module.exports = function (
function (accountResetToken) {
return this.pool.post(
'/passwordForgotToken/' + passwordForgotToken.id + '/verified',
unbuffer(
{
tokenId: accountResetToken.tokenId,
data: accountResetToken.data,
uid: accountResetToken.uid,
createdAt: accountResetToken.createdAt
},
'inplace'
)
{
tokenId: accountResetToken.tokenId,
data: accountResetToken.data,
uid: accountResetToken.uid,
createdAt: accountResetToken.createdAt
}
)
.then(
function () {
@ -779,7 +758,7 @@ module.exports = function (
securityEvent: event
})
return this.pool.post('/securityEvents', unbuffer(event))
return this.pool.post('/securityEvents', event)
}
DB.prototype.securityEvents = function (params) {

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

@ -4,23 +4,13 @@
'use strict'
var EventEmitter = require('events').EventEmitter
var util = require('util')
var mozlog = require('mozlog')
var config = require('../config')
var logConfig = config.get('log')
var StatsDCollector = require('./metrics/statsd')
function unbuffer(object) {
var keys = Object.keys(object)
for (var i = 0; i < keys.length; i++) {
var x = object[keys[i]]
if (Buffer.isBuffer(x)) {
object[keys[i]] = x.toString('hex')
}
}
return object
}
const EventEmitter = require('events').EventEmitter
const util = require('util')
const mozlog = require('mozlog')
const config = require('../config')
const logConfig = config.get('log')
const StatsDCollector = require('./metrics/statsd')
const unbuffer = require('./crypto/butil').unbuffer
function Lug(options) {
EventEmitter.call(this)
@ -139,10 +129,10 @@ Lug.prototype.summary = function (request, response) {
if (line.code >= 500) {
line.trace = request.app.traced
line.stack = response.stack
this.error(unbuffer(line), response.message)
this.error(unbuffer(line, true), response.message)
}
else {
this.info(unbuffer(line))
this.info(unbuffer(line, true))
}
}

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

@ -2,8 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var P = require('./promise')
var Poolee = require('poolee')
'use strict'
const P = require('./promise')
const Poolee = require('poolee')
const unbufferDatum = require('./crypto/butil').unbufferDatum
function parseUrl(url) {
var match = /([a-zA-Z]+):\/\/(\S+)/.exec(url)
@ -40,7 +43,7 @@ Pool.prototype.request = function (method, path, data) {
headers: {
'Content-Type': 'application/json'
},
data: data ? JSON.stringify(data) : undefined
data: data ? JSON.stringify(data, unbufferDatum) : undefined
},
handleResponse
)