Skip to content

Commit

Permalink
Merge pull request #4468 from telefonicaid/hardening/4462_ngsi_patchi…
Browse files Browse the repository at this point in the history
…ng_id_type_macro_always_stringfly

FIX NGSI patching macro subscription covering completely the string always cast to string for id/type
  • Loading branch information
mapedraza authored Jan 12, 2024
2 parents 5b7fa18 + bb72014 commit bd04adc
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Fix: update forwarding was not working when entity type is not included in the request (#4460)
- Fix: DateTime and geo:json types were not supported in custom notifications using ngsi patching (#4435)
- Fix: logDeprecate not working correctly (`geo:json` wrongly considered as deprecated)
- Fix: in custom notification NGSI payload patching macro subscription covering completely the string where is used, always cast to string for id/type (#4462)
- Fix: improve error traces (#4387)
- Fix: on delete attributes operation, the lack of attribute in entity doesn't preclude the deletion of attributes which do exist (this way behaving same way as update attributes operation)
- Fix: POST /v2/entities/E/attrs?options=append was wrongly creating entities
Expand Down
2 changes: 2 additions & 0 deletions doc/manuals/orion-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2255,6 +2255,8 @@ Some notes to take into account when using `ngsi`:
* If the macro *covers completely the string where is used*, then the JSON nature of the attribute value
is taken into account. For instance, `"value": "${temperature}"` resolves to `"value": 10`
if temperature attribute is a number or to `"value": "10"` if `temperature` attribute is a string.
* Exception to this is `id` and `type`. Given that entity id and type must be a string (as decribed
in [this section](#identifiers-syntax-restrictions)) the attribute value is always casted to string in this case.
* If the macro *is only part of string where is used*, then the attribute value is always casted
to string. For instance, `"value": "Temperature is: ${temperature}"` resolves to
`"value": "Temperature is 10"` even if temperature attribute is a number. Note that if the
Expand Down
30 changes: 22 additions & 8 deletions src/lib/ngsiNotify/Notifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,26 @@ static bool setJsonPayload
}


/* ****************************************************************************
*
* removeQuotes -
*
* Entity id and type are special. Different from a attribute, they are always
* strings and cannot take a number, boolean, etc. as value.
*/
inline std::string removeQuotes(std::string s)
{
if (s[0] == '"')
{
return s.substr(1, s.size()-2);
}
else
{
return s;
}
}



/* ****************************************************************************
*
Expand Down Expand Up @@ -252,10 +272,7 @@ static bool setNgsiPayload
else
{
// If id is not found in the replacements macro, we use en.id.
// In addition, note we have to remove double quotes here given the
// values stored in replacements map are "raw strings"
std::string s = smartStringValue(ngsi.id, &replacements, '"' + en.id + '"');
effectiveId = s.substr(1, s.size()-2);
effectiveId = removeQuotes(smartStringValue(ngsi.id, &replacements, '"' + en.id + '"'));
}

std::string effectiveType;
Expand All @@ -266,10 +283,7 @@ static bool setNgsiPayload
else
{
// If type is not found in the replacements macro, we use en.type.
// In addition, note we have to remove double quotes here given the
// values stored in replacements map are "raw strings"
std::string s = smartStringValue(ngsi.type, &replacements, '"' + en.type + '"');
effectiveType = s.substr(1, s.size()-2);
effectiveType = removeQuotes(smartStringValue(ngsi.type, &replacements, '"' + en.type + '"'));
}

cer.entity.fill(effectiveId, effectiveType, en.isPattern, en.servicePath);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
# 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--
NGSI patching macro subscription covering completely the string always cast to string for id/type

--SHELL-INIT--
dbInit CB
brokerStart CB
accumulatorStart --pretty-print

--SHELL--

#
# 01. Create custom sub1 with ngsi id and type with the value of idAtt and typeAtt attributes
# 02. Create entity E with idAtt=1 and typeAtt=2 as numbers
# 03. Update entity E with idAtt=110 and typeAtt=220 as numbers
# 04. Dump accumulator and see notifications with id "1" and type "2" and id "110" and type "220"
#


echo "01. Create custom sub1 with ngsi id and type with the value of idAtt and typeAtt attributes"
echo "==========================================================================================="
payload='{
"subject": {
"entities": [
{
"id" : "E",
"type": "T"
}
]
},
"notification": {
"httpCustom": {
"url": "http://127.0.0.1:'${LISTENER_PORT}'/notify",
"ngsi": {
"id": "${idAtt}",
"type": "${typeAtt}"
}
}
}
}'
orionCurl --url /v2/subscriptions --payload "$payload"
echo
echo


echo "02. Create entity E with idAtt=1 and typeAtt=2 as numbers"
echo "========================================================="
payload='{
"id": "E",
"type": "T",
"idAtt": {
"value": 1,
"type": "Number"
},
"typeAtt": {
"value": 2,
"type": "Number"
}
}'
orionCurl --url /v2/entities --payload "$payload"
echo
echo


echo "03. Update entity E with idAtt=110 and typeAtt=220 as numbers"
echo "============================================================="
payload='{
"idAtt": {
"value": 110,
"type": "Number"
},
"typeAtt": {
"value": 220,
"type": "Number"
}
}'
orionCurl --url /v2/entities/E/attrs -X PATCH --payload "$payload"
echo
echo


echo '04. Dump accumulator and see notifications with id "1" and type "2" and id "110" and type "220"'
echo "==============================================================================================="
accumulatorDump
echo
echo


--REGEXPECT--
01. Create custom sub1 with ngsi id and type with the value of idAtt and typeAtt attributes
===========================================================================================
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



02. Create entity E with idAtt=1 and typeAtt=2 as numbers
=========================================================
HTTP/1.1 201 Created
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})
Location: /v2/entities/E?type=T
Content-Length: 0



03. Update entity E with idAtt=110 and typeAtt=220 as numbers
=============================================================
HTTP/1.1 204 No Content
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})



04. Dump accumulator and see notifications with id "1" and type "2" and id "110" and type "220"
===============================================================================================
POST http://127.0.0.1:REGEX(\d+)/notify
Fiware-Servicepath: /
Content-Length: 178
User-Agent: orion/REGEX(\d+\.\d+\.\d+.*)
Ngsiv2-Attrsformat: normalized
Host: 127.0.0.1:REGEX(\d+)
Accept: application/json
Content-Type: application/json; charset=utf-8
Fiware-Correlator: REGEX([0-9a-f\-]{36}); cbnotif=1

{
"data": [
{
"id": "1",
"idAtt": {
"metadata": {},
"type": "Number",
"value": 1
},
"type": "2",
"typeAtt": {
"metadata": {},
"type": "Number",
"value": 2
}
}
],
"subscriptionId": "REGEX([0-9a-f]{24})"
}
=======================================
POST http://127.0.0.1:REGEX(\d+)/notify
Fiware-Servicepath: /
Content-Length: 186
User-Agent: orion/REGEX(\d+\.\d+\.\d+.*)
Ngsiv2-Attrsformat: normalized
Host: 127.0.0.1:REGEX(\d+)
Accept: application/json
Content-Type: application/json; charset=utf-8
Fiware-Correlator: REGEX([0-9a-f\-]{36}); cbnotif=1

{
"data": [
{
"id": "110",
"idAtt": {
"metadata": {},
"type": "Number",
"value": 110
},
"type": "220",
"typeAtt": {
"metadata": {},
"type": "Number",
"value": 220
}
}
],
"subscriptionId": "REGEX([0-9a-f]{24})"
}
=======================================


--TEARDOWN--
brokerStop CB
dbDrop CB
accumulatorStop

0 comments on commit bd04adc

Please sign in to comment.