2019-03-13 19:27:18 +01:00
const _ = require ( 'lodash' ) ;
2019-03-22 12:16:09 +01:00
const findModelByAssoc = assoc => {
const { models } = assoc . plugin ? strapi . plugins [ assoc . plugin ] : strapi ;
return models [ assoc . collection || assoc . model ] ;
} ;
const isAttribute = ( model , field ) => _ . has ( model . attributes , field ) || model . primaryKey === field ;
2019-03-13 19:27:18 +01:00
const createFilterValidator = model => ( { field } ) => {
const fieldParts = field . split ( '.' ) ;
2019-03-22 12:16:09 +01:00
let isValid = true ;
let tmpModel = model ;
for ( let i = 0 ; i < fieldParts . length ; i ++ ) {
const field = fieldParts [ i ] ;
const assoc = tmpModel . associations . find ( ast => ast . alias === field ) ;
if ( assoc ) {
tmpModel = findModelByAssoc ( assoc ) ;
continue ;
}
if ( ! assoc && ( ! isAttribute ( tmpModel , field ) || i !== fieldParts . length - 1 ) ) {
isValid = false ;
break ;
2019-03-13 19:27:18 +01:00
}
2019-03-22 12:16:09 +01:00
}
2019-03-13 19:27:18 +01:00
2019-03-22 12:16:09 +01:00
return isValid ;
2019-03-13 19:27:18 +01:00
} ;
2019-03-26 14:57:02 +01:00
/ * *
*
* @ param { Object } options - Options
* @ param { Object } options . model - The model for which the query will be built
* @ param { Object } options . filters - The filters for the query ( start , sort , limit , and where clauses )
* @ param { Object } options . rest - In case the database layer requires any other params pass them
* /
2019-03-13 19:27:18 +01:00
const buildQuery = ( { model , filters , ... rest } ) => {
const validator = createFilterValidator ( model ) ;
2019-03-26 14:57:02 +01:00
// Validate query clauses
2019-03-13 19:27:18 +01:00
if ( filters . where && Array . isArray ( filters . where ) ) {
2019-03-26 14:57:02 +01:00
const deepFilters = filters . where . filter ( ( { field } ) => field . split ( '.' ) . length > 1 ) ;
if ( deepFilters . length > 0 ) {
strapi . log . warn (
'Deep filtering queries should be used carefully (e.g Can cause performance issues).\nWhen possible build custom routes which will in most case be more optimised.'
) ;
}
2019-03-13 19:27:18 +01:00
filters . where . forEach ( whereClause => {
if ( ! validator ( whereClause ) ) {
2019-03-22 12:16:09 +01:00
const err = new Error (
` Your filters contain a field ' ${
2019-03-13 19:27:18 +01:00
whereClause . field
2019-03-22 12:16:09 +01:00
} ' that doesn' t appear on your model definition nor it ' s relations `
2019-03-13 19:27:18 +01:00
) ;
2019-03-22 12:16:09 +01:00
err . status = 400 ;
throw err ;
2019-03-13 19:27:18 +01:00
}
} ) ;
}
2019-03-26 14:57:02 +01:00
const orm = strapi . hook [ model . orm ] ;
2019-03-13 19:27:18 +01:00
2019-03-26 14:57:02 +01:00
// call the orm's buildQuery implementation
return orm . load ( ) . buildQuery ( { model , filters , ... rest } ) ;
2019-03-13 19:27:18 +01:00
} ;
module . exports = buildQuery ;