@@ -1000,13 +1000,20 @@ const bulkCreate = async function (req, res, next) {
10001000 next ( createExpressError ( err ) )
10011001 return
10021002 }
1003- let gate = documents . filter ( d => {
1003+ let gatekeep = documents . filter ( d => {
1004+ // Each item must be valid JSON, but can't be an array.
10041005 if ( Array . isArray ( d ) || typeof d !== "object" ) return d
1006+ try {
1007+ JSON . parse ( JSON . stringify ( d ) )
1008+ } catch ( err ) {
1009+ return d
1010+ }
1011+ // Items must not have an @id , and in some cases same for id.
10051012 const idcheck = _contextid ( d [ "@context" ] ) ? d . id ?? d [ "@id" ] : d [ "@id" ]
10061013 if ( idcheck ) return d
10071014 } )
1008- if ( gate . length > 1 ) {
1009- err . message = "All objects in the body of a `/bulkCreate` must be JSON and must not contain an @id or id property."
1015+ if ( gatekeep . length > 1 ) {
1016+ err . message = "All objects in the body of a `/bulkCreate` must be JSON and must not contain a declared identifier property."
10101017 err . status = 400
10111018 next ( createExpressError ( err ) )
10121019 return
@@ -1072,13 +1079,20 @@ const bulkUpdate = async function (req, res, next) {
10721079 next ( createExpressError ( err ) )
10731080 return
10741081 }
1075- let gate = documents . filter ( d => {
1082+ let gatekeep = documents . filter ( d => {
1083+ // Each item must be valid JSON, but can't be an array.
10761084 if ( Array . isArray ( d ) || typeof d !== "object" ) return d
1085+ try {
1086+ JSON . parse ( JSON . stringify ( d ) )
1087+ } catch ( err ) {
1088+ return d
1089+ }
1090+ // Items must have an @id , or in some cases an id will do
10771091 const idcheck = _contextid ( d [ "@context" ] ) ? d . id ?? d [ "@id" ] : d [ "@id" ]
10781092 if ( ! idcheck ) return d
10791093 } )
1080- if ( gate . length > 1 ) {
1081- err . message = "All objects in the body of a `/bulkUpdate` must be JSON and must contain an @id or id property."
1094+ if ( gatekeep . length > 1 ) {
1095+ err . message = "All objects in the body of a `/bulkUpdate` must be JSON and must contain a declared identifier property."
10821096 err . status = 400
10831097 next ( createExpressError ( err ) )
10841098 return
@@ -1091,46 +1105,44 @@ const bulkUpdate = async function (req, res, next) {
10911105 // but we will not update the same thing twice.
10921106 if ( encountered . includes ( idReceived ) ) continue
10931107 encountered . push ( idReceived )
1094- if ( idReceived ) {
1095- if ( ! idReceived . includes ( process . env . RERUM_ID_PREFIX ) ) {
1096- continue
1097- }
1098- let id = parseDocumentID ( idReceived )
1099- let originalObject
1100- try {
1101- originalObject = await db . findOne ( { "$or" :[ { "_id" : id } , { "__rerum.slug" : id } ] } )
1102- } catch ( error ) {
1103- next ( createExpressError ( error ) )
1104- return
1105- }
1106- if ( null === originalObject ) {
1107- continue
1108- }
1109- if ( utils . isDeleted ( originalObject ) ) {
1110- continue
1111- }
1112- id = ObjectID ( )
1113- let context = objectReceived [ "@context" ] ? { "@context" : objectReceived [ "@context" ] } : { }
1114- let rerumProp = { "__rerum" : utils . configureRerumOptions ( generatorAgent , originalObject , true , false ) [ "__rerum" ] }
1115- delete objectReceived [ "__rerum" ]
1116- delete objectReceived [ "_id" ]
1117- delete objectReceived [ "@id" ]
1118- // id is also protected in this case, so it can't be set.
1119- if ( _contextid ( objectReceived [ "@context" ] ) ) delete objectReceived . id
1120- delete objectReceived [ "@context" ]
1121- let newObject = Object . assign ( context , { "@id" : process . env . RERUM_ID_PREFIX + id } , objectReceived , rerumProp , { "_id" : id } )
1122- bulkOps . push ( { insertOne : { "document" : newObject } } )
1123- if ( originalObject . __rerum . history . next . indexOf ( newObject [ "@id" ] ) === - 1 ) {
1124- originalObject . __rerum . history . next . push ( newObject [ "@id" ] )
1125- const replaceOp = { replaceOne :
1126- {
1127- "filter" : { "_id" : originalObject [ "_id" ] } ,
1128- "replacement" : originalObject ,
1129- "upsert" : false
1130- }
1108+ if ( ! idReceived . includes ( process . env . RERUM_ID_PREFIX ) ) {
1109+ continue
1110+ }
1111+ let id = parseDocumentID ( idReceived )
1112+ let originalObject
1113+ try {
1114+ originalObject = await db . findOne ( { "$or" :[ { "_id" : id } , { "__rerum.slug" : id } ] } )
1115+ } catch ( error ) {
1116+ next ( createExpressError ( error ) )
1117+ return
1118+ }
1119+ if ( null === originalObject ) {
1120+ continue
1121+ }
1122+ if ( utils . isDeleted ( originalObject ) ) {
1123+ continue
1124+ }
1125+ id = ObjectID ( )
1126+ let context = objectReceived [ "@context" ] ? { "@context" : objectReceived [ "@context" ] } : { }
1127+ let rerumProp = { "__rerum" : utils . configureRerumOptions ( generatorAgent , originalObject , true , false ) [ "__rerum" ] }
1128+ delete objectReceived [ "__rerum" ]
1129+ delete objectReceived [ "_id" ]
1130+ delete objectReceived [ "@id" ]
1131+ // id is also protected in this case, so it can't be set.
1132+ if ( _contextid ( objectReceived [ "@context" ] ) ) delete objectReceived . id
1133+ delete objectReceived [ "@context" ]
1134+ let newObject = Object . assign ( context , { "@id" : process . env . RERUM_ID_PREFIX + id } , objectReceived , rerumProp , { "_id" : id } )
1135+ bulkOps . push ( { insertOne : { "document" : newObject } } )
1136+ if ( originalObject . __rerum . history . next . indexOf ( newObject [ "@id" ] ) === - 1 ) {
1137+ originalObject . __rerum . history . next . push ( newObject [ "@id" ] )
1138+ const replaceOp = { replaceOne :
1139+ {
1140+ "filter" : { "_id" : originalObject [ "_id" ] } ,
1141+ "replacement" : originalObject ,
1142+ "upsert" : false
11311143 }
1132- bulkOps . push ( replaceOp )
11331144 }
1145+ bulkOps . push ( replaceOp )
11341146 }
11351147 }
11361148 try {
0 commit comments