Skip to content

Commit 4aa76ec

Browse files
authored
feat(apps): system message handling for app access changed in conversations (WPB-21442) (#3704)
* feat: add system message infra for persistence * feat: add message insertion for app flag changed user triggered and by event * feat: add message insertion for app flag changed user triggered and by event * feat: add message insertion for app flag changed user triggered and by event * feat: add message insertion for app flag changed user triggered and by event * feat: adjustment of sys message when creating * feat: adjustment of sys message when creating * feat: test coverage and detekt cleanup * feat: comments * feat: broken tests fix * feat: broken tests fix * feat: broken tests fix
1 parent 5226269 commit 4aa76ec

File tree

31 files changed

+1350
-51
lines changed

31 files changed

+1350
-51
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,9 +423,15 @@ sealed interface Message {
423423
MessageContent.NewConversationWithCellMessage -> mutableMapOf(
424424
typeKey to "newConversationWithCellMessage"
425425
)
426+
426427
MessageContent.NewConversationWithCellSelfDeleteDisabledMessage -> mutableMapOf(
427428
typeKey to "newConversationWithCellSelfDeleteDisabledMessage"
428429
)
430+
431+
is MessageContent.ConversationAppsEnabledChanged -> mutableMapOf(
432+
typeKey to "conversationAppsEnabledChanged",
433+
"isEnabled" to "${content.isEnabled}"
434+
)
429435
}
430436

431437
val standardProperties = mapOf(

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,10 @@ sealed interface MessageContent {
339339
val receiptMode: Boolean
340340
) : System
341341

342+
data class ConversationAppsEnabledChanged(
343+
val isEnabled: Boolean
344+
) : System
345+
342346
data class ConversationReceiptModeChanged(
343347
val receiptMode: Boolean
344348
) : System
@@ -499,6 +503,7 @@ fun MessageContent?.getType() = when (this) {
499503
null -> "null"
500504
MessageContent.NewConversationWithCellMessage -> "NewConversationWithCell"
501505
MessageContent.NewConversationWithCellSelfDeleteDisabledMessage -> "NewConversationWithCellSelfDeleteDisabled"
506+
is MessageContent.ConversationAppsEnabledChanged -> "ConversationAppsEnabledChanged"
502507
}
503508

504509
sealed interface MessagePreviewContent {

logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationGroupRepository.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ internal class ConversationGroupRepositoryImpl(
177177
newGroupConversationSystemMessagesCreator.value.conversationStarted(conversationEntity)
178178
}.flatMap {
179179
newGroupConversationSystemMessagesCreator.value.conversationCellStatus(conversationEntity)
180+
}.flatMap {
181+
newGroupConversationSystemMessagesCreator.value.conversationAppsAccessIfEnabled(
182+
conversationId = conversationEntity.id.toModel(),
183+
hasAppsAccessEnabled = conversationResponse.hasAppsAccessEnabled(),
184+
creatorId = selfUserId,
185+
)
180186
}.flatMap {
181187
when (protocol) {
182188
is Conversation.ProtocolInfo.Proteus -> Either.Right(setOf())

logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/NewGroupConversationSystemMessagesCreator.kt

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

20-
import kotlin.uuid.Uuid
2120
import com.wire.kalium.common.error.CoreFailure
2221
import com.wire.kalium.common.functional.Either
2322
import com.wire.kalium.common.functional.fold
23+
import com.wire.kalium.common.functional.right
2424
import com.wire.kalium.logic.data.id.ConversationId
2525
import com.wire.kalium.logic.data.id.QualifiedIdMapper
2626
import com.wire.kalium.logic.data.id.SelfTeamIdProvider
@@ -37,6 +37,7 @@ import com.wire.kalium.persistence.dao.message.LocalId
3737
import io.mockative.Mockable
3838
import kotlinx.datetime.Clock
3939
import kotlinx.datetime.Instant
40+
import kotlin.uuid.Uuid
4041

4142
/**
4243
* This class is responsible to generate system messages for new group conversations.
@@ -66,6 +67,12 @@ internal interface NewGroupConversationSystemMessagesCreator {
6667
): Either<CoreFailure, Unit>
6768

6869
suspend fun conversationCellStatus(conversation: ConversationEntity): Either<CoreFailure, Unit>
70+
suspend fun conversationAppsAccessIfEnabled(
71+
eventId: String = LocalId.generate(),
72+
conversationId: ConversationId,
73+
hasAppsAccessEnabled: Boolean,
74+
creatorId: UserId
75+
): Either<CoreFailure, Unit>
6976
}
7077

7178
internal class NewGroupConversationSystemMessagesCreatorImpl(
@@ -246,5 +253,29 @@ internal class NewGroupConversationSystemMessagesCreatorImpl(
246253
} ?: Either.Right(Unit)
247254
}
248255

256+
override suspend fun conversationAppsAccessIfEnabled(
257+
eventId: String,
258+
conversationId: ConversationId,
259+
hasAppsAccessEnabled: Boolean,
260+
creatorId: UserId
261+
): Either<CoreFailure, Unit> {
262+
return if (hasAppsAccessEnabled) {
263+
persistMessage(
264+
Message.System(
265+
eventId,
266+
MessageContent.ConversationAppsEnabledChanged(isEnabled = true),
267+
conversationId,
268+
Clock.System.now(),
269+
creatorId,
270+
Message.Status.Sent,
271+
Message.Visibility.VISIBLE,
272+
expirationData = null
273+
)
274+
)
275+
} else {
276+
Unit.right()
277+
}
278+
}
279+
249280
private suspend fun isSelfATeamMember() = selfTeamIdProvider().fold({ false }, { it != null })
250281
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ class MessageMapperImpl(
333333
MessageEntity.ContentType.LEGAL_HOLD -> null
334334
MessageEntity.ContentType.CONVERSATION_WITH_CELL -> null
335335
MessageEntity.ContentType.CONVERSATION_WITH_CELL_SELF_DELETE_DISABLED -> null
336+
MessageEntity.ContentType.CONVERSATION_APPS_ENABLED_CHANGED -> null
336337

337338
MessageEntity.ContentType.MULTIPART -> LocalNotificationMessage.Text(
338339
messageId = message.id,
@@ -498,9 +499,12 @@ fun MessageEntityContent.System.toMessageContent(): MessageContent.System = when
498499
MessageContent.LegalHold.ForMembers.Enabled(this.memberUserIdList.map { it.toModel() })
499500
}
500501
}
502+
501503
is MessageEntityContent.NewConversationWithCellMessage -> MessageContent.NewConversationWithCellMessage
502504
is MessageEntityContent.NewConversationWithCellSelfDeleteDisabledMessage ->
503505
MessageContent.NewConversationWithCellSelfDeleteDisabledMessage
506+
507+
is MessageEntityContent.ConversationAppsAccessChanged -> MessageContent.ConversationAppsEnabledChanged(isEnabled)
504508
}
505509

506510
fun Message.Visibility.toEntityVisibility(): MessageEntity.Visibility = when (this) {
@@ -812,6 +816,7 @@ fun MessageContent.System.toMessageEntityContent(): MessageEntityContent.System
812816

813817
MessageContent.NewConversationWithCellMessage -> MessageEntityContent.NewConversationWithCellMessage
814818
MessageContent.NewConversationWithCellSelfDeleteDisabledMessage -> MessageEntityContent.NewConversationWithCellSelfDeleteDisabledMessage
819+
is MessageContent.ConversationAppsEnabledChanged -> MessageEntityContent.ConversationAppsAccessChanged(isEnabled)
815820
}
816821

817822
fun MessageAssetStatus.toDao(): MessageAssetStatusEntity {

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919
package com.wire.kalium.logic.data.message
2020

2121
import com.wire.kalium.common.error.CoreFailure
22-
import com.wire.kalium.logic.data.conversation.Conversation
23-
import com.wire.kalium.logic.data.user.UserId
24-
import com.wire.kalium.logic.data.notification.NotificationEventsManager
2522
import com.wire.kalium.common.functional.Either
2623
import com.wire.kalium.common.functional.fold
2724
import com.wire.kalium.common.functional.map
2825
import com.wire.kalium.common.functional.onSuccess
26+
import com.wire.kalium.logic.data.conversation.Conversation
27+
import com.wire.kalium.logic.data.notification.NotificationEventsManager
28+
import com.wire.kalium.logic.data.user.UserId
2929
import com.wire.kalium.persistence.dao.message.InsertMessageResult
3030
import io.mockative.Mockable
3131

@@ -134,6 +134,7 @@ internal class PersistMessageUseCaseImpl(
134134
is MessageContent.History -> false
135135
is MessageContent.NewConversationWithCellMessage -> false
136136
is MessageContent.NewConversationWithCellSelfDeleteDisabledMessage -> false
137+
is MessageContent.ConversationAppsEnabledChanged -> false
137138
}
138139

139140
@Suppress("ComplexMethod")
@@ -194,6 +195,7 @@ internal class PersistMessageUseCaseImpl(
194195
is MessageContent.InCallEmoji,
195196
is MessageContent.History,
196197
is MessageContent.NewConversationWithCellMessage,
198+
is MessageContent.ConversationAppsEnabledChanged,
197199
is MessageContent.NewConversationWithCellSelfDeleteDisabledMessage -> false
198200
}
199201
}

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
package com.wire.kalium.logic.data.message
1919

2020
import com.wire.kalium.common.error.CoreFailure
21+
import com.wire.kalium.common.functional.Either
2122
import com.wire.kalium.logic.data.conversation.Conversation
2223
import com.wire.kalium.logic.data.id.ConversationId
2324
import com.wire.kalium.logic.data.user.UserId
24-
import com.wire.kalium.common.functional.Either
2525
import com.wire.kalium.persistence.dao.message.LocalId
2626
import io.mockative.Mockable
2727
import kotlinx.datetime.Clock
@@ -48,6 +48,13 @@ internal interface SystemMessageInserter {
4848
suspend fun insertLostCommitSystemMessage(conversationId: ConversationId, instant: Instant): Either<CoreFailure, Unit>
4949

5050
suspend fun insertConversationStartedUnverifiedWarning(conversationId: ConversationId)
51+
52+
suspend fun insertConversationAppsAccessChanged(
53+
eventId: String = LocalId.generate(),
54+
conversationId: ConversationId,
55+
senderUserId: UserId,
56+
isAppsAccessEnabled: Boolean
57+
)
5158
}
5259

5360
internal class SystemMessageInserterImpl(
@@ -137,4 +144,24 @@ internal class SystemMessageInserterImpl(
137144
)
138145
)
139146
}
147+
148+
override suspend fun insertConversationAppsAccessChanged(
149+
eventId: String,
150+
conversationId: ConversationId,
151+
senderUserId: UserId,
152+
isAppsAccessEnabled: Boolean
153+
) {
154+
persistMessage(
155+
Message.System(
156+
id = eventId,
157+
content = MessageContent.ConversationAppsEnabledChanged(isAppsAccessEnabled),
158+
conversationId = conversationId,
159+
date = Clock.System.now(),
160+
senderUserId = senderUserId,
161+
status = Message.Status.Sent,
162+
visibility = Message.Visibility.VISIBLE,
163+
expirationData = null
164+
)
165+
)
166+
}
140167
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1736,7 +1736,8 @@ class UserSessionScope internal constructor(
17361736
private val conversationAccessUpdateEventHandler: AccessUpdateEventHandler
17371737
get() = AccessUpdateEventHandler(
17381738
conversationDAO = userStorage.database.conversationDAO,
1739-
selfUserId = userId
1739+
selfUserId = userId,
1740+
systemMessageInserter = systemMessageInserter
17401741
)
17411742

17421743
private val mlsResetConversationEventHandler: MLSResetConversationEventHandler
@@ -2120,6 +2121,7 @@ class UserSessionScope internal constructor(
21202121
persistConversationsUseCase,
21212122
cryptoTransactionProvider,
21222123
resetMlsConversation,
2124+
systemMessageInserter
21232125
)
21242126
}
21252127

logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/ConversationScope.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import com.wire.kalium.logic.data.id.CurrentClientIdProvider
4141
import com.wire.kalium.logic.data.id.SelfTeamIdProvider
4242
import com.wire.kalium.logic.data.message.MessageRepository
4343
import com.wire.kalium.logic.data.message.PersistMessageUseCase
44+
import com.wire.kalium.logic.data.message.SystemMessageInserter
4445
import com.wire.kalium.logic.data.properties.UserPropertyRepository
4546
import com.wire.kalium.logic.data.sync.SlowSyncRepository
4647
import com.wire.kalium.logic.data.team.TeamRepository
@@ -52,6 +53,7 @@ import com.wire.kalium.logic.feature.connection.MarkConnectionRequestAsNotifiedU
5253
import com.wire.kalium.logic.feature.connection.ObserveConnectionListUseCase
5354
import com.wire.kalium.logic.feature.connection.ObservePendingConnectionRequestsUseCase
5455
import com.wire.kalium.logic.feature.connection.ObservePendingConnectionRequestsUseCaseImpl
56+
import com.wire.kalium.logic.feature.conversation.apps.ChangeAccessForAppsInConversationUseCase
5557
import com.wire.kalium.logic.feature.conversation.createconversation.CreateChannelUseCase
5658
import com.wire.kalium.logic.feature.conversation.createconversation.CreateRegularGroupUseCase
5759
import com.wire.kalium.logic.feature.conversation.createconversation.CreateRegularGroupUseCaseImpl
@@ -90,7 +92,6 @@ import com.wire.kalium.logic.feature.conversation.keyingmaterials.UpdateKeyingMa
9092
import com.wire.kalium.logic.feature.conversation.messagetimer.UpdateMessageTimerUseCase
9193
import com.wire.kalium.logic.feature.conversation.messagetimer.UpdateMessageTimerUseCaseImpl
9294
import com.wire.kalium.logic.feature.conversation.mls.OneOnOneResolver
93-
import com.wire.kalium.messaging.sending.MessageSender
9495
import com.wire.kalium.logic.feature.message.ephemeral.DeleteEphemeralMessagesAfterEndDateUseCase
9596
import com.wire.kalium.logic.feature.message.receipt.ConversationWorkQueue
9697
import com.wire.kalium.logic.feature.message.receipt.ParallelConversationWorkQueue
@@ -101,6 +102,7 @@ import com.wire.kalium.logic.feature.team.DeleteTeamConversationUseCaseImpl
101102
import com.wire.kalium.logic.sync.SyncManager
102103
import com.wire.kalium.logic.sync.receiver.conversation.RenamedConversationEventHandler
103104
import com.wire.kalium.logic.sync.receiver.handler.CodeUpdateHandlerImpl
105+
import com.wire.kalium.messaging.sending.MessageSender
104106
import com.wire.kalium.util.KaliumDispatcher
105107
import com.wire.kalium.util.KaliumDispatcherImpl
106108
import kotlinx.coroutines.CoroutineScope
@@ -140,6 +142,7 @@ class ConversationScope internal constructor(
140142
private val persistConversationsUseCase: PersistConversationsUseCase,
141143
private val transactionProvider: CryptoTransactionProvider,
142144
private val resetMLSConversationUseCase: ResetMLSConversationUseCase,
145+
private val systemMessageInserter: SystemMessageInserter,
143146
internal val dispatcher: KaliumDispatcher = KaliumDispatcherImpl,
144147
) {
145148

@@ -271,7 +274,10 @@ class ConversationScope internal constructor(
271274
)
272275

273276
val updateConversationAccess: UpdateConversationAccessRoleUseCase
274-
get() = UpdateConversationAccessRoleUseCase(conversationRepository, conversationGroupRepository, syncManager)
277+
get() = UpdateConversationAccessRoleUseCaseImpl(conversationRepository, conversationGroupRepository, syncManager)
278+
279+
val changeAccessForAppsInConversation: ChangeAccessForAppsInConversationUseCase
280+
get() = ChangeAccessForAppsInConversationUseCase(updateConversationAccess, systemMessageInserter, selfUserId)
275281

276282
val updateConversationMemberRole: UpdateConversationMemberRoleUseCase
277283
get() = UpdateConversationMemberRoleUseCaseImpl(conversationRepository)

logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/UpdateConversationAccessRoleUseCase.kt

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@
1919
package com.wire.kalium.logic.feature.conversation
2020

2121
import com.wire.kalium.common.error.CoreFailure
22+
import com.wire.kalium.common.functional.Either
23+
import com.wire.kalium.common.functional.flatMap
24+
import com.wire.kalium.common.functional.fold
2225
import com.wire.kalium.logic.data.conversation.Conversation
2326
import com.wire.kalium.logic.data.conversation.ConversationGroupRepository
2427
import com.wire.kalium.logic.data.conversation.ConversationRepository
2528
import com.wire.kalium.logic.data.id.ConversationId
26-
import com.wire.kalium.common.functional.Either
27-
import com.wire.kalium.common.functional.flatMap
28-
import com.wire.kalium.common.functional.fold
2929
import com.wire.kalium.logic.sync.SyncManager
30+
import io.mockative.Mockable
3031
import kotlinx.coroutines.flow.first
3132

3233
/**
@@ -47,17 +48,36 @@ import kotlinx.coroutines.flow.first
4748
*
4849
* @see Conversation.Access
4950
*/
51+
@Mockable
52+
interface UpdateConversationAccessRoleUseCase {
53+
/**
54+
* @param conversationId the id of the conversation
55+
* @param accessRoles the set of access roles to set
56+
* @param access the set of access to set
57+
* @return the [Result] indicating a successful operation, otherwise a [CoreFailure]
58+
*/
59+
suspend operator fun invoke(
60+
conversationId: ConversationId,
61+
accessRoles: Set<Conversation.AccessRole>,
62+
access: Set<Conversation.Access>,
63+
): Result
64+
65+
sealed interface Result {
66+
data object Success : Result
67+
data class Failure(val cause: CoreFailure) : Result
68+
}
69+
}
5070

51-
class UpdateConversationAccessRoleUseCase internal constructor(
71+
internal class UpdateConversationAccessRoleUseCaseImpl internal constructor(
5272
private val conversationRepository: ConversationRepository,
5373
private val conversationGroupRepository: ConversationGroupRepository,
5474
private val syncManager: SyncManager
55-
) {
56-
suspend operator fun invoke(
75+
) : UpdateConversationAccessRoleUseCase {
76+
override suspend operator fun invoke(
5777
conversationId: ConversationId,
5878
accessRoles: Set<Conversation.AccessRole>,
5979
access: Set<Conversation.Access>,
60-
): Result {
80+
): UpdateConversationAccessRoleUseCase.Result {
6181

6282
syncManager.waitUntilLiveOrFailure().flatMap {
6383
if (!accessRoles.contains(Conversation.AccessRole.GUEST)
@@ -72,14 +92,9 @@ class UpdateConversationAccessRoleUseCase internal constructor(
7292
return conversationRepository
7393
.updateAccessInfo(conversationId, access, accessRoles)
7494
.fold({
75-
Result.Failure(it)
95+
UpdateConversationAccessRoleUseCase.Result.Failure(it)
7696
}, {
77-
Result.Success
97+
UpdateConversationAccessRoleUseCase.Result.Success
7898
})
7999
}
80-
81-
sealed interface Result {
82-
data object Success : Result
83-
data class Failure(val cause: CoreFailure) : Result
84-
}
85100
}

0 commit comments

Comments
 (0)