Skip to content

Commit

Permalink
fix: simple quotes escape in queries (#1227)
Browse files Browse the repository at this point in the history
  • Loading branch information
ranim-n authored Aug 30, 2024
1 parent 7d9c62f commit 526711d
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ class EntityServiceQueriesTests : WithTimescaleContainer, WithKafkaContainer {
"string~=\"(?i)another.*\", 1, urn:ngsi-ld:BeeHive:02",
"string!~=\"(?i)another.*\", 2, 'urn:ngsi-ld:BeeHive:01,urn:ngsi-ld:Apiary:05'",
"(string!~=\"(?i)another.*\";integer==213), 1, urn:ngsi-ld:BeeHive:01",
"simpleQuoteString~=\"(?i).*It's a name.*\", 1, urn:ngsi-ld:BeeHive:01",
"simpleQuoteString~=\"(?i)^it's.*\", 2, 'urn:ngsi-ld:BeeHive:01,urn:ngsi-ld:BeeHive:02'",
"simpleQuoteString==\"It's a name\", 1, urn:ngsi-ld:BeeHive:01",
"dateTime==2023-02-16T00:00:00Z, 1, urn:ngsi-ld:BeeHive:01",
"dateTime~=2023-02-16T00:00:00Z, 1, urn:ngsi-ld:BeeHive:01",
"dateTime>2023-02-16T00:00:00Z, 1, urn:ngsi-ld:BeeHive:02",
Expand All @@ -269,12 +272,14 @@ class EntityServiceQueriesTests : WithTimescaleContainer, WithKafkaContainer {
"multiInstanceProperty.datasetId==urn:ngsi-ld:Dataset:10, 0, ",
"jsonObject[aString]==\"flow monitoring\", 1, urn:ngsi-ld:BeeHive:02",
"jsonObject[aNumber]==93.93, 1, urn:ngsi-ld:BeeHive:02",
"jsonObject[aSimpleQuote]==\"precipitation's measures\", 1, urn:ngsi-ld:BeeHive:01",
"jsonObject[anObject.name]==\"River\", 1, urn:ngsi-ld:BeeHive:02",
"jsonObject[anObject.name]==\"Sea\", 0, ",
"integer==143..213, 2, 'urn:ngsi-ld:BeeHive:01,urn:ngsi-ld:BeeHive:02'",
"integer==144..213, 1, 'urn:ngsi-ld:BeeHive:01,urn:ngsi-ld:BeeHive:02'",
"integer==100..120, 0, ",
"listOfString==\"iot\", 1, urn:ngsi-ld:BeeHive:01",
"listOfString==\"data's processing\", 1, urn:ngsi-ld:BeeHive:01",
"listOfString==\"stellio\", 2, 'urn:ngsi-ld:BeeHive:01,urn:ngsi-ld:BeeHive:02'",
"'listOfString==\"iot\",\"dataviz\"', 2, 'urn:ngsi-ld:BeeHive:01,urn:ngsi-ld:BeeHive:02'",
"'listOfString==\"fiware\",\"egm\"', 0, ",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
"type": "Property",
"value": "aName"
},
"simpleQuoteString": {
"type": "Property",
"value": "It's a name"
},
"integer": {
"type": "Property",
"value": 213
Expand All @@ -22,7 +26,8 @@
"type": "Property",
"value": [
"iot",
"stellio"
"stellio",
"data's processing"
]
},
"listOfInt": {
Expand Down Expand Up @@ -59,7 +64,8 @@
"aList": [
"precipitation",
"wind"
]
],
"aSimpleQuote": "precipitation's measures"
}
},
"observedProperty": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
"type": "Property",
"value": "anotherName"
},
"simpleQuoteString": {
"type": "Property",
"value": "It's not a name"
},
"integer": {
"type": "Property",
"value": 143
Expand Down
15 changes: 9 additions & 6 deletions shared/src/main/kotlin/com/egm/stellio/shared/util/QueryUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ fun String.prepareDateValue() =
fun String.quote(): String =
"\"".plus(this).plus("\"")

fun String.escapeSimpleQuotes(): String =
this.replace("'", "''")

fun String.isRange(): Boolean =
this.contains("..")

Expand Down Expand Up @@ -155,7 +158,7 @@ private fun transformQQueryToSqlJsonPath(
"""
jsonb_path_exists(#{TARGET}#,
'$.$jsonAttributePath.**{0 to 2}."$JSONLD_VALUE" ? (@ $operator ${'$'}value)',
'{ "value": $value }')
'{ "value": ${value.escapeSimpleQuotes()}}')
""".trimIndent()
}
mainAttributePath.size > 1 && value.isURI() -> {
Expand All @@ -176,18 +179,18 @@ private fun transformQQueryToSqlJsonPath(
jsonb_path_exists(#{TARGET}#,
'$."${mainAttributePath[0]}"."$NGSILD_PROPERTY_VALUE".$jsonTrailingPath.**{0 to 1}."$JSONLD_VALUE" ?
(@ $operator ${'$'}value)',
'{ "value": $value }')
'{ "value": ${value.escapeSimpleQuotes()} }')
""".trimIndent()
}
operator == "like_regex" ->
"""
jsonb_path_exists(#{TARGET}#,
'$."${mainAttributePath[0]}"."$NGSILD_PROPERTY_VALUE"."$JSONLD_VALUE" ? (@ like_regex $value)')
'$."${mainAttributePath[0]}"."$NGSILD_PROPERTY_VALUE"."$JSONLD_VALUE" ? (@ like_regex ${value.escapeSimpleQuotes()})')
""".trimIndent()
operator == "not_like_regex" ->
"""
NOT (jsonb_path_exists(#{TARGET}#,
'$."${mainAttributePath[0]}"."$NGSILD_PROPERTY_VALUE"."$JSONLD_VALUE" ? (@ like_regex $value)'))
'$."${mainAttributePath[0]}"."$NGSILD_PROPERTY_VALUE"."$JSONLD_VALUE" ? (@ like_regex ${value.escapeSimpleQuotes()})'))
""".trimIndent()
value.isURI() ->
"""
Expand All @@ -211,14 +214,14 @@ private fun transformQQueryToSqlJsonPath(
.joinToString(separator = " JSONPATH_OR_FILTER ") { "@ == $it" }
"""
jsonb_path_exists(#{TARGET}#,
'$."${mainAttributePath[0]}"."$NGSILD_PROPERTY_VALUE"."$JSONLD_VALUE" ? ($valuesFilter)')
'$."${mainAttributePath[0]}"."$NGSILD_PROPERTY_VALUE"."$JSONLD_VALUE" ? (${valuesFilter.escapeSimpleQuotes()})')
""".trimIndent()
}
else ->
"""
jsonb_path_exists(#{TARGET}#,
'$."${mainAttributePath[0]}"."$NGSILD_PROPERTY_VALUE"."$JSONLD_VALUE" ? (@ $operator ${'$'}value)',
'{ "value": $value }')
'{ "value": ${value.escapeSimpleQuotes()} }')
""".trimIndent()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,21 @@ class SubscriptionServiceTests : WithTimescaleContainer, WithKafkaContainer {
.shouldSucceedWith { assertEquals(0, it.size) }
}

@Test
fun `it should return a subscription if entity matched a q query with a regular expression`() = runTest {
val expandedEntity = expandJsonLdEntity(entity, APIC_COMPOUND_CONTEXTS)
val subscription = gimmeSubscriptionFromMembers(
mapOf(
"watchedAttributes" to listOf(NGSILD_LOCATION_TERM),
"q" to "foodQuality!~=\"(?i).*It's good.*\""
)
)
subscriptionService.create(subscription, mockUserSub).shouldSucceed()

subscriptionService.getMatchingSubscriptions(expandedEntity, setOf(NGSILD_LOCATION_PROPERTY), ATTRIBUTE_UPDATED)
.shouldSucceedWith { assertEquals(1, it.size) }
}

@Test
fun `it should not return a subscription if throttling has not elapsed yet`() = runTest {
val expandedEntity = expandJsonLdEntity(entity, APIC_COMPOUND_CONTEXTS)
Expand Down

0 comments on commit 526711d

Please sign in to comment.