Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
path: Joi.string().default(requestDefaults.path),
method: Joi.string().required(),
operation: Joi.string().required().description('Ex: GET_supply_properties_v1'),
queryParams: Joi.object(),
pathParams: Joi.object(),
headers: Joi.object().default(requestDefaults.headers),
payload: Joi.any(),
redirects: Joi.alternatives().try(Joi.number(), Joi.valid(false)), // default value provided by global config
connectTimeout: Joi.number(), // default value provided by global config
maxConnectRetry: Joi.number(), // default value provided by global config
timeout: Joi.number(), // default value provided by global config
agent: Joi.object(), // default value provided by global config
read: Joi.bool().default(requestDefaults.read),
readOptions: Joi.object({
timeout: Joi.number().default(requestDefaults.readOptions.timeout),
json: Joi.valid(true, false, 'strict', 'force').default(requestDefaults.readOptions.json),
maxBytes: Joi.number(),
gunzip: Joi.valid(true, false, 'force').default(requestDefaults.readOptions.gunzip)
}).default(requestDefaults.readOptions),
plugins: Joi.object().default(requestDefaults.plugins)
}).unknown(true).default(requestDefaults)
// defaults listed in config.js
const globalSchema = Joi.object({
plugins: Joi.array().items(Joi.function()),
base: Joi.object(),
overrides: Joi.object().pattern(/.+/, Joi.object())
})
function validate (schema, options) {
const validated = schema.validate(options)
'beforeDate',
'afterDate'
];
const querySchema = Joi.object().keys({
measures: Joi.array().items(id),
dimensions: Joi.array().items(dimensionWithTime),
filters: Joi.array().items(Joi.object().keys({
dimension: id,
member: id,
operator: Joi.valid(operators).required(),
values: Joi.array().items(Joi.string().allow(''))
}).xor('dimension', 'member')),
timeDimensions: Joi.array().items(Joi.object().keys({
dimension: id.required(),
granularity: Joi.valid('day', 'month', 'year', 'week', 'hour', 'minute', 'second', null),
dateRange: [
Joi.array().items(Joi.string()).min(1).max(2),
Joi.string()
]
})),
order: Joi.object().pattern(id, Joi.valid('asc', 'desc')),
segments: Joi.array().items(id),
timezone: Joi.string(),
limit: Joi.number().integer().min(1).max(50000),
offset: Joi.number().integer().min(0),
renewQuery: Joi.boolean(),
ungrouped: Joi.boolean()
});
const normalizeQuery = (query) => {
// eslint-disable-next-line no-unused-vars
dimensions: Joi.array().items(dimensionWithTime),
filters: Joi.array().items(Joi.object().keys({
dimension: id,
member: id,
operator: Joi.valid(operators).required(),
values: Joi.array().items(Joi.string().allow(''))
}).xor('dimension', 'member')),
timeDimensions: Joi.array().items(Joi.object().keys({
dimension: id.required(),
granularity: Joi.valid('day', 'month', 'year', 'week', 'hour', 'minute', 'second', null),
dateRange: [
Joi.array().items(Joi.string()).min(1).max(2),
Joi.string()
]
})),
order: Joi.object().pattern(id, Joi.valid('asc', 'desc')),
segments: Joi.array().items(id),
timezone: Joi.string(),
limit: Joi.number().integer().min(1).max(50000),
offset: Joi.number().integer().min(0),
renewQuery: Joi.boolean(),
ungrouped: Joi.boolean()
});
const normalizeQuery = (query) => {
// eslint-disable-next-line no-unused-vars
const { error, value } = Joi.validate(query, querySchema);
if (error) {
throw new UserError(`Invalid query format: ${error.message || error.toString()}`);
}
const validQuery = query.measures && query.measures.length ||
query.dimensions && query.dimensions.length ||
operation: Joi.string().required().description('Ex: GET_supply_properties_v1'),
queryParams: Joi.object(),
pathParams: Joi.object(),
headers: Joi.object().default(requestDefaults.headers),
payload: Joi.any(),
redirects: Joi.alternatives().try(Joi.number(), Joi.valid(false)), // default value provided by global config
connectTimeout: Joi.number(), // default value provided by global config
maxConnectRetry: Joi.number(), // default value provided by global config
timeout: Joi.number(), // default value provided by global config
agent: Joi.object(), // default value provided by global config
read: Joi.bool().default(requestDefaults.read),
readOptions: Joi.object({
timeout: Joi.number().default(requestDefaults.readOptions.timeout),
json: Joi.valid(true, false, 'strict', 'force').default(requestDefaults.readOptions.json),
maxBytes: Joi.number(),
gunzip: Joi.valid(true, false, 'force').default(requestDefaults.readOptions.gunzip)
}).default(requestDefaults.readOptions),
plugins: Joi.object().default(requestDefaults.plugins)
}).unknown(true).default(requestDefaults)
// defaults listed in config.js
const globalSchema = Joi.object({
plugins: Joi.array().items(Joi.function()),
base: Joi.object(),
overrides: Joi.object().pattern(/.+/, Joi.object())
})
function validate (schema, options) {
const validated = schema.validate(options)
Hoek.assert(!validated.error, validated.error)
// Validated in route construction
handler: Joi.any(),
options: Joi.any(),
config: Joi.any() // Backwards compatibility
})
.without('config', 'options');
internals.pre = [
Joi.function(),
Joi.object({
method: Joi.alternatives(Joi.string(), Joi.function()).required(),
assign: Joi.string(),
mode: Joi.valid('serial', 'parallel'),
failAction: internals.failAction
})
];
internals.routeConfig = internals.routeBase.keys({
description: Joi.string(),
id: Joi.string(),
isInternal: Joi.boolean(),
notes: [
Joi.string(),
Joi.array().items(Joi.string())
],
pre: Joi.array().items(...internals.pre.concat(Joi.array().items(...internals.pre).min(1))),
tags: [
Joi.string(),
internals.access = Joi.object({
entity: Joi.valid('user', 'app', 'any'),
scope: [false, Joi.array().items(Joi.string()).single().min(1)]
});
internals.auth = Joi.alternatives([
Joi.string(),
internals.access.keys({
mode: Joi.valid('required', 'optional', 'try'),
strategy: Joi.string(),
strategies: Joi.array().items(Joi.string()).min(1),
access: Joi.array().items(internals.access.min(1)).single().min(1),
payload: [
Joi.valid('required', 'optional'),
Joi.boolean()
]
})
.without('strategy', 'strategies')
.without('access', ['scope', 'entity'])
]);
internals.event = Joi.object({
method: Joi.array().items(Joi.function()).single(),
options: Joi.object({
before: Joi.array().items(Joi.string()).single(),
after: Joi.array().items(Joi.string()).single(),
bind: Joi.any(),
sandbox: Joi.valid('server', 'plugin'),
timeout: Joi.number().integer().min(1)
log: Joi.object({
collect: Joi.boolean().default(false)
})
.default(),
payload: Joi.object({
output: Joi.valid('data', 'stream', 'file').default('data'),
parse: Joi.boolean().allow('gunzip').default(true),
multipart: Joi.object({
output: Joi.valid('data', 'stream', 'file', 'annotated').required()
})
.default(false)
.allow(true, false)
.when('.', { is: true, then: Joi.object().strip() }),
allow: Joi.array().items(Joi.string()).single(),
override: Joi.string(),
protoAction: Joi.valid('error', 'remove', 'ignore').default('error'),
maxBytes: Joi.number().integer().positive().default(1024 * 1024),
uploads: Joi.string().default(Os.tmpdir()),
failAction: internals.failAction,
timeout: Joi.number().integer().positive().allow(false).default(10 * 1000),
defaultContentType: Joi.string().default('application/json'),
compression: Joi.object()
.pattern(/.+/, Joi.object())
.default()
})
.default(),
plugins: Joi.object(),
response: Joi.object({
disconnectStatusCode: Joi.number().integer().min(400).default(499),
emptyStatusCode: Joi.valid(200, 204).default(204),
failAction: internals.failAction,
modify: Joi.boolean(),
})
.default(),
json: Joi.object({
replacer: Joi.alternatives(Joi.function(), Joi.array()).allow(null).default(null),
space: Joi.number().allow(null).default(null),
suffix: Joi.string().allow(null).default(null),
escape: Joi.boolean().default(false)
})
.default(),
jsonp: Joi.string(),
log: Joi.object({
collect: Joi.boolean().default(false)
})
.default(),
payload: Joi.object({
output: Joi.valid('data', 'stream', 'file').default('data'),
parse: Joi.boolean().allow('gunzip').default(true),
multipart: Joi.object({
output: Joi.valid('data', 'stream', 'file', 'annotated').required()
})
.default(false)
.allow(true, false)
.when('.', { is: true, then: Joi.object().strip() }),
allow: Joi.array().items(Joi.string()).single(),
override: Joi.string(),
protoAction: Joi.valid('error', 'remove', 'ignore').default('error'),
maxBytes: Joi.number().integer().positive().default(1024 * 1024),
uploads: Joi.string().default(Os.tmpdir()),
failAction: internals.failAction,
timeout: Joi.number().integer().positive().allow(false).default(10 * 1000),
defaultContentType: Joi.string().default('application/json'),
compression: Joi.object()
'A+': 'brightgreen',
A: 'brightgreen',
'A-': 'green',
'B+': 'yellowgreen',
B: 'yellowgreen',
'B-': 'yellowgreen',
'C+': 'yellow',
C: 'yellow',
'C-': 'yellow',
'D+': 'orange',
D: 'orange',
'D-': 'orange',
F: 'red',
}
const isValidGrade = Joi.valid(...Object.keys(colorMap)).required()
function gradeColor(grade) {
const color = colorMap[grade]
if (color === undefined) {
throw Error(`Unknown grade: ${grade}`)
}
return color
}
module.exports = { isValidGrade, gradeColor }
hsts: Joi.alternatives([
Joi.object({
maxAge: Joi.number(),
includeSubdomains: Joi.boolean(),
includeSubDomains: Joi.boolean(),
preload: Joi.boolean()
}),
Joi.boolean(),
Joi.number()
])
.default(15768000),
xframe: Joi.alternatives([
Joi.boolean(),
Joi.valid('sameorigin', 'deny'),
Joi.object({
rule: Joi.valid('sameorigin', 'deny', 'allow-from'),
source: Joi.string()
})
])
.default('deny'),
xss: Joi.boolean().default(true),
noOpen: Joi.boolean().default(true),
noSniff: Joi.boolean().default(true),
referrer: Joi.alternatives([
Joi.boolean().valid(false),
Joi.valid('', 'no-referrer', 'no-referrer-when-downgrade',
'unsafe-url', 'same-origin', 'origin', 'strict-origin',
'origin-when-cross-origin', 'strict-origin-when-cross-origin')
])
.default(false)
})
.allow(null, false, true)