diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 96d575fabf..386eb6cec8 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1 +1,5 @@ - Fix: memory leak in POST /v2/op/notify operation (#4261) +- Fix: changed the default value of `-dbTimeout` to 0 to resolve conflict with `-dbURI` (#4496) +- Fix: wrong INFO startup log showing ORION_MONGO_TIMEOUT, ORION_IN_REQ_PAYLOAD_MAX_SIZE and ORION_OUT_REQ_MSG_MAX_SIZE env var values (#4496) +- Fix: return 400 Bad Request when subject.entities exists but it is an empty array (#4499) + diff --git a/src/app/contextBroker/contextBroker.cpp b/src/app/contextBroker/contextBroker.cpp index bf81abec8f..d1cc8a57b2 100644 --- a/src/app/contextBroker/contextBroker.cpp +++ b/src/app/contextBroker/contextBroker.cpp @@ -309,7 +309,7 @@ PaArgument paArgs[] = { "-dbDisableRetryWrites", &dbDisableRetryWrites, "MONGO_DISABLE_RETRY_WRITES", PaBool, PaOpt, false, false, true, DBDISABLERETRYWRITES_DESC }, { "-db", dbName, "MONGO_DB", PaString, PaOpt, _i "orion", PaNL, PaNL, DB_DESC }, - { "-dbTimeout", &dbTimeout, "MONGO_TIMEOUT", PaULong, PaOpt, 10000, 0, UINT_MAX, DB_TMO_DESC }, + { "-dbTimeout", &dbTimeout, "MONGO_TIMEOUT", PaULong, PaOpt, 0, 0, UINT_MAX, DB_TMO_DESC }, { "-dbPoolSize", &dbPoolSize, "MONGO_POOL_SIZE", PaInt, PaOpt, 10, 1, 10000, DBPS_DESC }, { "-ipv4", &useOnlyIPv4, "USEIPV4", PaBool, PaOpt, false, false, true, USEIPV4_DESC }, @@ -979,13 +979,17 @@ static void logEnvVars(void) { LM_I(("env var ORION_%s (%s): %d", aP->envName, aP->option, *((int*) aP->varP))); } + else if (aP->type == PaULong) + { + LM_I(("env var ORION_%s (%s): %d", aP->envName, aP->option, *((unsigned long*) aP->varP))); + } else if (aP->type == PaDouble) { LM_I(("env var ORION_%s (%s): %d", aP->envName, aP->option, *((double*) aP->varP))); } else { - LM_I(("env var ORION_%s (%s): %d", aP->envName, aP->option)); + LM_E(("cannot show env var ORION_%s (%s) due to unrecognized type: %d", aP->envName, aP->option, aP->type)); } } } diff --git a/src/lib/jsonParseV2/parseSubscription.cpp b/src/lib/jsonParseV2/parseSubscription.cpp index 3724528ba1..4207dfa023 100644 --- a/src/lib/jsonParseV2/parseSubscription.cpp +++ b/src/lib/jsonParseV2/parseSubscription.cpp @@ -278,6 +278,11 @@ static std::string parseSubject(ConnectionInfo* ciP, SubscriptionUpdate* subsP, return badInput(ciP, errorString); } + if (subsP->subject.entities.size() == 0) + { + return badInput(ciP, "subject entities is empty"); + } + // Condition if (subject.HasMember("condition")) { diff --git a/src/lib/mongoDriver/mongoConnectionPool.cpp b/src/lib/mongoDriver/mongoConnectionPool.cpp index ed0d1db07c..855896753e 100644 --- a/src/lib/mongoDriver/mongoConnectionPool.cpp +++ b/src/lib/mongoDriver/mongoConnectionPool.cpp @@ -407,7 +407,7 @@ static std::string composeMongoUri optionPrefix = "&"; } } - + LM_T(LmtMongo, ("MongoDB connection URI: '%s'", offuscatePassword(uri, passwd).c_str())); return uri; diff --git a/src/lib/ngsiNotify/Notifier.cpp b/src/lib/ngsiNotify/Notifier.cpp index f452b51ac2..aae1ecb34f 100644 --- a/src/lib/ngsiNotify/Notifier.cpp +++ b/src/lib/ngsiNotify/Notifier.cpp @@ -121,8 +121,7 @@ static bool setPayload const std::string& notifPayload, const SubscriptionId& subscriptionId, Entity& en, - const std::string& service, - const std::string& token, + std::map* replacementsP, const std::vector& attrsFilter, bool blacklist, const std::vector& metadataFilter, @@ -171,9 +170,7 @@ static bool setPayload } else { - std::map replacements; - buildReplacementsMap(en, service, token, &replacements); - if (!macroSubstitute(payloadP, notifPayload, &replacements, "")) + if (!macroSubstitute(payloadP, notifPayload, replacementsP, "")) { return false; } @@ -197,19 +194,12 @@ static bool setPayload static bool setJsonPayload ( orion::CompoundValueNode* json, - const Entity& en, - const std::string& service, - const std::string& token, + std::map* replacementsP, std::string* payloadP, std::string* mimeTypeP ) { - // Prepare a map for macro replacements. We firstly tried to pass Entity object to - // orion::CompoundValueNode()::toJson(), but the include Entity.h in CompoundValueNode.h - // makes compiler to cry (maybe some kind of circular dependency problem?) - std::map replacements; - buildReplacementsMap(en, service, token, &replacements); - *payloadP = json->toJson(&replacements); + *payloadP = json->toJson(replacementsP); *mimeTypeP = "application/json"; // this can be overriden by headers field return true; } @@ -247,8 +237,7 @@ static bool setNgsiPayload const Entity& ngsi, const SubscriptionId& subscriptionId, Entity& en, - const std::string& service, - const std::string& token, + std::map* replacementsP, const std::vector& attrsFilter, bool blacklist, const std::vector& metadataFilter, @@ -256,12 +245,6 @@ static bool setNgsiPayload RenderFormat renderFormat ) { - // Prepare a map for macro replacements. We firstly tried to pass Entity object to - // orion::CompoundValueNode()::toJson(), but the include Entity.h in CompoundValueNode.h - // makes compiler to cry (maybe some kind of circular dependency problem?) - std::map replacements; - buildReplacementsMap(en, service, token, &replacements); - NotifyContextRequest ncr; ContextElementResponse cer; @@ -273,7 +256,7 @@ static bool setNgsiPayload else { // If id is not found in the replacements macro, we use en.id. - effectiveId = removeQuotes(smartStringValue(ngsi.id, &replacements, '"' + en.id + '"')); + effectiveId = removeQuotes(smartStringValue(ngsi.id, replacementsP, '"' + en.id + '"')); } std::string effectiveType; @@ -284,7 +267,7 @@ static bool setNgsiPayload else { // If type is not found in the replacements macro, we use en.type. - effectiveType = removeQuotes(smartStringValue(ngsi.type, &replacements, '"' + en.type + '"')); + effectiveType = removeQuotes(smartStringValue(ngsi.type, replacementsP, '"' + en.type + '"')); } cer.entity.fill(effectiveId, effectiveType, en.isPattern, en.servicePath); @@ -310,11 +293,11 @@ static bool setNgsiPayload if ((renderFormat == NGSI_V2_SIMPLIFIEDNORMALIZED) || (renderFormat == NGSI_V2_SIMPLIFIEDKEYVALUES)) { - *payloadP = ncr.toJson(renderFormat, attrsFilter, blacklist, metadataFilter, &replacements); + *payloadP = ncr.toJson(renderFormat, attrsFilter, blacklist, metadataFilter, replacementsP); } else { - *payloadP = ncr.toJson(NGSI_V2_NORMALIZED, attrsFilter, blacklist, metadataFilter, &replacements); + *payloadP = ncr.toJson(NGSI_V2_NORMALIZED, attrsFilter, blacklist, metadataFilter, replacementsP); } return true; @@ -354,7 +337,7 @@ static SenderThreadParams* buildSenderParamsCustom // Used by several macroSubstitute() calls along this function std::map replacements; - buildReplacementsMap(en, service, xauthToken, &replacements); + buildReplacementsMap(en, tenant, xauthToken, &replacements); // // 1. Verb/Method @@ -396,7 +379,7 @@ static SenderThreadParams* buildSenderParamsCustom { bool includePayload = (notification.type == ngsiv2::HttpNotification ? notification.httpInfo.includePayload : notification.mqttInfo.includePayload); std::string notifPayload = (notification.type == ngsiv2::HttpNotification ? notification.httpInfo.payload : notification.mqttInfo.payload); - if (!setPayload(includePayload, notifPayload, subscriptionId, en, tenant, xauthToken, attrsFilter, blacklist, metadataFilter, &payload, &mimeType, &renderFormat)) + if (!setPayload(includePayload, notifPayload, subscriptionId, en, &replacements, attrsFilter, blacklist, metadataFilter, &payload, &mimeType, &renderFormat)) { // Warning already logged in macroSubstitute() return NULL; @@ -405,14 +388,14 @@ static SenderThreadParams* buildSenderParamsCustom else if (customPayloadType == ngsiv2::CustomPayloadType::Json) { orion::CompoundValueNode* json = (notification.type == ngsiv2::HttpNotification ? notification.httpInfo.json : notification.mqttInfo.json); - setJsonPayload(json, en, tenant, xauthToken, &payload, &mimeType); + setJsonPayload(json, &replacements, &payload, &mimeType); renderFormat = NGSI_V2_CUSTOM; } else // customPayloadType == ngsiv2::CustomPayloadType::Ngsi { // Important to use const& for Entity here. Otherwise problems may occur in the object release logic const Entity& ngsi = (notification.type == ngsiv2::HttpNotification ? notification.httpInfo.ngsi : notification.mqttInfo.ngsi); - if (!setNgsiPayload(ngsi, subscriptionId, en, tenant, xauthToken, attrsFilter, blacklist, metadataFilter, &payload, renderFormat)) + if (!setNgsiPayload(ngsi, subscriptionId, en, &replacements, attrsFilter, blacklist, metadataFilter, &payload, renderFormat)) { // Warning already logged in macroSubstitute() return NULL; diff --git a/test/functionalTest/cases/3658_env_vars/env_vars.test b/test/functionalTest/cases/3658_env_vars/env_vars.test index 495c359dec..2ede8f83af 100644 --- a/test/functionalTest/cases/3658_env_vars/env_vars.test +++ b/test/functionalTest/cases/3658_env_vars/env_vars.test @@ -95,7 +95,7 @@ Extended Usage: contextBroker [option '-U' (extended usage)] [option '-dbSSL' (enable SSL connection to DB)] ORION_MONGO_SSL FALSE /FALSE/ [option '-dbDisableRetryWrites' (set retryWrite parameter to false in DB connect] ORION_MONGO_DISABLE_RETRY_WRITES FALSE /FALSE/ [option '-db' ] ORION_MONGO_DB 'orion' /'orion'/ - [option '-dbTimeout' ] ORION_MONGO_POOL_SIZE 1 <= 10 /10/ <= 10000 [option '-ipv4' (use ip v4 only)] ORION_USEIPV4 FALSE /FALSE/ [option '-ipv6' (use ip v6 only)] ORION_USEIPV6 FALSE /FALSE/ diff --git a/test/functionalTest/cases/4499_subs_without_entities_return_error/sub_without_entities_return_error.test b/test/functionalTest/cases/4499_subs_without_entities_return_error/sub_without_entities_return_error.test new file mode 100644 index 0000000000..c1f71e8d51 --- /dev/null +++ b/test/functionalTest/cases/4499_subs_without_entities_return_error/sub_without_entities_return_error.test @@ -0,0 +1,193 @@ +# Copyright 2024 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Subscription without entities return error + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create subscription without subject.entities field, see error +# 02. Create subscription with subject.entities field with 0 items, see error +# 03. Create subscription +# 04. Update subscription without subject.entities field, see error +# 05. Update subscription with subject.entities field with 0 items, see error +# + + +echo "01. Create subscription without subject.entities field, see error" +echo "=================================================================" +payload='{ + "subject": { + }, + "notification": { + "http": { + "url": "http://127.0.0.1:'${LISTENER_PORT}'/notify" + } + } +}' +orionCurl --url /v2/subscriptions --payload "$payload" +echo +echo + + +echo "02. Create subscription with subject.entities field with 0 items, see error" +echo "===========================================================================" +payload='{ + "subject": { + "entities": [ + ] + }, + "notification": { + "http": { + "url": "http://127.0.0.1:'${LISTENER_PORT}'/notify" + } + } +}' +orionCurl --url /v2/subscriptions --payload "$payload" +echo +echo + + +echo "03. Create subscription" +echo "=======================" +payload='{ + "subject": { + "entities": [ + { + "id" : "E", + "type": "T" + } + ] + }, + "notification": { + "http": { + "url": "http://127.0.0.1:'${LISTENER_PORT}'/notify" + } + } +}' +orionCurl --url /v2/subscriptions --payload "$payload" +echo +echo + + +SUB_ID=$(echo "$_responseHeaders" | grep Location | awk -F/ '{ print $4 }' | tr -d "\r\n") + + +echo "04. Update subscription without subject.entities field, see error" +echo "=================================================================" +payload='{ + "subject": { + } +}' +orionCurl --url /v2/subscriptions/$SUB_ID -X PATCH --payload "$payload" +echo +echo + + +echo "05. Update subscription with subject.entities field with 0 items, see error" +echo "===========================================================================" +payload='{ + "subject": { + "entities": [ + ] + } +}' +orionCurl --url /v2/subscriptions/$SUB_ID -X PATCH --payload "$payload" +echo +echo + + +--REGEXPECT-- +01. Create subscription without subject.entities field, see error +================================================================= +HTTP/1.1 400 Bad Request +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 68 + +{ + "description": "no subject entities specified", + "error": "BadRequest" +} + + +02. Create subscription with subject.entities field with 0 items, see error +=========================================================================== +HTTP/1.1 400 Bad Request +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 64 + +{ + "description": "subject entities is empty", + "error": "BadRequest" +} + + +03. Create subscription +======================= +HTTP/1.1 201 Created +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Location: /v2/subscriptions/REGEX([0-9a-f]{24}) +Content-Length: 0 + + + +04. Update subscription without subject.entities field, see error +================================================================= +HTTP/1.1 400 Bad Request +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 68 + +{ + "description": "no subject entities specified", + "error": "BadRequest" +} + + +05. Update subscription with subject.entities field with 0 items, see error +=========================================================================== +HTTP/1.1 400 Bad Request +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 64 + +{ + "description": "subject entities is empty", + "error": "BadRequest" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB