fix(validation): Add validation rules for resume and utm_* (#4956), r=@shane-tomlinson, @philbooth

This commit is contained in:
Vijay Budhram 2017-04-20 10:46:40 -04:00 коммит произвёл GitHub
Родитель eb057d3e06
Коммит bb8d298701
3 изменённых файлов: 78 добавлений и 5 удалений

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

@ -11,7 +11,9 @@ const joi = require('joi');
const validation = require('../validation');
const fxaAccountUrl = config.get('fxaccount_url');
const RESUME_TYPE = validation.TYPES.RESUME;
const STRING_TYPE = validation.TYPES.STRING;
const UTM_TYPE = validation.TYPES.UTM;
const VERIFICATION_ENDPOINT = `${fxaAccountUrl}/v1/recovery_email/verify_code`;
const VERIFICATION_TIMEOUT = 5000;
@ -27,13 +29,13 @@ const REQUIRED_SCHEMA = {
const REPORT_ONLY_SCHEMA = {
'code': STRING_TYPE.alphanum().min(32).max(32).required(),
// resume token can be long, do not use the limited STRING_TYPE
'resume': joi.string().alphanum().optional(),
'resume': RESUME_TYPE.optional(),
'service': STRING_TYPE.alphanum().max(100).optional(),
'uid': STRING_TYPE.alphanum().min(32).max(32).required(),
'utm_campaign': STRING_TYPE.alphanum().optional(),
'utm_content': STRING_TYPE.alphanum().optional(),
'utm_medium': STRING_TYPE.alphanum().optional(),
'utm_source': STRING_TYPE.alphanum().optional()
'utm_campaign': UTM_TYPE.optional(),
'utm_content': UTM_TYPE.optional(),
'utm_medium': UTM_TYPE.optional(),
'utm_source': UTM_TYPE.optional()
};
module.exports = function () {

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

@ -27,6 +27,7 @@ module.exports = {
INTEGER: joi.number().integer(),
OFFSET: joi.number().integer().min(0),
REFERRER: joi.string().max(2048).uri({ scheme: [ 'android-app', 'http', 'https' ]}).allow('none'),
RESUME: joi.string().regex(/^[a-zA-Z0-9\/+]+={0,2}$/), // match any valid base64 character
STRING: joi.string().max(1024), // 1024 is arbitrary, seems like it should give CSP reports plenty of space.
TIME: joi.number().integer().min(0),
URL: joi.string().max(2048).uri({ scheme: [ 'http', 'https' ]}), // 2048 is also arbitrary, the same limit we use on the front end.

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

@ -153,6 +153,76 @@ define([
});
return dfd.dojoPromise;
},
'logs error with invalid utm param' () {
const dfd = this.async(1000);
const req = {
query: {
/*eslint-disable camelcase*/
code: '12345678912345678912345678912312',
uid: '12345678912345678912345678912312',
utm_campaign: '!'
/*eslint-enable camelcase*/
},
url: '/verify_email'
};
mocks.got = {
post: () => {
return new Promise((resolve) => {
resolve({});
});
}
};
mockModule(mocks).process(req, res, () => {
// We have to use a setTimeout here because the log is performed passively after the response has
// been sent.
setTimeout(() => {
const c = ravenMock.ravenMiddleware.captureMessage;
const arg = c.args[0];
assert.equal(c.calledOnce, true);
assert.equal(arg[0], 'VerificationValidationInfo');
const errorMessage = '"utm_campaign" with value "!" fails to match the required pattern: /^[\\w\\/.%-]+/';
assert.equal(arg[1].extra.details[0].message, errorMessage);
dfd.resolve();
}, 100);
});
return dfd.promise;
},
'no logs with valid resume param' () {
const dfd = this.async(1000);
const req = {
query: {
code: '12345678912345678912345678912312',
resume: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', // All possible base64 characters
uid: '12345678912345678912345678912312'
},
url: '/verify_email'
};
mocks.got = {
post: () => {
return new Promise((resolve) => {
resolve({});
});
}
};
mockModule(mocks).process(req, res, () => {
// We have to use a setTimeout here because the log is performed passively after the response has
// been sent.
setTimeout(() => {
const c = ravenMock.ravenMiddleware.captureMessage;
assert.equal(c.callCount, 0);
dfd.resolve();
}, 100);
});
return dfd.promise;
}
});