Skip to content

Commit bd897ee

Browse files
committed
chore: serialize history client messages
1 parent 85ab4fc commit bd897ee

File tree

12 files changed

+136
-38
lines changed

12 files changed

+136
-38
lines changed

conversation-history/src/commonMain/kotlin/com/wire/kalium/conversation/history/data/HistoryClientDAO.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*/
1818
package com.wire.kalium.conversation.history.data
1919

20-
import com.wire.kalium.conversation.history.HistoryClient
20+
import com.wire.kalium.logic.data.history.HistoryClient
2121
import com.wire.kalium.persistence.dao.QualifiedIDEntity
2222
import kotlinx.coroutines.flow.Flow
2323
import kotlinx.datetime.Instant

conversation-history/src/commonMain/kotlin/com/wire/kalium/conversation/history/data/SQLiteHistoryClientDAO.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ package com.wire.kalium.conversation.history.data
1919

2020
import app.cash.sqldelight.coroutines.asFlow
2121
import app.cash.sqldelight.coroutines.mapToList
22-
import com.wire.kalium.conversation.history.HistoryClient
23-
import com.wire.kalium.logic.data.id.ConversationId
22+
import com.wire.kalium.logic.data.history.HistoryClient
2423
import com.wire.kalium.persistence.HistoryClientQueries
2524
import com.wire.kalium.persistence.dao.QualifiedIDEntity
2625
import kotlinx.coroutines.Dispatchers
@@ -44,12 +43,10 @@ internal class SQLiteHistoryClientDAO internal constructor(
4443
* Maps a database entity to a domain model.
4544
*/
4645
private fun mapToHistoryClient(
47-
conversationId: QualifiedIDEntity,
4846
id: String,
4947
secret: ByteArray,
5048
creationDate: Instant
5149
): HistoryClient = HistoryClient(
52-
conversationId = ConversationId(conversationId.value, conversationId.domain),
5350
id = id,
5451
creationTime = creationDate,
5552
secret = HistoryClient.Secret(secret)

conversation-history/src/commonTest/kotlin/com/wire/kalium/conversation/history/data/SQLiteHistoryClientDAOTest.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
package com.wire.kalium.conversation.history.data
1919

2020
import app.cash.turbine.test
21-
import com.wire.kalium.logic.data.id.ConversationId
2221
import com.wire.kalium.persistence.TestUserDatabase
2322
import com.wire.kalium.persistence.dao.QualifiedIDEntity
2423
import com.wire.kalium.persistence.dao.UserIDEntity
@@ -121,7 +120,6 @@ class SQLiteHistoryClientDAOTest {
121120
// Then
122121
assertEquals(1, result.size)
123122
with(result.first()) {
124-
assertEquals(ConversationId(conversationId.value, conversationId.domain), this.conversationId)
125123
assertEquals(clientId, this.id)
126124
assertEquals(creationDate, this.creationTime)
127125
assertTrue(this.secret.value.contentEquals(secret))
@@ -166,12 +164,10 @@ class SQLiteHistoryClientDAOTest {
166164
assertEquals(1, result2.size)
167165

168166
with(result1.first()) {
169-
assertEquals(ConversationId(conversationId1.value, conversationId1.domain), this.conversationId)
170167
assertEquals(clientId1, this.id)
171168
}
172169

173170
with(result2.first()) {
174-
assertEquals(ConversationId(conversationId2.value, conversationId2.domain), this.conversationId)
175171
assertEquals(clientId2, this.id)
176172
}
177173
}
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,12 @@
1515
* You should have received a copy of the GNU General Public License
1616
* along with this program. If not, see http://www.gnu.org/licenses/.
1717
*/
18-
package com.wire.kalium.conversation.history
18+
package com.wire.kalium.logic.data.history
1919

20-
import com.wire.kalium.logic.data.id.ConversationId
2120
import kotlinx.datetime.Instant
2221
import kotlin.time.ExperimentalTime
2322

24-
public data class HistoryClient @OptIn(ExperimentalTime::class) constructor(
25-
val conversationId: ConversationId,
23+
data class HistoryClient @OptIn(ExperimentalTime::class) constructor(
2624
val id: String,
2725
val creationTime: Instant,
2826
val secret: Secret,
@@ -45,6 +43,5 @@ public data class HistoryClient @OptIn(ExperimentalTime::class) constructor(
4543
override fun hashCode(): Int {
4644
return value.contentHashCode()
4745
}
48-
4946
}
5047
}

data/src/commonMain/kotlin/com/wire/kalium/logic/data/message/Message.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,19 @@ sealed interface Message {
260260
is MessageContent.CompositeEdited -> mutableMapOf(
261261
typeKey to "compositeEdited"
262262
)
263+
264+
MessageContent.History.ClientsRequest -> mutableMapOf(
265+
typeKey to "historyClientsRequest",
266+
)
267+
268+
is MessageContent.History.ClientsResponse -> mutableMapOf(
269+
typeKey to "historyClientsResponse",
270+
"count" to content.clients.size
271+
)
272+
273+
is MessageContent.History.NewClientAvailable -> mutableMapOf(
274+
typeKey to "historyNewClientAvailable",
275+
)
263276
}
264277

265278
val standardProperties = mapOf(

data/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageContent.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ package com.wire.kalium.logic.data.message
2121
import com.wire.kalium.logger.obfuscateId
2222
import com.wire.kalium.logic.data.conversation.ClientId
2323
import com.wire.kalium.logic.data.conversation.Conversation
24+
import com.wire.kalium.logic.data.history.HistoryClient
2425
import com.wire.kalium.logic.data.id.ConversationId
2526
import com.wire.kalium.logic.data.id.MessageButtonId
2627
import com.wire.kalium.logic.data.id.MessageId
@@ -401,6 +402,12 @@ sealed interface MessageContent {
401402
val emojis: Map<String, Int>
402403
) : Signaling
403404

405+
sealed interface History : Signaling {
406+
data class NewClientAvailable(val client: HistoryClient) : History
407+
data class ClientsResponse(val clients: List<HistoryClient>) : History
408+
data object ClientsRequest : History
409+
}
410+
404411
data class Multipart(
405412
val value: String?,
406413
val linkPreviews: List<MessageLinkPreview> = emptyList(),
@@ -421,7 +428,7 @@ sealed interface MessageContent {
421428
* @return A string representing the type of content.
422429
* Useful for logging. Plain strings must be used, otherwise it may be affected by code minification.
423430
*/
424-
@Suppress("ComplexMethod")
431+
@Suppress("ComplexMethod", "LongMethod")
425432
fun MessageContent?.getType() = when (this) {
426433
is MessageContent.Asset -> "Asset"
427434
is MessageContent.FailedDecryption -> "FailedDecryption"
@@ -478,6 +485,9 @@ fun MessageContent?.getType() = when (this) {
478485
is MessageContent.InCallEmoji -> "InCallEmoji"
479486
is MessageContent.Multipart -> "Multipart"
480487
is MessageContent.CompositeEdited -> "CompositeEdited"
488+
MessageContent.History.ClientsRequest -> "History.ClientsRequest"
489+
is MessageContent.History.ClientsResponse -> "History.ClientsResponse"
490+
is MessageContent.History.NewClientAvailable -> "History.NewClientAvailable"
481491
null -> "null"
482492
}
483493

data/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageContentLogging.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,7 @@ inline fun MessageContent.FromProto.typeDescription(): String = when (this) {
4444
is MessageContent.InCallEmoji -> "InCallEmoji"
4545
is MessageContent.Multipart -> "Multipart"
4646
is MessageContent.CompositeEdited -> "CompositeEdited"
47+
MessageContent.History.ClientsRequest -> "History.ClientsRequest"
48+
is MessageContent.History.ClientsResponse -> "History.ClientsResponse"
49+
is MessageContent.History.NewClientAvailable -> "History.NewClientAvailable"
4750
}

logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/PersistMessageUseCase.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ internal class PersistMessageUseCaseImpl(
131131
is MessageContent.DataTransfer -> false
132132
is MessageContent.InCallEmoji -> false
133133
is MessageContent.Multipart -> true
134+
is MessageContent.History -> false
134135
}
135136

136137
@Suppress("ComplexMethod")
@@ -188,6 +189,7 @@ internal class PersistMessageUseCaseImpl(
188189
is MessageContent.MemberChange.RemovedFromTeam,
189190
is MessageContent.TeamMemberRemoved,
190191
is MessageContent.DataTransfer,
191-
is MessageContent.InCallEmoji -> false
192+
is MessageContent.InCallEmoji,
193+
is MessageContent.History -> false
192194
}
193195
}

logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/ProtoContentMapper.kt

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.wire.kalium.logic.data.asset.AssetTransferStatus
2525
import com.wire.kalium.logic.data.asset.toModel
2626
import com.wire.kalium.logic.data.asset.toProto
2727
import com.wire.kalium.logic.data.conversation.Conversation
28+
import com.wire.kalium.logic.data.history.HistoryClient
2829
import com.wire.kalium.logic.data.id.ConversationId
2930
import com.wire.kalium.logic.data.id.IdMapper
3031
import com.wire.kalium.logic.data.message.composite.CompositeButton
@@ -51,7 +52,12 @@ import com.wire.kalium.protobuf.messages.DataTransfer
5152
import com.wire.kalium.protobuf.messages.Ephemeral
5253
import com.wire.kalium.protobuf.messages.External
5354
import com.wire.kalium.protobuf.messages.GenericMessage
55+
import com.wire.kalium.protobuf.messages.GenericMessage.Content.Availability
56+
import com.wire.kalium.protobuf.messages.GenericMessage.Content.Deleted
5457
import com.wire.kalium.protobuf.messages.GenericMessage.UnknownStrategy
58+
import com.wire.kalium.protobuf.messages.HistoryClientAvailable
59+
import com.wire.kalium.protobuf.messages.HistoryClientRequest
60+
import com.wire.kalium.protobuf.messages.HistoryClientResponse
5561
import com.wire.kalium.protobuf.messages.InCallEmoji
5662
import com.wire.kalium.protobuf.messages.Knock
5763
import com.wire.kalium.protobuf.messages.LastRead
@@ -66,9 +72,12 @@ import com.wire.kalium.protobuf.messages.Quote
6672
import com.wire.kalium.protobuf.messages.Reaction
6773
import com.wire.kalium.protobuf.messages.Text
6874
import com.wire.kalium.protobuf.messages.TrackingIdentifier
75+
import com.wire.kalium.util.DateTimeUtil.toIsoDateTimeString
6976
import io.mockative.Mockable
7077
import kotlinx.datetime.Instant
7178
import pbandk.ByteArr
79+
import pbandk.Message
80+
import com.wire.kalium.protobuf.messages.HistoryClient as ProtoHistoryClient
7281

7382
@Mockable
7483
interface ProtoContentMapper {
@@ -130,9 +139,9 @@ class ProtoContentMapperImpl(
130139
is MessageContent.Calling -> packCalling(readableContent)
131140
is MessageContent.Asset -> packAsset(readableContent, expectsReadConfirmation, legalHoldStatus)
132141
is MessageContent.Knock -> packKnock(readableContent, legalHoldStatus)
133-
is MessageContent.DeleteMessage -> GenericMessage.Content.Deleted(MessageDelete(messageId = readableContent.messageId))
142+
is MessageContent.DeleteMessage -> Deleted(MessageDelete(messageId = readableContent.messageId))
134143
is MessageContent.DeleteForMe -> packHidden(readableContent)
135-
is MessageContent.Availability -> GenericMessage.Content.Availability(
144+
is MessageContent.Availability -> Availability(
136145
availabilityMapper.fromModelAvailabilityToProto(
137146
readableContent.status
138147
)
@@ -161,6 +170,27 @@ class ProtoContentMapperImpl(
161170
is MessageContent.DataTransfer -> packDataTransfer(readableContent)
162171
is MessageContent.InCallEmoji -> packInCallEmoji(readableContent)
163172
is MessageContent.Multipart -> packMultipart(readableContent, expectsReadConfirmation, legalHoldStatus)
173+
is MessageContent.History -> packHistoryMessage(readableContent)
174+
}
175+
}
176+
177+
private fun packHistoryMessage(readableContent: MessageContent.History): GenericMessage.Content<out Any> {
178+
fun mapHistoryClientToProto(historyClient: HistoryClient): ProtoHistoryClient {
179+
return ProtoHistoryClient(
180+
clientId = historyClient.id,
181+
createdAt = historyClient.creationTime.toIsoDateTimeString(),
182+
secret = ByteArr(historyClient.secret.value)
183+
)
184+
}
185+
return when (readableContent) {
186+
MessageContent.History.ClientsRequest -> GenericMessage.Content.HistoryClientRequest(HistoryClientRequest())
187+
is MessageContent.History.ClientsResponse -> GenericMessage.Content.HistoryClientResponse(
188+
HistoryClientResponse(readableContent.clients.map { mapHistoryClientToProto(it) })
189+
)
190+
191+
is MessageContent.History.NewClientAvailable -> GenericMessage.Content.HistoryClientAvailable(
192+
HistoryClientAvailable(mapHistoryClientToProto(readableContent.client))
193+
)
164194
}
165195
}
166196

@@ -337,6 +367,7 @@ class ProtoContentMapperImpl(
337367
is MessageContent.CompositeEdited,
338368
is MessageContent.DataTransfer,
339369
is MessageContent.InCallEmoji,
370+
is MessageContent.History,
340371
is MessageContent.Multipart -> throw IllegalArgumentException(
341372
"Unexpected message content type: ${readableContent.getType()}"
342373
)
@@ -349,7 +380,9 @@ class ProtoContentMapperImpl(
349380
External(
350381
ByteArr(protoContent.otrKey),
351382
protoContent.sha256?.let { ByteArr(it) },
352-
protoContent.encryptionAlgorithm?.let { encryptionAlgorithmMapper.toProtoBufModel(it) }
383+
protoContent.encryptionAlgorithm?.let {
384+
encryptionAlgorithmMapper.toProtoBufModel(it)
385+
}
353386
)
354387
)
355388

@@ -450,6 +483,10 @@ class ProtoContentMapperImpl(
450483

451484
is GenericMessage.Content.InCallEmoji -> unpackInCallEmoji(protoContent)
452485

486+
is GenericMessage.Content.HistoryClientAvailable -> unpackHistoryClientAvailable(protoContent)
487+
is GenericMessage.Content.HistoryClientRequest -> unpackHistoryClientRequest()
488+
is GenericMessage.Content.HistoryClientResponse -> unpackHistoryClientResponse(protoContent)
489+
453490
null -> {
454491
kaliumLogger.w(
455492
"Null content when parsing protobuf. Message UUID = ${genericMessage.messageId.obfuscateId()}" +
@@ -889,6 +926,21 @@ class ProtoContentMapperImpl(
889926
)
890927
}
891928

929+
private fun unpackHistoryClientRequest(): MessageContent.History =
930+
MessageContent.History.ClientsRequest
931+
932+
private fun protoHistoryClientToHistoryClient(protoClient: ProtoHistoryClient) = HistoryClient(
933+
id = protoClient.clientId,
934+
secret = HistoryClient.Secret(protoClient.secret.array),
935+
creationTime = Instant.parse(protoClient.createdAt),
936+
)
937+
938+
private fun unpackHistoryClientResponse(protoContent: GenericMessage.Content.HistoryClientResponse): MessageContent.History =
939+
MessageContent.History.ClientsResponse(protoContent.value.clients.map(::protoHistoryClientToHistoryClient))
940+
941+
private fun unpackHistoryClientAvailable(protoContent: GenericMessage.Content.HistoryClientAvailable): MessageContent.History =
942+
MessageContent.History.NewClientAvailable(protoHistoryClientToHistoryClient(protoContent.value.client))
943+
892944
private fun extractConversationId(
893945
qualifiedConversationID: QualifiedConversationId?,
894946
unqualifiedConversationID: String

logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/conversation/message/ApplicationMessageHandler.kt

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -184,23 +184,7 @@ internal class ApplicationMessageHandlerImpl(
184184
userRepository.updateOtherUserAvailabilityStatus(signaling.senderUserId, content.status)
185185
}
186186

187-
is MessageContent.ClientAction -> {
188-
logger.i(message = "ClientAction status update received: ")
189-
190-
val message = Message.System(
191-
id = signaling.id,
192-
content = MessageContent.CryptoSessionReset,
193-
conversationId = signaling.conversationId,
194-
date = signaling.date,
195-
senderUserId = signaling.senderUserId,
196-
status = signaling.status,
197-
senderUserName = signaling.senderUserName,
198-
expirationData = null
199-
)
200-
201-
logger.i(message = "Persisting crypto session reset system message..")
202-
persistMessage(message)
203-
}
187+
is MessageContent.ClientAction -> handleClientAction(signaling)
204188

205189
is MessageContent.Reaction -> persistReaction(content, signaling.conversationId, signaling.senderUserId, signaling.date)
206190
is MessageContent.DeleteMessage -> deleteMessageHandler(content, signaling.conversationId, signaling.senderUserId)
@@ -240,9 +224,31 @@ internal class ApplicationMessageHandlerImpl(
240224
)
241225

242226
is MessageContent.CompositeEdited -> messageCompositeEditHandler.handle(signaling, content)
227+
228+
is MessageContent.History -> TODO("HISTORY CLIENTS ARE NOT HANDLED YET")
243229
}
244230
}
245231

232+
private suspend fun handleClientAction(
233+
signaling: Message.Signaling,
234+
) {
235+
logger.i(message = "ClientAction status update received: ")
236+
237+
val message = Message.System(
238+
id = signaling.id,
239+
content = MessageContent.CryptoSessionReset,
240+
conversationId = signaling.conversationId,
241+
date = signaling.date,
242+
senderUserId = signaling.senderUserId,
243+
status = signaling.status,
244+
senderUserName = signaling.senderUserName,
245+
expirationData = null
246+
)
247+
248+
logger.i(message = "Persisting crypto session reset system message..")
249+
persistMessage(message)
250+
}
251+
246252
private suspend fun processMessage(message: Message.Regular) {
247253
logger.i(message = "Message received: { \"message\" : ${message.toLogString()} }")
248254
when (val content = message.content) {

0 commit comments

Comments
 (0)