Validate query and payload #20
							
								
								
									
										152
									
								
								src/crud.js
									
									
									
									
									
								
							
							
						
						
									
										152
									
								
								src/crud.js
									
									
									
									
									
								
							| @@ -6,9 +6,112 @@ import { parseInclude, parseWhere } from './utils'; | |||||||
| import { notFound } from 'boom'; | import { notFound } from 'boom'; | ||||||
| import * as associations from './associations/index'; | import * as associations from './associations/index'; | ||||||
|  |  | ||||||
| const createAll = ({ server, model, prefix, config }) => { | const sequelizeOperators = { | ||||||
|  |   $and: joi.any(), | ||||||
|  |   $or: joi.any(), | ||||||
|  |   $gt: joi.any(), | ||||||
|  |   $gte: joi.any(), | ||||||
|  |   $lt: joi.any(), | ||||||
|  |   $lte: joi.any(), | ||||||
|  |   $ne: joi.any(), | ||||||
|  |   $eq: joi.any(), | ||||||
|  |   $not: joi.any(), | ||||||
|  |   $between: joi.any(), | ||||||
|  |   $notBetween: joi.any(), | ||||||
|  |   $in: joi.any(), | ||||||
|  |   $notIn: joi.any(), | ||||||
|  |   $like: joi.any(), | ||||||
|  |   $notLike: joi.any(), | ||||||
|  |   $iLike: joi.any(), | ||||||
|  |   $notILike: joi.any(), | ||||||
|  |   $overlap: joi.any(), | ||||||
|  |   $contains: joi.any(), | ||||||
|  |   $contained: joi.any(), | ||||||
|  |   $any: joi.any(), | ||||||
|  |   $col: joi.any(), | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const whereMethods = [ | ||||||
|  |   'list', | ||||||
|  |   'get', | ||||||
|  |   'scope', | ||||||
|  |   'destroy', | ||||||
|  |   'destoryScope', | ||||||
|  |   'destroyAll', | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | const includeMethods = [ | ||||||
|  |   'list', | ||||||
|  |   'get', | ||||||
|  |   'scope', | ||||||
|  |   'destoryScope', | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | const payloadMethods = [ | ||||||
|  |   'create', | ||||||
|  |   'update', | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | const getConfigForMethod = ({ method, attributeValidation, associationValidation, config }) => { | ||||||
|  |   const hasWhere = whereMethods.includes(method); | ||||||
|  |   const hasInclude = includeMethods.includes(method); | ||||||
|  |   const hasPayload = payloadMethods.includes(method); | ||||||
|  |   const methodConfig = { ...config }; | ||||||
|  |  | ||||||
|  |   if (hasWhere) { | ||||||
|  |     _.defaultsDeep(methodConfig, { | ||||||
|  |       validate: { | ||||||
|  |         query: { | ||||||
|  |           ...attributeValidation, | ||||||
|  |           ...sequelizeOperators, | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (hasInclude) { | ||||||
|  |     _.defaultsDeep(methodConfig, { | ||||||
|  |       validate: { | ||||||
|  |         query: { | ||||||
|  |           ...associationValidation, | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (hasPayload) { | ||||||
|  |     _.defaultsDeep(methodConfig, { | ||||||
|  |       validate: { | ||||||
|  |         payload: { | ||||||
|  |           ...attributeValidation, | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return methodConfig; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const createAll = ({ | ||||||
|  |   server, | ||||||
|  |   model, | ||||||
|  |   prefix, | ||||||
|  |   config, | ||||||
|  |   attributeValidation, | ||||||
|  |   associationValidation, | ||||||
|  | }) => { | ||||||
|   Object.keys(methods).forEach((method) => { |   Object.keys(methods).forEach((method) => { | ||||||
|     methods[method]({ server, model, prefix, config }); |     methods[method]({ | ||||||
|  |       server, | ||||||
|  |       model, | ||||||
|  |       prefix, | ||||||
|  |       config: getConfigForMethod({ | ||||||
|  |         method, | ||||||
|  |         attributeValidation, | ||||||
|  |         associationValidation, | ||||||
|  |         config, | ||||||
|  |       }), | ||||||
|  |     }); | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -34,17 +137,42 @@ models: { | |||||||
|  |  | ||||||
| export default (server, model, { prefix, defaultConfig: config, models: permissions }) => { | export default (server, model, { prefix, defaultConfig: config, models: permissions }) => { | ||||||
|   const modelName = model._singular; |   const modelName = model._singular; | ||||||
|  |   const modelAttributes = Object.keys(model.attributes); | ||||||
|  |   const modelAssociations = Object.keys(model.associations); | ||||||
|  |  | ||||||
|  |   const attributeValidation = modelAttributes.reduce((params, attribute) => { | ||||||
|  |     params[attribute] = joi.any(); | ||||||
|  |     return params; | ||||||
|  |   }, {}); | ||||||
|  |  | ||||||
|  |   const associationValidation = { | ||||||
|  |     include: joi.array().items(joi.string().valid(...modelAssociations)), | ||||||
|  |   }; | ||||||
|  |  | ||||||
|   // if we don't have any permissions set, just create all the methods |   // if we don't have any permissions set, just create all the methods | ||||||
|   if (!permissions) { |   if (!permissions) { | ||||||
|     createAll({ server, model, prefix, config }); |     createAll({ | ||||||
|  |       server, | ||||||
|  |       model, | ||||||
|  |       prefix, | ||||||
|  |       config, | ||||||
|  |       attributeValidation, | ||||||
|  |       associationValidation, | ||||||
|  |     }); | ||||||
|   // if permissions are set, but we can't parse them, throw an error |   // if permissions are set, but we can't parse them, throw an error | ||||||
|   } else if (!Array.isArray(permissions)) { |   } else if (!Array.isArray(permissions)) { | ||||||
|     throw new Error('hapi-sequelize-crud: `models` property must be an array'); |     throw new Error('hapi-sequelize-crud: `models` property must be an array'); | ||||||
|   // if permissions are set, but the only thing we've got is a model name, there |   // if permissions are set, but the only thing we've got is a model name, there | ||||||
|   // are no permissions to be set, so just create all methods and move on |   // are no permissions to be set, so just create all methods and move on | ||||||
|   } else if (permissions.includes(modelName)) { |   } else if (permissions.includes(modelName)) { | ||||||
|     createAll({ server, model, prefix, config }); |     createAll({ | ||||||
|  |       server, | ||||||
|  |       model, | ||||||
|  |       prefix, | ||||||
|  |       config, | ||||||
|  |       attributeValidation, | ||||||
|  |       associationValidation, | ||||||
|  |     }); | ||||||
|   // if we've gotten here, we have complex permissions and need to set them |   // if we've gotten here, we have complex permissions and need to set them | ||||||
|   } else { |   } else { | ||||||
|     const permissionOptions = permissions.filter((permission) => { |     const permissionOptions = permissions.filter((permission) => { | ||||||
| @@ -61,11 +189,23 @@ export default (server, model, { prefix, defaultConfig: config, models: permissi | |||||||
|               server, |               server, | ||||||
|               model, |               model, | ||||||
|               prefix, |               prefix, | ||||||
|               config: permissionConfig, |               config: getConfigForMethod({ | ||||||
|  |                 method, | ||||||
|  |                 attributeValidation, | ||||||
|  |                 associationValidation, | ||||||
|  |                 config: permissionConfig, | ||||||
|  |               }), | ||||||
|             }); |             }); | ||||||
|           }); |           }); | ||||||
|         } else { |         } else { | ||||||
|           createAll({ server, model, prefix, config: permissionConfig }); |           createAll({ | ||||||
|  |             server, | ||||||
|  |             model, | ||||||
|  |             prefix, | ||||||
|  |             attributeValidation, | ||||||
|  |             associationValidation, | ||||||
|  |             config: permissionConfig, | ||||||
|  |           }); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user