@@ -5,13 +5,16 @@ var _ = {
5
5
var async = require ( "async" ) ;
6
6
var debug = require ( "./debugging" ) ;
7
7
var mongodb = require ( "mongodb" ) ;
8
-
8
+ var Joi = require ( "joi" ) ;
9
9
10
10
var MongoStore = module . exports = function MongoStore ( config ) {
11
11
this . _config = config ;
12
12
} ;
13
13
14
14
15
+ var FILTER_OPERATORS = [ "<" , ">" , "~" , ":" ] ;
16
+
17
+
15
18
/**
16
19
Handlers readiness status. This should be set to `true` once all handlers are ready to process requests.
17
20
*/
@@ -48,13 +51,43 @@ MongoStore._getRelationshipAttributeNames = function(attributes) {
48
51
} ;
49
52
50
53
54
+ MongoStore . _splitFilterElement = function ( filterElementStr ) {
55
+ if ( FILTER_OPERATORS . indexOf ( filterElementStr [ 0 ] ) !== - 1 ) {
56
+ return { operator : filterElementStr [ 0 ] , value : filterElementStr . substring ( 1 ) } ;
57
+ }
58
+ return { operator : null , value : filterElementStr } ;
59
+ } ;
60
+
61
+
62
+ MongoStore . _filterElementToMongoExpr = function ( attributeConfig , filterElementStr ) {
63
+ var filterElement = MongoStore . _splitFilterElement ( filterElementStr ) ;
64
+ var value = filterElement . value ;
65
+ if ( ! attributeConfig . _settings ) { // not a relationship attribute
66
+ var validationResult = attributeConfig . validate ( filterElement . value ) ;
67
+ if ( validationResult . error ) return null ;
68
+ value = validationResult . value ;
69
+ }
70
+ if ( ! filterElement . operator ) return value ;
71
+ if ( [ "~" , ":" ] . indexOf ( filterElement . operator ) !== - 1 && typeof value !== "string" ) {
72
+ return null ;
73
+ }
74
+ var mongoExpr = {
75
+ ">" : { $gt : value } ,
76
+ "<" : { $lt : value } ,
77
+ "~" : new RegExp ( "^" + value + "$" , "i" ) ,
78
+ ":" : new RegExp ( value )
79
+ } [ filterElement . operator ] ;
80
+ return mongoExpr ;
81
+ } ;
82
+
83
+
51
84
MongoStore . prototype . _getSearchCriteria = function ( request ) {
52
85
var self = this ;
53
86
if ( ! request . params . filter ) return { } ;
54
87
55
88
var criteria = Object . keys ( request . params . filter ) . map ( function ( attribute ) {
56
89
var attributeConfig = self . resourceConfig . attributes [ attribute ] ;
57
- // If the filter attribute doens 't exist, skip it
90
+ // If the filter attribute doesn 't exist, skip it
58
91
if ( ! attributeConfig ) return null ;
59
92
60
93
var values = request . params . filter [ attribute ] ;
@@ -65,28 +98,33 @@ MongoStore.prototype._getSearchCriteria = function(request) {
65
98
if ( values instanceof Object ) return null ;
66
99
}
67
100
68
- // Coerce values to an array to simplify the logic
69
- if ( ! ( values instanceof Array ) ) values = [ values ] ;
70
- values = values . map ( function ( value ) {
71
- if ( value [ 0 ] === "<" ) return { $lt : value . substring ( 1 ) } ;
72
- if ( value [ 0 ] === ">" ) return { $gt : value . substring ( 1 ) } ;
73
- if ( value [ 0 ] === "~" ) return new RegExp ( "^" + value . substring ( 1 ) + "$" , "i" ) ;
74
- if ( value [ 0 ] === ":" ) return new RegExp ( value . substring ( 1 ) ) ;
75
- return value ;
76
- } ) . map ( function ( value ) {
77
- var tmp = { } ;
78
- tmp [ attribute ] = value ;
79
- return tmp ;
80
- } ) ;
81
-
101
+ values = [ ] . concat ( values ) ; // Coerce values to an array to simplify the logic
102
+ var filterElemForAttrToMongoExpr = MongoStore . _filterElementToMongoExpr . bind ( null , attributeConfig ) ;
103
+ values = values . map ( filterElemForAttrToMongoExpr ) ;
104
+ values = values . reduce ( function ( mongoExpressions , mongoExpr ) {
105
+ if ( mongoExpr !== null ) {
106
+ var mongoExprForAttr = { } ;
107
+ mongoExprForAttr [ attribute ] = mongoExpr ;
108
+ mongoExpressions . push ( mongoExprForAttr ) ;
109
+ }
110
+ return mongoExpressions ;
111
+ } , [ ] ) ;
112
+ if ( values . length === 0 ) {
113
+ return null ;
114
+ }
115
+ if ( values . length === 1 ) {
116
+ return values [ 0 ] ;
117
+ }
82
118
return { $or : values } ;
83
119
} ) . filter ( function ( value ) {
84
120
return value !== null ;
85
121
} ) ;
86
-
87
122
if ( criteria . length === 0 ) {
88
123
return { } ;
89
124
}
125
+ if ( criteria . length === 1 ) {
126
+ return criteria [ 0 ] ;
127
+ }
90
128
return { $and : criteria } ;
91
129
} ;
92
130
@@ -192,7 +230,11 @@ MongoStore.prototype.populate = function(callback) {
192
230
self . _db . dropDatabase ( function ( err ) {
193
231
if ( err ) return console . error ( "error dropping database" , err . message ) ;
194
232
async . each ( self . resourceConfig . examples , function ( document , cb ) {
195
- self . create ( { params : { } } , document , cb ) ;
233
+ var validationResult = Joi . validate ( document , self . resourceConfig . attributes ) ;
234
+ if ( validationResult . error ) {
235
+ return cb ( validationResult . error ) ;
236
+ }
237
+ self . create ( { params : { } } , validationResult . value , cb ) ;
196
238
} , function ( error ) {
197
239
if ( error ) console . error ( "error creating example document:" , error ) ;
198
240
return callback ( ) ;
0 commit comments