Skip to content

Commit 5788184

Browse files
MohamadJaaraGarzasyamilmedinaborichellowohassine
authored
feat: harden ClientCapabilityDTO for api v7 [WPB-14882] (#3151)
* feat: harden ClientCapabilityDTO for api v7 * add tests * detekt * detekt * chore: disable folders update handler (#3161) * fix: Login to second device does not have MLS capabilities RC (#3165) * feat: add usecase to get team url (WPB-14872) (#3157) (#3168) * feat: add usecase to get team url * feat:detekt * feat: detekt * feat: detekt (cherry picked from commit abcd037) * chore: upgrade to cc3, fixes new_transaction in paralell (#3170) * test: add tests for old format parser in capabilities (#3173) * Update libs.versions.toml * Update UserPropertiesEventReceiver.kt * Update UserPropertiesEventReceiver.kt * Update UserPropertiesEventReceiverTest.kt * fix * fix tests * missing imports * fix circular dependency * Trigger CI * remove not needed dependency --------- Co-authored-by: Jakub Żerko <[email protected]> Co-authored-by: Yamil Medina <[email protected]> Co-authored-by: boris <[email protected]> Co-authored-by: Oussama Hassine <[email protected]>
1 parent f506f90 commit 5788184

File tree

9 files changed

+120
-18
lines changed

9 files changed

+120
-18
lines changed

data/src/commonMain/kotlin/com/wire/kalium/logic/data/client/ClientModel.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,9 @@ enum class DeviceType {
6969
Unknown;
7070
}
7171

72-
enum class ClientCapability {
73-
LegalHoldImplicitConsent;
72+
sealed class ClientCapability {
73+
data object LegalHoldImplicitConsent : ClientCapability()
74+
data class Unknown(val name: String) : ClientCapability()
7475
}
7576

7677
data class OtherUserClient(

logic/src/commonMain/kotlin/com/wire/kalium/logic/data/client/ClientMapper.kt

+2
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,12 @@ class ClientMapper(
198198

199199
private fun toClientCapabilityDTO(clientCapability: ClientCapability): ClientCapabilityDTO = when (clientCapability) {
200200
ClientCapability.LegalHoldImplicitConsent -> ClientCapabilityDTO.LegalHoldImplicitConsent
201+
is ClientCapability.Unknown -> ClientCapabilityDTO.Unknown(clientCapability.name)
201202
}
202203

203204
private fun fromClientCapabilityDTO(clientCapabilityDTO: ClientCapabilityDTO): ClientCapability = when (clientCapabilityDTO) {
204205
ClientCapabilityDTO.LegalHoldImplicitConsent -> ClientCapability.LegalHoldImplicitConsent
206+
is ClientCapabilityDTO.Unknown -> ClientCapability.Unknown(clientCapabilityDTO.name)
205207
}
206208

207209
fun fromOtherUsersClientsDTO(otherUsersClients: List<ClientEntity>): List<OtherUserClient> =

logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt

+5-4
Original file line numberDiff line numberDiff line change
@@ -2164,14 +2164,15 @@ class UserSessionScope internal constructor(
21642164
kaliumLogger = userScopedLogger,
21652165
)
21662166

2167-
val getTeamUrlUseCase: GetTeamUrlUseCase by lazy {
2168-
GetTeamUrlUseCase(
2167+
val getTeamUrlUseCase: GetTeamUrlUseCase
2168+
get() = GetTeamUrlUseCase(
21692169
userId,
21702170
authenticationScope.serverConfigRepository,
21712171
)
2172-
}
21732172

2174-
private val inCallReactionsRepository: InCallReactionsRepository = InCallReactionsDataSource()
2173+
private val inCallReactionsRepository: InCallReactionsRepository by lazy {
2174+
InCallReactionsDataSource()
2175+
}
21752176

21762177
/**
21772178
* This will start subscribers of observable work per user session, as long as the user is logged in.

logic/src/commonTest/kotlin/com/wire/kalium/logic/sync/receiver/UserPropertiesEventReceiverTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class UserPropertiesEventReceiverTest {
8585
suspend fun withUpdateConversationFolders() = apply {
8686
coEvery {
8787
conversationFolderRepository.updateConversationFolders(any())
88-
}.returns(Either.Right(Unit))
88+
}.returns(Either.Right(Unit))
8989
}
9090

9191
fun arrange() = this to userPropertiesEventReceiver

mocks/src/commonMain/kotlin/com/wire/kalium/mocks/responses/ClientResponseJson.kt

+5-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import com.wire.kalium.network.api.authenticated.client.ClientCapabilityDTO
2222
import com.wire.kalium.network.api.authenticated.client.ClientDTO
2323
import com.wire.kalium.network.api.authenticated.client.ClientTypeDTO
2424
import com.wire.kalium.network.api.authenticated.client.DeviceTypeDTO
25+
import kotlinx.serialization.encodeToString
26+
import kotlinx.serialization.json.Json
2527

2628
object ClientResponseJson {
2729
private val jsonProvider = { serializable: ClientDTO ->
@@ -36,7 +38,7 @@ object ClientResponseJson {
3638
| "cookie": "${serializable.cookie}",
3739
| "model": "${serializable.model}",
3840
| "capabilities": [
39-
| "${serializable.capabilities[0]}"
41+
| ${Json.encodeToString(serializable.capabilities[0])}
4042
| ],
4143
| "mls_public_keys": ${serializable.mlsPublicKeys}
4244
|}
@@ -57,9 +59,9 @@ object ClientResponseJson {
5759
| "model": "${serializable.model}",
5860
| "capabilities": {
5961
| "capabilities": [
60-
| "${serializable.capabilities[0]}"
62+
| ${Json.encodeToString(serializable.capabilities[0])}
6163
| ]
62-
| }
64+
| },
6365
| "mls_public_keys": ${serializable.mlsPublicKeys}
6466
|}
6567
""".trimMargin()

network-model/build.gradle.kts

-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ kotlin {
4545

4646
// KTX
4747
implementation(libs.ktxDateTime)
48-
4948
}
5049
}
5150
}

network-model/src/commonMain/kotlin/com/wire/kalium/network/api/authenticated/client/ClientRequest.kt

+32-5
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,14 @@ import com.wire.kalium.network.api.authenticated.client.DeviceTypeDTO.Unknown
2222
import com.wire.kalium.network.api.authenticated.prekey.PreKeyDTO
2323
import com.wire.kalium.network.api.model.MLSPublicKey
2424
import com.wire.kalium.network.api.model.UserId
25+
import kotlinx.serialization.KSerializer
2526
import kotlinx.serialization.SerialName
2627
import kotlinx.serialization.Serializable
28+
import kotlinx.serialization.descriptors.PrimitiveKind
29+
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
30+
import kotlinx.serialization.descriptors.SerialDescriptor
31+
import kotlinx.serialization.encoding.Decoder
32+
import kotlinx.serialization.encoding.Encoder
2733

2834
@Serializable
2935
data class RegisterClientRequest(
@@ -86,12 +92,33 @@ enum class DeviceTypeDTO {
8692
}
8793
}
8894

89-
@Serializable
90-
enum class ClientCapabilityDTO {
95+
@Serializable(with = ClientCapabilityDTOSerializer::class)
96+
sealed class ClientCapabilityDTO {
9197
@SerialName("legalhold-implicit-consent")
92-
LegalHoldImplicitConsent {
93-
override fun toString(): String {
94-
return "legalhold-implicit-consent"
98+
data object LegalHoldImplicitConsent : ClientCapabilityDTO()
99+
data class Unknown(val name: String) : ClientCapabilityDTO()
100+
}
101+
102+
object ClientCapabilityDTOSerializer : KSerializer<ClientCapabilityDTO> {
103+
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(
104+
serialName = "ClientCapabilityDTO",
105+
kind = PrimitiveKind.STRING
106+
)
107+
108+
override fun serialize(encoder: Encoder, value: ClientCapabilityDTO) {
109+
when (value) {
110+
is ClientCapabilityDTO.LegalHoldImplicitConsent ->
111+
encoder.encodeString("legalhold-implicit-consent")
112+
113+
is ClientCapabilityDTO.Unknown ->
114+
encoder.encodeString(value.name)
115+
}
116+
}
117+
118+
override fun deserialize(decoder: Decoder): ClientCapabilityDTO {
119+
return when (val value = decoder.decodeString()) {
120+
"legalhold-implicit-consent" -> ClientCapabilityDTO.LegalHoldImplicitConsent
121+
else -> ClientCapabilityDTO.Unknown(value)
95122
}
96123
}
97124
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Wire
3+
* Copyright (C) 2024 Wire Swiss GmbH
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see http://www.gnu.org/licenses/.
17+
*/
18+
package com.wire.kalium.network.api.authenticated.client
19+
20+
import kotlinx.serialization.SerializationException
21+
import kotlinx.serialization.json.Json
22+
import kotlin.test.Test
23+
import kotlin.test.assertEquals
24+
import kotlin.test.assertFailsWith
25+
26+
27+
class ClientCapabilityDTOSerializerTest {
28+
29+
private val json = Json { ignoreUnknownKeys = true }
30+
31+
@Test
32+
fun serialize_legal_hold_implicit_consent() {
33+
val capability = ClientCapabilityDTO.LegalHoldImplicitConsent
34+
val result = json.encodeToString(ClientCapabilityDTO.serializer(), capability)
35+
assertEquals("\"legalhold-implicit-consent\"", result)
36+
}
37+
38+
@Test
39+
fun serialize_unknown_capability() {
40+
val capability = ClientCapabilityDTO.Unknown("custom-capability")
41+
val result = json.encodeToString(ClientCapabilityDTO.serializer(), capability)
42+
assertEquals("\"custom-capability\"", result)
43+
}
44+
45+
@Test
46+
fun deserialize_legal_hold_implicit_consent() {
47+
val jsonString = "\"legalhold-implicit-consent\""
48+
val result = json.decodeFromString(ClientCapabilityDTO.serializer(), jsonString)
49+
assertEquals(ClientCapabilityDTO.LegalHoldImplicitConsent, result)
50+
}
51+
52+
@Test
53+
fun deserialize_unknown_capability() {
54+
val jsonString = "\"unknown-capability\""
55+
val result = json.decodeFromString(ClientCapabilityDTO.serializer(), jsonString)
56+
assertEquals(ClientCapabilityDTO.Unknown("unknown-capability"), result)
57+
}
58+
59+
@Test
60+
fun deserialization_fails_on_invalid_json_format() {
61+
val invalidJson = "12345" // Invalid format for a string
62+
assertFailsWith<SerializationException> {
63+
json.decodeFromString(ClientCapabilityDTO.serializer(), invalidJson)
64+
}
65+
}
66+
}

network/src/commonTest/kotlin/com/wire/kalium/api/v0/user/client/ClientApiV0Test.kt

+6-2
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,12 @@ internal class ClientApiV0Test : ApiTest() {
6464
@Test
6565
fun givenAValidRegisterClientRequest_whenCallingTheRegisterClientEndpointWithOldFormat_theRequestShouldBeConfiguredCorrectly() =
6666
runTest {
67+
68+
val rowJson = VALID_REGISTER_CLIENT_OLD_RESPONSE.rawJson
69+
val data = VALID_REGISTER_CLIENT_OLD_RESPONSE.serializableData
70+
6771
val networkClient = mockAuthenticatedNetworkClient(
68-
VALID_REGISTER_CLIENT_OLD_RESPONSE.rawJson,
72+
rowJson,
6973
statusCode = HttpStatusCode.Created,
7074
assertion = {
7175
assertPost()
@@ -77,7 +81,7 @@ internal class ClientApiV0Test : ApiTest() {
7781
val clientApi: ClientApi = ClientApiV0(networkClient)
7882
val response = clientApi.registerClient(REGISTER_CLIENT_REQUEST.serializableData)
7983
assertTrue(response.isSuccessful())
80-
assertEquals(VALID_REGISTER_CLIENT_OLD_RESPONSE.serializableData, response.value)
84+
assertEquals(data, response.value)
8185
}
8286

8387
@Test

0 commit comments

Comments
 (0)