Skip to content

Commit f16a194

Browse files
GH-653: Fix sensitive data logging, etc (#497)
* GH-653: Fix sensitive data logging, silent exceptions, and null safety in inbox & SSE mappers - Downgrade inbox message logging from INFO to DEBUG without payload - Add WARN-level logging to ValtimoCloudEventMapper catch blocks - Replace non-null assertion with null-safe check in DocumentSseEventMapper - Return null instead of empty string for missing caseDefinitionVersionTag Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * GH-653: Fix copy-paste bug, null safety, and malformed error messages in RabbitMessagePublisher - Fix debug log that printed exchange instead of routingKey - Replace non-null assertion with proper null handling for confirmation result - Use idiomatic ?.let for returned message check - Remove stray escaped quotes from exception messages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent be40474 commit f16a194

8 files changed

Lines changed: 44 additions & 19 deletions

File tree

backend/case/src/main/kotlin/com/ritense/case/mapper/ConfigurationIssueSseEventMapper.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ class ConfigurationIssueSseEventMapper : SseEventMapper {
3131
val caseDefinitionKey = result?.get("caseDefinitionKey")?.asText()
3232
?: event.resultId
3333
?: return null
34+
val caseDefinitionVersionTag = result?.get("caseDefinitionVersionTag")?.asText()
35+
?: return null
3436
ConfigurationIssueUpdatedSseEvent(
3537
caseDefinitionKey = caseDefinitionKey,
36-
caseDefinitionVersionTag = result?.get("caseDefinitionVersionTag")?.asText() ?: ""
38+
caseDefinitionVersionTag = caseDefinitionVersionTag
3739
)
3840
}
3941
else -> null

backend/case/src/main/kotlin/com/ritense/document/mapper/DocumentSseEventMapper.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import com.ritense.document.event.DocumentUpdatedSseEvent
2727
import com.ritense.inbox.ValtimoEvent
2828
import com.ritense.valtimo.web.sse.domain.SseEventMapper
2929
import com.ritense.valtimo.web.sse.event.BaseSseEvent
30+
import io.github.oshai.kotlinlogging.KotlinLogging
3031

3132
class DocumentSseEventMapper : SseEventMapper {
3233

@@ -35,13 +36,20 @@ class DocumentSseEventMapper : SseEventMapper {
3536
DocumentCreated.TYPE -> CaseCreatedEvent()
3637
DocumentAssigned.TYPE -> CaseAssignedEvent()
3738
DocumentUnassigned.TYPE -> CaseUnassignedEvent()
38-
DocumentUpdated.TYPE -> event.let {
39-
DocumentUpdatedSseEvent(
40-
it.resultId!!
41-
)
39+
DocumentUpdated.TYPE -> {
40+
val resultId = event.resultId
41+
if (resultId == null) {
42+
logger.warn { "Received DocumentUpdated event without resultId, skipping" }
43+
return null
44+
}
45+
DocumentUpdatedSseEvent(resultId)
4246
}
4347

4448
else -> null
4549
}
4650
}
51+
52+
companion object {
53+
private val logger = KotlinLogging.logger {}
54+
}
4755
}

backend/case/src/test/kotlin/com/ritense/case/mapper/ConfigurationIssueSseEventMapperTest.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class ConfigurationIssueSseEventMapperTest {
5454
}
5555

5656
@Test
57-
fun `map should fallback to resultId when result is not ObjectNode`() {
57+
fun `map should return null when result is not ObjectNode and caseDefinitionVersionTag is missing`() {
5858
val event = ValtimoEvent(
5959
id = "test-id",
6060
type = ConfigurationIssueUpdated.TYPE,
@@ -68,10 +68,7 @@ class ConfigurationIssueSseEventMapperTest {
6868

6969
val result = mapper.map(event)
7070

71-
assertThat(result).isInstanceOf(ConfigurationIssueUpdatedSseEvent::class.java)
72-
val sseEvent = result as ConfigurationIssueUpdatedSseEvent
73-
assertThat(sseEvent.caseDefinitionKey).isEqualTo("fallback-key")
74-
assertThat(sseEvent.caseDefinitionVersionTag).isEqualTo("")
71+
assertThat(result).isNull()
7572
}
7673

7774
@Test

backend/case/src/test/kotlin/com/ritense/document/mapper/DocumentSseEventMapperTest.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ class DocumentSseEventMapperTest {
8282
assertEquals(documentId, (sseEvent as DocumentUpdatedSseEvent).documentId)
8383
}
8484

85+
@Test
86+
fun `should return null when document updated event has no resultId`() {
87+
val valtimoEvent = mock<ValtimoEvent>()
88+
whenever(valtimoEvent.type).thenReturn(DocumentUpdated.TYPE)
89+
whenever(valtimoEvent.resultId).thenReturn(null)
90+
91+
val sseEvent = documentSseEventMapper.map(valtimoEvent)
92+
assertNull(sseEvent)
93+
}
94+
8595
@Test
8696
fun `should map to null with unknown type event`() {
8797
val valtimoEvent = mock<ValtimoEvent>()

backend/inbox/src/main/kotlin/com/ritense/inbox/InboxHandlingService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class InboxHandlingService(
2222
private val eventHandlers: List<InboxEventHandler>,
2323
) {
2424
fun handle(message: String) {
25-
logger.info("Received message: {}", message)
25+
logger.debug { "Received inbox message" }
2626
eventHandlers.forEach { it.handle(message) }
2727
}
2828

backend/inbox/src/main/kotlin/com/ritense/inbox/ValtimoCloudEventMapper.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import com.fasterxml.jackson.module.kotlin.readValue
2121
import io.cloudevents.CloudEvent
2222
import io.cloudevents.core.provider.EventFormatProvider
2323
import io.cloudevents.jackson.JsonFormat
24+
import io.github.oshai.kotlinlogging.KotlinLogging
2425

2526
class ValtimoCloudEventMapper(
2627
private val objectMapper: ObjectMapper
@@ -34,6 +35,7 @@ class ValtimoCloudEventMapper(
3435
return try {
3536
cloudEventFormat.deserialize(payload.encodeToByteArray())
3637
} catch (ex: Exception) {
38+
logger.warn(ex) { "Failed to deserialize CloudEvent from payload" }
3739
null
3840
}
3941
}
@@ -52,7 +54,12 @@ class ValtimoCloudEventMapper(
5254
result = cloudEventData?.result
5355
)
5456
} catch (ex: Exception) {
57+
logger.warn(ex) { "Failed to map CloudEvent to ValtimoEvent" }
5558
null
5659
}
5760
}
61+
62+
companion object {
63+
private val logger = KotlinLogging.logger {}
64+
}
5865
}

backend/outbox/outbox-rabbitmq/src/main/kotlin/com/ritense/outbox/rabbitmq/RabbitMessagePublisher.kt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class RabbitMessagePublisher(
4040
rabbitTemplate.exchange ?: ""
4141
}
4242
private val routingKey: String = routingKey ?: run {
43-
logger.debug { "Using Rabbit template default routingKey: ${rabbitTemplate.exchange}" }
43+
logger.debug { "Using Rabbit template default routingKey: ${rabbitTemplate.routingKey}" }
4444
rabbitTemplate.routingKey ?: ""
4545
}
4646

@@ -58,14 +58,15 @@ class RabbitMessagePublisher(
5858

5959
try {
6060
val result = correlationData.future[deliveryTimeout.toMillis(), TimeUnit.MILLISECONDS]
61-
if (!result!!.isAck) {
62-
throw MessagePublishingFailed("Outbox message was not acknowledged: reason=${result.reason}, routingKey=${routingKey}, msgId=${message.id}, correlationId= ${correlationData.id}\"")
63-
} else if (correlationData.returned != null) {
64-
val returned = correlationData.returned!!
65-
throw MessagePublishingFailed("Could not deliver outbox message: routingKey=${returned.routingKey}, code=${returned.replyCode}, msg=${returned.replyText}, routingKey=${routingKey}, msgId=${message.id}, correlationId= ${correlationData.id}\"")
61+
?: throw MessagePublishingFailed("Outbox message confirmation result was null: routingKey=${routingKey}, msgId=${message.id}, correlationId=${correlationData.id}")
62+
if (!result.isAck) {
63+
throw MessagePublishingFailed("Outbox message was not acknowledged: reason=${result.reason}, routingKey=${routingKey}, msgId=${message.id}, correlationId=${correlationData.id}")
64+
}
65+
correlationData.returned?.let { returned ->
66+
throw MessagePublishingFailed("Could not deliver outbox message: routingKey=${returned.routingKey}, code=${returned.replyCode}, msg=${returned.replyText}, routingKey=${routingKey}, msgId=${message.id}, correlationId=${correlationData.id}")
6667
}
6768
} catch (timeoutException: TimeoutException) {
68-
throw MessagePublishingFailed("Outbox message delivery was not confirmed in time: routingKey=${routingKey}, msgId=${message.id}, correlationId= ${correlationData.id}")
69+
throw MessagePublishingFailed("Outbox message delivery was not confirmed in time: routingKey=${routingKey}, msgId=${message.id}, correlationId=${correlationData.id}")
6970
}
7071
}
7172

documentation/release-notes/13.x.x/13.22.0/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@
1818

1919
## Bugfixes
2020

21-
* New bugfix.
21+
* Fixed sensitive data logging in inbox messages, silent exception swallowing in cloud event mapping, and null safety issues in SSE event mappers.

0 commit comments

Comments
 (0)