Fix (validation) use joi's concat
It turns out defaultsDeep doesn't ever correctly combine Joi objects. So, the only option is to use Joi's concat method to combine Joi schemas. This complicates `getConfigForMethod`, but simplifies actual route creation. I ran into this because I'm setting up [lout](https://github.com/hapijs/lout) on a server, and it requires properly formatted Joi schemas. This leads me to believe there was something already wrong and Lout just exposed the problem.
This commit is contained in:
@ -1,6 +1,15 @@
|
||||
import { defaultsDeep } from 'lodash';
|
||||
import { set, get } from 'lodash';
|
||||
import joi from 'joi';
|
||||
|
||||
// if the custom validation is a joi object we need to concat
|
||||
// else, assume it's an plain object and we can just add it in with .keys
|
||||
const concatToJoiObject = (joi, candidate) => {
|
||||
if (!candidate) return joi;
|
||||
else if (candidate.isJoi) return joi.concat(candidate);
|
||||
else return joi.keys(candidate);
|
||||
};
|
||||
|
||||
|
||||
export const sequelizeOperators = {
|
||||
$and: joi.any(),
|
||||
$or: joi.any(),
|
||||
@ -47,41 +56,81 @@ export const payloadMethods = [
|
||||
'update',
|
||||
];
|
||||
|
||||
export default ({ method, attributeValidation, associationValidation, config = {} }) => {
|
||||
export const scopeParamsMethods = [
|
||||
'destroyScope',
|
||||
'scope',
|
||||
];
|
||||
|
||||
export const idParamsMethods = [
|
||||
'get',
|
||||
'update',
|
||||
];
|
||||
|
||||
export default ({
|
||||
method, attributeValidation, associationValidation, scopes = [], config = {},
|
||||
}) => {
|
||||
const hasWhere = whereMethods.includes(method);
|
||||
const hasInclude = includeMethods.includes(method);
|
||||
const hasPayload = payloadMethods.includes(method);
|
||||
const methodConfig = { ...config };
|
||||
const hasScopeParams = scopeParamsMethods.includes(method);
|
||||
const hasIdParams = idParamsMethods.includes(method);
|
||||
// clone the config so we don't modify it on multiple passes.
|
||||
let methodConfig = { ...config, validate: { ...config.validate } };
|
||||
|
||||
if (hasWhere) {
|
||||
defaultsDeep(methodConfig, {
|
||||
validate: {
|
||||
query: {
|
||||
...attributeValidation,
|
||||
...sequelizeOperators,
|
||||
},
|
||||
},
|
||||
});
|
||||
const query = concatToJoiObject(joi.object()
|
||||
.keys({
|
||||
...attributeValidation,
|
||||
...sequelizeOperators,
|
||||
}),
|
||||
get(methodConfig, 'validate.query')
|
||||
);
|
||||
|
||||
methodConfig = set(methodConfig, 'validate.query', query);
|
||||
}
|
||||
|
||||
if (hasInclude) {
|
||||
defaultsDeep(methodConfig, {
|
||||
validate: {
|
||||
query: {
|
||||
...associationValidation,
|
||||
},
|
||||
},
|
||||
});
|
||||
const query = concatToJoiObject(joi.object()
|
||||
.keys({
|
||||
...associationValidation,
|
||||
}),
|
||||
get(methodConfig, 'validate.query')
|
||||
);
|
||||
|
||||
methodConfig = set(methodConfig, 'validate.query', query);
|
||||
}
|
||||
|
||||
if (hasPayload) {
|
||||
defaultsDeep(methodConfig, {
|
||||
validate: {
|
||||
payload: {
|
||||
...attributeValidation,
|
||||
},
|
||||
},
|
||||
});
|
||||
const payload = concatToJoiObject(joi.object()
|
||||
.keys({
|
||||
...attributeValidation,
|
||||
}),
|
||||
get(methodConfig, 'validate.payload')
|
||||
);
|
||||
|
||||
methodConfig = set(methodConfig, 'validate.payload', payload);
|
||||
}
|
||||
|
||||
if (hasScopeParams) {
|
||||
const params = concatToJoiObject(joi.object()
|
||||
.keys({
|
||||
scope: joi.string().valid(...scopes),
|
||||
}),
|
||||
get(methodConfig, 'validate.params')
|
||||
);
|
||||
|
||||
methodConfig = set(methodConfig, 'validate.params', params);
|
||||
}
|
||||
|
||||
if (hasIdParams) {
|
||||
const params = concatToJoiObject(joi.object()
|
||||
.keys({
|
||||
id: joi.any(),
|
||||
}),
|
||||
get(methodConfig, 'validate.params')
|
||||
);
|
||||
|
||||
methodConfig = set(methodConfig, 'validate.params', params);
|
||||
}
|
||||
|
||||
return methodConfig;
|
||||
|
Reference in New Issue
Block a user