Skip to content

Commit e88c769

Browse files
committed
Harder checks against objects supplied in the bodies of bulk endpoints.
1 parent bbb88c5 commit e88c769

1 file changed

Lines changed: 47 additions & 59 deletions

File tree

db-controller.js

Lines changed: 47 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,8 @@ const create = async function (req, res, next) {
132132
const id = isValidID(providedID) ? providedID : ObjectID()
133133
delete provided["__rerum"]
134134
delete provided["@id"]
135-
if(_contextid(provided["@context"])) {
136-
// id is also protected in this case, so it can't be set.
137-
delete provided.id
138-
}
135+
// id is also protected in this case, so it can't be set.
136+
if(_contextid(provided["@context"])) delete provided.id
139137
delete provided["@context"]
140138

141139
let newObject = Object.assign(context, { "@id": process.env.RERUM_ID_PREFIX + id }, provided, rerumProp, { "_id": id })
@@ -296,10 +294,8 @@ const putUpdate = async function (req, res, next) {
296294
delete objectReceived["__rerum"]
297295
delete objectReceived["_id"]
298296
delete objectReceived["@id"]
299-
if(_contextid(objectReceived["@context"])) {
300-
// id is also protected in this case, so it can't be set.
301-
delete objectReceived.id
302-
}
297+
// id is also protected in this case, so it can't be set.
298+
if(_contextid(objectReceived["@context"])) delete objectReceived.id
303299
delete objectReceived["@context"]
304300

305301
let newObject = Object.assign(context, { "@id": process.env.RERUM_ID_PREFIX + id }, objectReceived, rerumProp, { "_id": id })
@@ -357,10 +353,8 @@ async function _import(req, res, next) {
357353
delete objectReceived["__rerum"]
358354
delete objectReceived["_id"]
359355
delete objectReceived["@id"]
360-
if(_contextid(objectReceived["@context"])) {
361-
// id is also protected in this case, so it can't be set.
362-
delete objectReceived.id
363-
}
356+
// id is also protected in this case, so it can't be set.
357+
if(_contextid(objectReceived["@context"])) delete objectReceived.id
364358
delete objectReceived["@context"]
365359

366360
let newObject = Object.assign(context, { "@id": process.env.RERUM_ID_PREFIX + id }, objectReceived, rerumProp, { "_id": id })
@@ -423,10 +417,8 @@ const patchUpdate = async function (req, res, next) {
423417
delete objectReceived.__rerum //can't patch this
424418
delete objectReceived._id //can't patch this
425419
delete objectReceived["@id"] //can't patch this
426-
if(_contextid(objectReceived["@context"])) {
427-
// id is also protected in this case, so it can't be set.
428-
delete objectReceived.id
429-
}
420+
// id is also protected in this case, so it can't be set.
421+
if(_contextid(objectReceived["@context"])) delete objectReceived.id
430422
//A patch only alters existing keys. Remove non-existent keys from the object received in the request body.
431423
for (let k in objectReceived) {
432424
if (originalObject.hasOwnProperty(k)) {
@@ -459,10 +451,8 @@ const patchUpdate = async function (req, res, next) {
459451
delete patchedObject["__rerum"]
460452
delete patchedObject["_id"]
461453
delete patchedObject["@id"]
462-
if(_contextid(patchedObject["@context"])) {
463-
// id is also protected in this case, so it can't be set.
464-
delete patchedObject.id
465-
}
454+
// id is also protected in this case, so it can't be set.
455+
if(_contextid(patchedObject["@context"])) delete patchedObject.id
466456
delete patchedObject["@context"]
467457
let newObject = Object.assign(context, { "@id": process.env.RERUM_ID_PREFIX + id }, patchedObject, rerumProp, { "_id": id })
468458
console.log("PATCH UPDATE")
@@ -654,10 +644,9 @@ const patchUnset = async function (req, res, next) {
654644
delete objectReceived._id //can't unset this
655645
delete objectReceived.__rerum //can't unset this
656646
delete objectReceived["@id"] //can't unset this
657-
if(_contextid(originalObject["@context"])) {
658-
// id is also protected in this case, so it can't be unset.
659-
delete objectReceived.id
660-
}
647+
// id is also protected in this case, so it can't be unset.
648+
if(_contextid(originalObject["@context"])) delete objectReceived.id
649+
661650
/**
662651
* unset does not alter an existing key. It removes an existing key.
663652
* The request payload had {key:null} to flag keys to be removed.
@@ -689,12 +678,9 @@ const patchUnset = async function (req, res, next) {
689678
delete patchedObject["__rerum"]
690679
delete patchedObject["_id"]
691680
delete patchedObject["@id"]
692-
if(_contextid(patchedObject["@context"])) {
693-
// id is also protected in this case, so it can't be set.
694-
delete patchedObject.id
695-
}
681+
// id is also protected in this case, so it can't be set.
682+
if(_contextid(patchedObject["@context"])) delete patchedObject.id
696683
delete patchedObject["@context"]
697-
698684
let newObject = Object.assign(context, { "@id": process.env.RERUM_ID_PREFIX + id }, patchedObject, rerumProp, { "_id": id })
699685
console.log("PATCH UNSET")
700686
try {
@@ -786,10 +772,8 @@ const overwrite = async function (req, res, next) {
786772
delete objectReceived["@id"]
787773
delete objectReceived["_id"]
788774
delete objectReceived["__rerum"]
789-
if(_contextid(objectReceived["@context"])) {
790-
// id is also protected in this case, so it can't be set.
791-
delete objectReceived.id
792-
}
775+
// id is also protected in this case, so it can't be set.
776+
if(_contextid(objectReceived["@context"])) delete objectReceived.id
793777
delete objectReceived["@context"]
794778
let newObject = Object.assign(context, { "@id": originalObject["@id"] }, objectReceived, rerumProp, { "_id": id })
795779
let result
@@ -1016,13 +1000,17 @@ const bulkCreate = async function (req, res, next) {
10161000
next(createExpressError(err))
10171001
return
10181002
}
1019-
if (documents.filter(d=>d["@id"] ?? d.id).length > 0) {
1020-
err.message = "`/bulkCreate` will only accept objects without @id or id properties."
1021-
//err.status = 422
1003+
let gate = documents.filter(d=> {
1004+
if(Array.isArray(d) || typeof d !== "object") return d
1005+
const idcheck = _contextid(d["@context"]) ? d.id ?? d["@id"] : d["@id"]
1006+
if(idcheck) return d
1007+
})
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."
10221010
err.status = 400
10231011
next(createExpressError(err))
10241012
return
1025-
}
1013+
})
10261014
// TODO: bulkWrite SLUGS? Maybe assign an id to each document and then use that to create the slug?
10271015
// let slug = req.get("Slug")
10281016
// if(slug){
@@ -1041,10 +1029,8 @@ const bulkCreate = async function (req, res, next) {
10411029
const providedID = d._id
10421030
const id = isValidID(providedID) ? providedID : ObjectID()
10431031
d = utils.configureRerumOptions(generatorAgent, d)
1044-
if(_contextid(d["@context"])) {
1045-
// id is also protected in this case, so it can't be set.
1046-
delete d.id
1047-
}
1032+
// id is also protected in this case, so it can't be set.
1033+
if(_contextid(d["@context"])) delete d.id
10481034
d._id = id
10491035
d['@id'] = `${process.env.RERUM_ID_PREFIX}${id}`
10501036
bulkOps.push({ insertOne : { "document" : d }})
@@ -1071,7 +1057,7 @@ const bulkUpdate = async function (req, res, next) {
10711057
res.set("Content-Type", "application/json; charset=utf-8")
10721058
const documents = req.body
10731059
let err = {}
1074-
// TODO: validate documents gatekeeper function?
1060+
let encountered = []
10751061
if (!Array.isArray(documents)) {
10761062
err.message = "The request body must be an array of objects."
10771063
//err.status = 406
@@ -1086,21 +1072,27 @@ const bulkUpdate = async function (req, res, next) {
10861072
next(createExpressError(err))
10871073
return
10881074
}
1089-
if (documents.filter(d=>!(d["@id"] ?? d.id)).length > 0) {
1090-
err.message = "All objects in the body of a `/bulkUpdate` must contain an @id or id property."
1091-
//err.status = 422
1075+
let gate = documents.filter(d => {
1076+
if(Array.isArray(d) || typeof d !== "object") return d
1077+
const idcheck = _contextid(d["@context"]) ? d.id ?? d["@id"] : d["@id"]
1078+
if(!idcheck) return d
1079+
})
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."
10921082
err.status = 400
10931083
next(createExpressError(err))
10941084
return
1095-
}
1085+
})
10961086
let bulkOps = []
10971087
let generatorAgent = getAgentClaim(req, next)
1098-
for(const d of documents){
1099-
const objectReceived = d
1088+
for(const objectReceived of documents){
1089+
// We know it has an id
11001090
const idReceived = objectReceived["@id"] ?? objectReceived.id
1091+
// but we will not update the same thing twice.
1092+
if(encountered.includes(idReceived)) continue
1093+
encountered.push(idReceived)
11011094
if (idReceived) {
11021095
if(!idReceived.includes(process.env.RERUM_ID_PREFIX)){
1103-
//This would need imported. This is not supported in the bulk update. Skip this object, or error.
11041096
continue
11051097
}
11061098
let id = parseDocumentID(idReceived)
@@ -1112,7 +1104,6 @@ const bulkUpdate = async function (req, res, next) {
11121104
return
11131105
}
11141106
if (null === originalObject) {
1115-
//This object is not found. Skip it or error
11161107
continue
11171108
}
11181109
if (utils.isDeleted(originalObject)) {
@@ -1124,20 +1115,17 @@ const bulkUpdate = async function (req, res, next) {
11241115
delete objectReceived["__rerum"]
11251116
delete objectReceived["_id"]
11261117
delete objectReceived["@id"]
1127-
if(_contextid(objectReceived["@context"])) {
1128-
// id is also protected in this case, so it can't be set.
1129-
delete objectReceived.id
1130-
}
1118+
// id is also protected in this case, so it can't be set.
1119+
if(_contextid(objectReceived["@context"])) delete objectReceived.id
11311120
delete objectReceived["@context"]
11321121
let newObject = Object.assign(context, { "@id": process.env.RERUM_ID_PREFIX + id }, objectReceived, rerumProp, { "_id": id })
11331122
bulkOps.push({ insertOne : { "document" : newObject }})
1134-
let alteredObj = JSON.parse(JSON.stringify(originalObject))
1135-
if(alteredObj.__rerum.history.next.indexOf(newObject["@id"]) === -1){
1136-
alteredObj.__rerum.history.next.push(newObject["@id"])
1123+
if(originalObject.__rerum.history.next.indexOf(newObject["@id"]) === -1){
1124+
originalObject.__rerum.history.next.push(newObject["@id"])
11371125
const replaceOp = { replaceOne :
11381126
{
1139-
"filter" : { "_id": alteredObj["_id"] },
1140-
"replacement" : alteredObj,
1127+
"filter" : { "_id": originalObject["_id"] },
1128+
"replacement" : originalObject,
11411129
"upsert" : false
11421130
}
11431131
}

0 commit comments

Comments
 (0)