/* **************************************************************************** * * parseEntity - * * This function is used to parse two slightly different payloads: * - POST /v2/entities * - POST /v2/entities/<eid> * * In the latter case, "id" CANNOT be in the payload, while in the former case, * "id" MUST be in the payload. * * In the case of /v2/entities/<eid>, the entityId of 'Entity* eP' is set in * the service routine postEntity. * * Also, if the URI param 'options' includes the value 'keyValues', then the * parse changes for compound values of attributes. If the value is a JSON object * then there is no looking inside to find the 'value' field, but the attribute is * always treated as a compound attribute. * */ std::string parseEntity(ConnectionInfo* ciP, Entity* eP, bool eidInURL) { Document document; document.Parse(ciP->payload); if (document.HasParseError()) { alarmMgr.badInput(clientIp, "JSON parse error"); eP->oe.fill(SccBadRequest, "Errors found in incoming JSON buffer", ERROR_STRING_PARSERROR); ciP->httpStatusCode = SccBadRequest; return eP->render(ciP, EntitiesRequest); } if (!document.IsObject()) { alarmMgr.badInput(clientIp, "JSON Parse Error"); eP->oe.fill(SccBadRequest, "Errors found in incoming JSON buffer", ERROR_STRING_PARSERROR); ciP->httpStatusCode = SccBadRequest; return eP->render(ciP, EntitiesRequest); } if (eidInURL == false) { if (!document.HasMember("id")) { alarmMgr.badInput(clientIp, "No entity id specified"); eP->oe.fill(SccBadRequest, "no entity id specified", "BadRequest"); ciP->httpStatusCode = SccBadRequest;; return eP->render(ciP, EntitiesRequest); } } if (eidInURL == true) { if (document.HasMember("id")) { alarmMgr.badInput(clientIp, "entity id specified in payload"); eP->oe.fill(SccBadRequest, "entity id specified in payload", "BadRequest"); ciP->httpStatusCode = SccBadRequest;; return eP->render(ciP, EntitiesRequest); } if (document.HasMember("type")) { alarmMgr.badInput(clientIp, "entity type specified in payload"); eP->oe.fill(SccBadRequest, "entity type specified in payload", "BadRequest"); ciP->httpStatusCode = SccBadRequest;; return eP->render(ciP, EntitiesRequest); } } else if (document.ObjectEmpty()) { // // Initially we used the method "Empty". As the broker crashed inside that method, some // research was made and "ObjectEmpty" was found. As the broker stopped crashing and complaints // about crashes with small docs and "Empty()" were found on the internet, we opted to use ObjectEmpty // alarmMgr.badInput(clientIp, "Empty payload"); eP->oe.fill(SccBadRequest, "empty payload", "BadRequest"); ciP->httpStatusCode = SccBadRequest; return eP->render(ciP, EntitiesRequest); } int membersFound = 0; for (Value::ConstMemberIterator iter = document.MemberBegin(); iter != document.MemberEnd(); ++iter) { std::string name = iter->name.GetString(); std::string type = jsonParseTypeNames[iter->value.GetType()]; ++membersFound; if (name == "id") { if (eidInURL == false) { if (type != "String") { alarmMgr.badInput(clientIp, "invalid JSON type for entity id"); eP->oe.fill(SccBadRequest, "invalid JSON type for entity id", "BadRequest"); ciP->httpStatusCode = SccBadRequest;; return eP->render(ciP, EntitiesRequest); } eP->id = iter->value.GetString(); } else // "id" is present in payload for /v2/entities/<eid> - not a valid payload { alarmMgr.badInput(clientIp, "'id' is not a valid attribute"); eP->oe.fill(SccBadRequest, "invalid input, 'id' as attribute", "BadRequest"); ciP->httpStatusCode = SccBadRequest;; return eP->render(ciP, EntitiesRequest); } } else if (name == "type") { if (type != "String") { alarmMgr.badInput(clientIp, "invalid JSON type for entity type"); eP->oe.fill(SccBadRequest, "invalid JSON type for entity type", "BadRequest"); ciP->httpStatusCode = SccBadRequest;; return eP->render(ciP, EntitiesRequest); } eP->type = iter->value.GetString(); eP->typeGiven = true; } else // attribute { ContextAttribute* caP = new ContextAttribute(); eP->attributeVector.push_back(caP); std::string r = parseContextAttribute(ciP, iter, caP); if (r != "OK") { alarmMgr.badInput(clientIp, "parse error in context attribute"); eP->oe.fill(SccBadRequest, r, "BadRequest"); ciP->httpStatusCode = SccBadRequest; return eP->render(ciP, EntitiesRequest); } } } if (membersFound == 0) { eP->oe.fill(SccBadRequest, "empty payload", "BadRequest"); ciP->httpStatusCode = SccBadRequest; return eP->render(ciP, EntitiesRequest); } if (eidInURL == false) { if (eP->id == "") { alarmMgr.badInput(clientIp, "empty entity id"); eP->oe.fill(SccBadRequest, "empty entity id", "BadRequest"); ciP->httpStatusCode = SccBadRequest; return eP->render(ciP, EntitiesRequest); } } if (!eP->typeGiven) { eP->type = DEFAULT_ENTITY_TYPE; } return "OK"; }
/* **************************************************************************** * * parseBatchUpdate - */ std::string parseBatchUpdate(ConnectionInfo* ciP, BatchUpdate* burP) { Document document; document.Parse(ciP->payload); if (document.HasParseError()) { ErrorCode ec; alarmMgr.badInput(clientIp, "JSON Parse Error"); ec.fill(ERROR_STRING_PARSERROR, "Errors found in incoming JSON buffer"); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } if (!document.IsObject()) { ErrorCode ec; alarmMgr.badInput(clientIp, "JSON Parse Error"); ec.fill("BadRequest", "JSON Parse Error"); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } else if (document.ObjectEmpty()) { ErrorCode ec; alarmMgr.badInput(clientIp, "Empty JSON payload"); ec.fill("BadRequest", "empty payload"); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } else if (!document.HasMember("entities")) { ErrorCode ec; std::string details = "Invalid JSON payload, mandatory field /entities/ not found"; alarmMgr.badInput(clientIp, details); ec.fill("BadRequest", details); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } else if (!document.HasMember("actionType")) { ErrorCode ec; std::string details = "Invalid JSON payload, mandatory field /actionType/ not found"; alarmMgr.badInput(clientIp, details); ec.fill("BadRequest", details); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } for (Value::ConstMemberIterator iter = document.MemberBegin(); iter != document.MemberEnd(); ++iter) { std::string name = iter->name.GetString(); std::string type = jsonParseTypeNames[iter->value.GetType()]; if (name == "entities") { std::string r = parseEntityVector(ciP, iter, &burP->entities, true); // param 4: attributes are allowed in payload if (r != "OK") { ErrorCode ec("BadRequest", r); alarmMgr.badInput(clientIp, r); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } } else if (name == "actionType") { burP->updateActionType.set(iter->value.GetString()); } else { std::string description = std::string("Unrecognized field in JSON payload: /") + name + "/"; ErrorCode ec("BadRequest", description); alarmMgr.badInput(clientIp, description); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } } return "OK"; }
/* **************************************************************************** * * parseBatchQuery - */ std::string parseBatchQuery(ConnectionInfo* ciP, BatchQuery* bqrP) { Document document; document.Parse(ciP->payload); if (document.HasParseError()) { ErrorCode ec; alarmMgr.badInput(clientIp, "JSON Parse Error"); ec.fill(ERROR_STRING_PARSERROR, "Errors found in incoming JSON buffer"); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } if (!document.IsObject()) { ErrorCode ec; alarmMgr.badInput(clientIp, "JSON Parse Error"); ec.fill("BadRequest", "JSON Parse Error"); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } else if (document.ObjectEmpty()) { ErrorCode ec; alarmMgr.badInput(clientIp, "Empty JSON payload"); ec.fill("BadRequest", "empty payload"); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } else if (!document.HasMember("entities") && !document.HasMember("attributes") && !document.HasMember("scopes")) { ErrorCode ec; alarmMgr.badInput(clientIp, "Invalid JSON payload, no relevant fields found"); ec.fill("BadRequest", "Invalid JSON payload, no relevant fields found"); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } for (Value::ConstMemberIterator iter = document.MemberBegin(); iter != document.MemberEnd(); ++iter) { std::string name = iter->name.GetString(); std::string type = jsonParseTypeNames[iter->value.GetType()]; if (name == "entities") { std::string r = parseEntityVector(ciP, iter, &bqrP->entities, false); // param 4: attributes are NOT allowed in payload if (r != "OK") { ErrorCode ec("BadRequest", r); alarmMgr.badInput(clientIp, r); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } } else if (name == "attributes") { std::string r = parseAttributeList(ciP, iter, &bqrP->attributeV); if (r != "OK") { ErrorCode ec("BadRequest", r); alarmMgr.badInput(clientIp, r); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } } else if (name == "scopes") { std::string r = parseScopeVector(ciP, iter, &bqrP->scopeV); if (r != "OK") { ErrorCode ec("BadRequest", r); alarmMgr.badInput(clientIp, r); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } } else { std::string description = std::string("Unrecognizedfield in JSON payload: /") + name + "/"; ErrorCode ec("BadRequest", description); alarmMgr.badInput(clientIp, description); ciP->httpStatusCode = SccBadRequest; return ec.toJson(true); } } return "OK"; }