From 709e72e66d9e3703db1d0c428e9cd68e295b86be Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Mon, 24 Jul 2023 09:01:54 +0000 Subject: [PATCH] feat: use case to send Message Button Action [part-2] (#1896) * receive composite messages * map composite to proto * detekt * detekt * db migration * db migration * sqm * map to composite entity * detekt * remove is pending state from the DB * Update logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageContent.kt Co-authored-by: Vitor Hugo Schwaab * Update logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageContent.kt Co-authored-by: Vitor Hugo Schwaab * address PR comments * detekt * remove composite message preview mapping * fix migration * feat: use case to execute composite message action * expose use case to message scope * missing param * rename use case * docs * map to proto * merge issues * address PR comments * address PR comments * detekt * sent the message only to the message original sender * detekt * Update logic/src/commonTest/kotlin/com/wire/kalium/logic/data/message/MessageMetaDataRepositoryTest.kt Co-authored-by: Alexandre Ferris * PR comments --------- Co-authored-by: Vitor Hugo Schwaab Co-authored-by: Alexandre Ferris --- .../wire/kalium/logic/data/id/QualifiedId.kt | 3 + .../message/CompositeMessageRepository.kt | 64 ++++++ .../logic/data/message/MessageContent.kt | 10 +- .../data/message/MessageMetaDataRepository.kt | 46 +++++ .../logic/data/message/ProtoContentMapper.kt | 13 +- .../kalium/logic/feature/UserSessionScope.kt | 6 + .../logic/feature/message/MessageScope.kt | 11 ++ .../logic/feature/message/MessageTarget.kt | 5 +- .../SendButtonActionMessageUseCase.kt | 85 ++++++++ .../connection/ConnectionRepositoryTest.kt | 4 +- .../ConversationGroupRepositoryTest.kt | 4 +- .../ConversationRepositoryTest.kt | 7 +- .../NewConversationMembersRepositoryTest.kt | 4 +- .../message/MessageMetaDataRepositoryTest.kt | 94 +++++++++ ...MessageForSelfUserAsReceiverUseCaseTest.kt | 12 +- .../publicuser/UserSearchApiWrapperTest.kt | 4 +- .../message/SendButtonActionMessageTest.kt | 184 ++++++++++++++++++ .../arrangement/MessageSenderArrangement.kt | 35 +++- .../arrangement/SyncManagerArrangement.kt | 45 +++++ .../dao/MemberDAOArrangement.kt | 2 +- .../dao/MessageMetaDataDAOArrangement.kt | 54 +++++ .../CurrentClientIdProviderArrangement.kt | 2 +- .../AssetRepositoryArrangement.kt | 2 +- .../MessageMetaDataRepositoryArrangement.kt | 58 ++++++ .../MessageRepositoryArrangement.kt | 2 +- .../kalium/persistence/MessageMetaData.sq | 3 + .../dao/message/MessageMetaDataDAO.kt | 38 ++++ .../persistence/db/UserDatabaseBuilder.kt | 5 + .../dao/message/MessageMetaDataDAOTest.kt | 91 +++++++++ 29 files changed, 861 insertions(+), 32 deletions(-) create mode 100644 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/CompositeMessageRepository.kt create mode 100644 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageMetaDataRepository.kt create mode 100644 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/composite/SendButtonActionMessageUseCase.kt create mode 100644 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/message/MessageMetaDataRepositoryTest.kt create mode 100644 logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/message/SendButtonActionMessageTest.kt create mode 100644 logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/SyncManagerArrangement.kt rename logic/src/commonTest/kotlin/com/wire/kalium/logic/util/{arrangment => arrangement}/dao/MemberDAOArrangement.kt (98%) create mode 100644 logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/dao/MessageMetaDataDAOArrangement.kt rename logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/{ => provider}/CurrentClientIdProviderArrangement.kt (97%) rename logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/{ => repository}/AssetRepositoryArrangement.kt (94%) create mode 100644 logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/repository/MessageMetaDataRepositoryArrangement.kt rename logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/{ => repository}/MessageRepositoryArrangement.kt (98%) create mode 100644 persistence/src/commonMain/db_user/com/wire/kalium/persistence/MessageMetaData.sq create mode 100644 persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageMetaDataDAO.kt create mode 100644 persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/message/MessageMetaDataDAOTest.kt diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/id/QualifiedId.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/id/QualifiedId.kt index 184d11fbdfa..16cb58555e0 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/id/QualifiedId.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/id/QualifiedId.kt @@ -60,3 +60,6 @@ data class QualifiedClientID( val clientId: ClientId, val userId: UserId ) + +typealias MessageId = String +typealias MessageButtonId = String diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/CompositeMessageRepository.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/CompositeMessageRepository.kt new file mode 100644 index 00000000000..e65b196b92b --- /dev/null +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/CompositeMessageRepository.kt @@ -0,0 +1,64 @@ +/* + * Wire + * Copyright (C) 2023 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.logic.data.message + +import com.wire.kalium.logic.StorageFailure +import com.wire.kalium.logic.data.id.ConversationId +import com.wire.kalium.logic.data.id.toDao +import com.wire.kalium.logic.functional.Either +import com.wire.kalium.logic.wrapStorageRequest +import com.wire.kalium.persistence.dao.message.CompositeMessageDAO + +interface CompositeMessageRepository { + suspend fun markSelected( + messageId: String, + conversationId: ConversationId, + buttonId: String + ): Either + + suspend fun resetSelection( + messageId: String, + conversationId: ConversationId + ): Either +} + +internal class CompositeMessageDatasource internal constructor( + private val compositeMessageDAO: CompositeMessageDAO +) : CompositeMessageRepository { + override suspend fun markSelected( + messageId: String, + conversationId: ConversationId, + buttonId: String + ): Either = wrapStorageRequest { + compositeMessageDAO.markAsSelected( + messageId = messageId, + conversationId = conversationId.toDao(), + buttonId = buttonId + ) + } + + override suspend fun resetSelection( + messageId: String, + conversationId: ConversationId + ): Either = wrapStorageRequest { + compositeMessageDAO.resetSelection( + messageId = messageId, + conversationId = conversationId.toDao() + ) + } +} diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageContent.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageContent.kt index 2ef46962b48..ae806056fb2 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageContent.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageContent.kt @@ -21,6 +21,8 @@ package com.wire.kalium.logic.data.message import com.wire.kalium.logger.obfuscateId import com.wire.kalium.logic.data.conversation.ClientId import com.wire.kalium.logic.data.id.ConversationId +import com.wire.kalium.logic.data.id.MessageButtonId +import com.wire.kalium.logic.data.id.MessageId import com.wire.kalium.logic.data.message.mention.MessageMention import com.wire.kalium.logic.data.message.receipt.ReceiptType import com.wire.kalium.logic.data.user.UserAvailabilityStatus @@ -185,12 +187,12 @@ sealed class MessageContent { /** * The ID of the original composite message. */ - val referencedMessageId: String, + val referencedMessageId: MessageId, /** * ID of the button that was selected. */ - val buttonId: String + val buttonId: MessageButtonId ) : Signaling() /** @@ -205,11 +207,11 @@ sealed class MessageContent { /** * ID fo the original composite message */ - val referencedMessageId: String, + val referencedMessageId: MessageId, /** * ID of the selected button. Null if no button should be marked as selected. */ - val buttonId: String?, + val buttonId: MessageButtonId?, ) : Signaling() data class Unknown( // messages that aren't yet handled properly but stored in db in case diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageMetaDataRepository.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageMetaDataRepository.kt new file mode 100644 index 00000000000..9e9f0963159 --- /dev/null +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageMetaDataRepository.kt @@ -0,0 +1,46 @@ +/* + * Wire + * Copyright (C) 2023 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.logic.data.message + +import com.wire.kalium.logic.StorageFailure +import com.wire.kalium.logic.data.id.ConversationId +import com.wire.kalium.logic.data.id.MessageId +import com.wire.kalium.logic.data.id.toDao +import com.wire.kalium.logic.data.id.toModel +import com.wire.kalium.logic.data.user.UserId +import com.wire.kalium.logic.functional.Either +import com.wire.kalium.logic.functional.map +import com.wire.kalium.logic.wrapStorageRequest +import com.wire.kalium.persistence.dao.UserIDEntity +import com.wire.kalium.persistence.dao.message.MessageMetaDataDAO + +interface MessageMetaDataRepository { + suspend fun originalSenderId( + conversationId: ConversationId, + messageId: MessageId + ): Either +} + +internal class MessageMetaDataDataSource internal constructor( + private val messageMetaDataDAO: MessageMetaDataDAO +) : MessageMetaDataRepository { + override suspend fun originalSenderId(conversationId: ConversationId, messageId: MessageId): Either = + wrapStorageRequest { + messageMetaDataDAO.originalSenderId(conversationId.toDao(), messageId) + }.map(UserIDEntity::toModel) +} diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/ProtoContentMapper.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/ProtoContentMapper.kt index 1270a468a79..42aae27ebbb 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/ProtoContentMapper.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/ProtoContentMapper.kt @@ -32,6 +32,7 @@ import com.wire.kalium.protobuf.decodeFromByteArray import com.wire.kalium.protobuf.encodeToByteArray import com.wire.kalium.protobuf.messages.Asset import com.wire.kalium.protobuf.messages.Button +import com.wire.kalium.protobuf.messages.ButtonAction import com.wire.kalium.protobuf.messages.Calling import com.wire.kalium.protobuf.messages.Cleared import com.wire.kalium.protobuf.messages.ClientAction @@ -123,12 +124,22 @@ class ProtoContentMapperImpl( ) is MessageContent.Composite -> packComposite(readableContent, expectsReadConfirmation) + is MessageContent.ButtonAction -> packButtonAction(readableContent) is MessageContent.ButtonActionConfirmation -> TODO() - is MessageContent.ButtonAction -> TODO() } } + private fun packButtonAction( + readableContent: MessageContent.ButtonAction + ): GenericMessage.Content.ButtonAction = + GenericMessage.Content.ButtonAction( + ButtonAction( + buttonId = readableContent.buttonId, + referenceMessageId = readableContent.referencedMessageId + ) + ) + private fun packComposite( readableContent: MessageContent.Composite, expectsReadConfirmation: Boolean diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt index edbf5369d87..1a31e3c204a 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt @@ -83,6 +83,8 @@ import com.wire.kalium.logic.data.logout.LogoutRepository import com.wire.kalium.logic.data.message.IsMessageSentInSelfConversationUseCase import com.wire.kalium.logic.data.message.IsMessageSentInSelfConversationUseCaseImpl import com.wire.kalium.logic.data.message.MessageDataSource +import com.wire.kalium.logic.data.message.MessageMetaDataDataSource +import com.wire.kalium.logic.data.message.MessageMetaDataRepository import com.wire.kalium.logic.data.message.MessageRepository import com.wire.kalium.logic.data.message.PersistMessageUseCase import com.wire.kalium.logic.data.message.PersistMessageUseCaseImpl @@ -555,6 +557,9 @@ class UserSessionScope internal constructor( selfUserId = userId ) + private val messageMetaDataRepository: MessageMetaDataRepository + get() = MessageMetaDataDataSource(messageMetaDataDAO = userStorage.database.messageMetaDataDAO) + private val userRepository: UserRepository = UserDataSource( userStorage.database.userDAO, userStorage.database.metadataDAO, @@ -1226,6 +1231,7 @@ class UserSessionScope internal constructor( incrementalSyncRepository, protoContentMapper, observeSelfDeletingMessages, + messageMetaDataRepository, this ) val users: UserScope diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/MessageScope.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/MessageScope.kt index 6accf19b805..1459d06cb5a 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/MessageScope.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/MessageScope.kt @@ -26,6 +26,7 @@ import com.wire.kalium.logic.data.connection.ConnectionRepository import com.wire.kalium.logic.data.conversation.ConversationRepository import com.wire.kalium.logic.data.conversation.MLSConversationRepository import com.wire.kalium.logic.data.id.QualifiedID +import com.wire.kalium.logic.data.message.MessageMetaDataRepository import com.wire.kalium.logic.data.message.MessageRepository import com.wire.kalium.logic.data.message.PersistMessageUseCase import com.wire.kalium.logic.data.message.PersistMessageUseCaseImpl @@ -47,6 +48,7 @@ import com.wire.kalium.logic.feature.asset.UpdateAssetMessageDownloadStatusUseCa import com.wire.kalium.logic.feature.asset.UpdateAssetMessageDownloadStatusUseCaseImpl import com.wire.kalium.logic.feature.asset.UpdateAssetMessageUploadStatusUseCase import com.wire.kalium.logic.feature.asset.UpdateAssetMessageUploadStatusUseCaseImpl +import com.wire.kalium.logic.feature.message.composite.SendButtonActionMessageUseCase import com.wire.kalium.logic.feature.message.ephemeral.DeleteEphemeralMessageForSelfUserAsReceiverUseCaseImpl import com.wire.kalium.logic.feature.message.ephemeral.DeleteEphemeralMessageForSelfUserAsSenderUseCaseImpl import com.wire.kalium.logic.feature.message.ephemeral.EnqueueMessageSelfDeletionUseCase @@ -86,6 +88,7 @@ class MessageScope internal constructor( private val incrementalSyncRepository: IncrementalSyncRepository, private val protoContentMapper: ProtoContentMapper, private val observeSelfDeletingMessages: ObserveSelfDeletionTimerSettingsForConversationUseCase, + private val messageMetaDataRepository: MessageMetaDataRepository, private val scope: CoroutineScope, internal val dispatcher: KaliumDispatcher = KaliumDispatcherImpl ) { @@ -298,6 +301,14 @@ class MessageScope internal constructor( val resetSession: ResetSessionUseCase get() = ResetSessionUseCaseImpl(proteusClientProvider, sessionResetSender, messageRepository) + val sendButtonActionMessage: SendButtonActionMessageUseCase + get() = SendButtonActionMessageUseCase( + syncManager = syncManager, + messageSender = messageSender, + selfUserId = selfUserId, + currentClientIdProvider = currentClientIdProvider, + messageMetaDataRepository = messageMetaDataRepository + ) private val deleteEphemeralMessageForSelfUserAsReceiver: DeleteEphemeralMessageForSelfUserAsReceiverUseCaseImpl get() = DeleteEphemeralMessageForSelfUserAsReceiverUseCaseImpl( messageRepository = messageRepository, diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/MessageTarget.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/MessageTarget.kt index a143c3ac1fd..936cef1ebc3 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/MessageTarget.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/MessageTarget.kt @@ -22,7 +22,10 @@ import com.wire.kalium.logic.data.conversation.Recipient import com.wire.kalium.logic.data.user.UserId sealed interface MessageTarget { - data class Users(val userId: List) : MessageTarget + data class Users(val userId: List) : MessageTarget { + constructor(vararg userId: UserId) : this(userId.toList()) + } + class Client(val recipients: List) : MessageTarget data class Conversation(val usersToIgnore: Set = emptySet()) : MessageTarget } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/composite/SendButtonActionMessageUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/composite/SendButtonActionMessageUseCase.kt new file mode 100644 index 00000000000..945bb73cdbd --- /dev/null +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/composite/SendButtonActionMessageUseCase.kt @@ -0,0 +1,85 @@ +/* + * Wire + * Copyright (C) 2023 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.logic.feature.message.composite + +import com.benasher44.uuid.uuid4 +import com.wire.kalium.logic.CoreFailure +import com.wire.kalium.logic.data.id.ConversationId +import com.wire.kalium.logic.data.message.Message +import com.wire.kalium.logic.data.message.MessageContent +import com.wire.kalium.logic.data.message.MessageMetaDataRepository +import com.wire.kalium.logic.data.user.UserId +import com.wire.kalium.logic.feature.CurrentClientIdProvider +import com.wire.kalium.logic.feature.message.MessageSender +import com.wire.kalium.logic.feature.message.MessageTarget +import com.wire.kalium.logic.functional.flatMap +import com.wire.kalium.logic.functional.fold +import com.wire.kalium.logic.sync.SyncManager +import com.wire.kalium.util.DateTimeUtil + +/** + * Use case for sending a button action message. + * @param conversationId The conversation id. + * @param messageId The id of the message that contains the button. + * @param buttonId The id of the button. + * + * the action message is sent only to the message original sender. + */ +class SendButtonActionMessageUseCase internal constructor( + private val messageSender: MessageSender, + private val messageMetaDataRepository: MessageMetaDataRepository, + private val syncManager: SyncManager, + private val currentClientIdProvider: CurrentClientIdProvider, + private val selfUserId: UserId +) { + suspend operator fun invoke( + conversationId: ConversationId, + messageId: String, + buttonId: String + ): Result = syncManager.waitUntilLiveOrFailure().flatMap { + messageMetaDataRepository.originalSenderId( + conversationId, + messageId + ).flatMap { originalSenderId -> + currentClientIdProvider().flatMap { currentClientId -> + val regularMessage = Message.Signaling( + id = uuid4().toString(), + content = MessageContent.ButtonAction( + referencedMessageId = messageId, + buttonId = buttonId + ), + conversationId = conversationId, + date = DateTimeUtil.currentIsoDateTimeString(), + senderUserId = selfUserId, + senderClientId = currentClientId, + status = Message.Status.PENDING, + isSelfMessage = true, + expirationData = null + ) + messageSender.sendMessage(regularMessage, messageTarget = MessageTarget.Users(originalSenderId)) + } + } + }.fold(Result::Failure, { Result.Success }) + + sealed interface Result { + object Success : Result + data class Failure( + val error: CoreFailure + ) : Result + } +} diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/connection/ConnectionRepositoryTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/connection/ConnectionRepositoryTest.kt index 947aaec5d8c..06408330b41 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/connection/ConnectionRepositoryTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/connection/ConnectionRepositoryTest.kt @@ -27,8 +27,8 @@ import com.wire.kalium.logic.feature.SelfTeamIdProvider import com.wire.kalium.logic.framework.TestConversation import com.wire.kalium.logic.framework.TestUser import com.wire.kalium.logic.functional.Either -import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangement -import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangementImpl +import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangement +import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangementImpl import com.wire.kalium.logic.util.shouldFail import com.wire.kalium.logic.util.shouldSucceed import com.wire.kalium.network.api.base.authenticated.connection.ConnectionApi diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/ConversationGroupRepositoryTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/ConversationGroupRepositoryTest.kt index a241af1cf87..ae0d3112379 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/ConversationGroupRepositoryTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/ConversationGroupRepositoryTest.kt @@ -35,8 +35,8 @@ import com.wire.kalium.logic.framework.TestUser import com.wire.kalium.logic.functional.Either import com.wire.kalium.logic.sync.receiver.conversation.MemberJoinEventHandler import com.wire.kalium.logic.sync.receiver.conversation.MemberLeaveEventHandler -import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangement -import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangementImpl +import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangement +import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangementImpl import com.wire.kalium.logic.util.shouldFail import com.wire.kalium.logic.util.shouldSucceed import com.wire.kalium.network.api.base.authenticated.conversation.AddServiceRequest diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepositoryTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepositoryTest.kt index 794315957d5..392621d0415 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepositoryTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepositoryTest.kt @@ -43,8 +43,8 @@ import com.wire.kalium.logic.framework.TestTeam import com.wire.kalium.logic.framework.TestUser import com.wire.kalium.logic.functional.Either import com.wire.kalium.logic.sync.receiver.conversation.RenamedConversationEventHandler -import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangement -import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangementImpl +import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangement +import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangementImpl import com.wire.kalium.logic.util.shouldSucceed import com.wire.kalium.network.api.base.authenticated.client.ClientApi import com.wire.kalium.network.api.base.authenticated.conversation.ConvProtocol @@ -74,7 +74,6 @@ import com.wire.kalium.persistence.dao.UserIDEntity import com.wire.kalium.persistence.dao.client.ClientDAO import com.wire.kalium.persistence.dao.client.ClientTypeEntity import com.wire.kalium.persistence.dao.client.DeviceTypeEntity -import com.wire.kalium.persistence.dao.client.Client as ClientEntity import com.wire.kalium.persistence.dao.conversation.ConversationDAO import com.wire.kalium.persistence.dao.conversation.ConversationEntity import com.wire.kalium.persistence.dao.conversation.ConversationViewEntity @@ -96,7 +95,6 @@ import io.mockative.mock import io.mockative.once import io.mockative.thenDoNothing import io.mockative.verify -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest @@ -110,6 +108,7 @@ import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue import com.wire.kalium.network.api.base.model.ConversationId as ConversationIdDTO +import com.wire.kalium.persistence.dao.client.Client as ClientEntity @Suppress("LargeClass") class ConversationRepositoryTest { diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/NewConversationMembersRepositoryTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/NewConversationMembersRepositoryTest.kt index 20ac37fcc25..2b1cc4daca0 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/NewConversationMembersRepositoryTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/NewConversationMembersRepositoryTest.kt @@ -21,8 +21,8 @@ import com.wire.kalium.logic.data.id.toApi import com.wire.kalium.logic.framework.TestConversation import com.wire.kalium.logic.framework.TestUser import com.wire.kalium.logic.functional.Either -import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangement -import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangementImpl +import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangement +import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangementImpl import com.wire.kalium.logic.util.shouldSucceed import com.wire.kalium.network.api.base.authenticated.conversation.ConvProtocol import com.wire.kalium.network.api.base.authenticated.conversation.ConversationMemberDTO diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/message/MessageMetaDataRepositoryTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/message/MessageMetaDataRepositoryTest.kt new file mode 100644 index 00000000000..c86322ca619 --- /dev/null +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/message/MessageMetaDataRepositoryTest.kt @@ -0,0 +1,94 @@ +/* + * Wire + * Copyright (C) 2023 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.logic.data.message + +import com.wire.kalium.logic.StorageFailure +import com.wire.kalium.logic.data.id.ConversationId +import com.wire.kalium.logic.util.arrangement.dao.MessageMetaDataDAOArrangement +import com.wire.kalium.logic.util.arrangement.dao.MessageMetaDataDAOArrangementImpl +import com.wire.kalium.logic.util.shouldFail +import com.wire.kalium.logic.util.shouldSucceed +import com.wire.kalium.persistence.dao.ConversationIDEntity +import com.wire.kalium.persistence.dao.UserIDEntity +import io.mockative.eq +import io.mockative.once +import io.mockative.verify +import kotlinx.coroutines.test.runTest +import kotlin.test.Test +import kotlin.test.assertEquals + +class MessageMetaDataRepositoryTest { + + @Test + fun givenMessageOriginalSender_whenGetOriginalSender_thenReturnsOriginalSender() = runTest { + val convId = ConversationId("conversation_id", "domain") + + val (arrangement, repo) = Arrangement().arrange { + withMessageOriginalSender( + result = UserIDEntity("original_sender_id", "domain") + ) + } + + repo.originalSenderId( + conversationId = convId, + messageId = "message_id" + ).shouldSucceed { + assertEquals("original_sender_id", it.value) + assertEquals("domain", it.domain) + } + + verify(arrangement.messageMetaDataDAO) + .suspendFunction(arrangement.messageMetaDataDAO::originalSenderId) + .with(eq(ConversationIDEntity("conversation_id", "domain")), eq("message_id")) + .wasInvoked(exactly = once) + } + + @Test + fun givenMessageNotExists_whenGetOriginalSender_thenDataNotFound() = runTest { + val convId = ConversationId("conversation_id", "domain") + + val (arrangement, repo) = Arrangement().arrange { + withMessageOriginalSender( + result = null + ) + } + + repo.originalSenderId( + conversationId = convId, + messageId = "message_id" + ).shouldFail { + assertEquals(StorageFailure.DataNotFound, it) + } + + verify(arrangement.messageMetaDataDAO) + .suspendFunction(arrangement.messageMetaDataDAO::originalSenderId) + .with(eq(ConversationIDEntity("conversation_id", "domain")), eq("message_id")) + .wasInvoked(exactly = once) + } + + + + private class Arrangement : MessageMetaDataDAOArrangement by MessageMetaDataDAOArrangementImpl() { + private val repo: MessageMetaDataRepository = MessageMetaDataDataSource(messageMetaDataDAO) + + fun arrange(block: Arrangement.() -> Unit): Pair { + block() + return this to repo + } + } +} diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/message/ephemeral/DeleteEphemeralMessageForSelfUserAsReceiverUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/message/ephemeral/DeleteEphemeralMessageForSelfUserAsReceiverUseCaseTest.kt index 3dfe09d5a34..94fc8e81c9b 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/message/ephemeral/DeleteEphemeralMessageForSelfUserAsReceiverUseCaseTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/message/ephemeral/DeleteEphemeralMessageForSelfUserAsReceiverUseCaseTest.kt @@ -26,16 +26,16 @@ import com.wire.kalium.logic.feature.message.MessageTarget import com.wire.kalium.logic.feature.message.ephemeral.DeleteEphemeralMessageForSelfUserAsReceiverUseCase import com.wire.kalium.logic.feature.message.ephemeral.DeleteEphemeralMessageForSelfUserAsReceiverUseCaseImpl import com.wire.kalium.logic.functional.Either -import com.wire.kalium.logic.util.arrangement.AssetRepositoryArrangement -import com.wire.kalium.logic.util.arrangement.AssetRepositoryArrangementImpl -import com.wire.kalium.logic.util.arrangement.CurrentClientIdProviderArrangement -import com.wire.kalium.logic.util.arrangement.CurrentClientIdProviderArrangementImpl -import com.wire.kalium.logic.util.arrangement.MessageRepositoryArrangement -import com.wire.kalium.logic.util.arrangement.MessageRepositoryArrangementImpl import com.wire.kalium.logic.util.arrangement.MessageSenderArrangement import com.wire.kalium.logic.util.arrangement.MessageSenderArrangementImpl import com.wire.kalium.logic.util.arrangement.SelfConversationIdProviderArrangement import com.wire.kalium.logic.util.arrangement.SelfConversationIdProviderArrangementImpl +import com.wire.kalium.logic.util.arrangement.provider.CurrentClientIdProviderArrangement +import com.wire.kalium.logic.util.arrangement.provider.CurrentClientIdProviderArrangementImpl +import com.wire.kalium.logic.util.arrangement.repository.AssetRepositoryArrangement +import com.wire.kalium.logic.util.arrangement.repository.AssetRepositoryArrangementImpl +import com.wire.kalium.logic.util.arrangement.repository.MessageRepositoryArrangement +import com.wire.kalium.logic.util.arrangement.repository.MessageRepositoryArrangementImpl import com.wire.kalium.logic.util.shouldSucceed import com.wire.kalium.util.DateTimeUtil.toIsoDateTimeString import io.mockative.any diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/publicuser/UserSearchApiWrapperTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/publicuser/UserSearchApiWrapperTest.kt index 20d1ce31903..5f4f9d52516 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/publicuser/UserSearchApiWrapperTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/publicuser/UserSearchApiWrapperTest.kt @@ -25,8 +25,8 @@ import com.wire.kalium.logic.data.user.SelfUser import com.wire.kalium.logic.data.user.UserAvailabilityStatus import com.wire.kalium.logic.data.user.UserMapper import com.wire.kalium.logic.functional.Either -import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangement -import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangementImpl +import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangement +import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangementImpl import com.wire.kalium.network.api.base.authenticated.search.ContactDTO import com.wire.kalium.network.api.base.authenticated.search.SearchPolicyDTO import com.wire.kalium.network.api.base.authenticated.search.UserSearchApi diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/message/SendButtonActionMessageTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/message/SendButtonActionMessageTest.kt new file mode 100644 index 00000000000..4e6f6060283 --- /dev/null +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/message/SendButtonActionMessageTest.kt @@ -0,0 +1,184 @@ +/* + * Wire + * Copyright (C) 2023 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.logic.feature.message + +import com.wire.kalium.logic.StorageFailure +import com.wire.kalium.logic.data.conversation.ClientId +import com.wire.kalium.logic.data.id.ConversationId +import com.wire.kalium.logic.data.user.UserId +import com.wire.kalium.logic.feature.message.composite.SendButtonActionMessageUseCase +import com.wire.kalium.logic.functional.Either +import com.wire.kalium.logic.util.arrangement.MessageSenderArrangement +import com.wire.kalium.logic.util.arrangement.MessageSenderArrangementImpl +import com.wire.kalium.logic.util.arrangement.SyncManagerArrangement +import com.wire.kalium.logic.util.arrangement.SyncManagerArrangementImpl +import com.wire.kalium.logic.util.arrangement.provider.CurrentClientIdProviderArrangement +import com.wire.kalium.logic.util.arrangement.provider.CurrentClientIdProviderArrangementImpl +import com.wire.kalium.logic.util.arrangement.repository.MessageMetaDataRepositoryArrangement +import com.wire.kalium.logic.util.arrangement.repository.MessageMetaDataRepositoryArrangementImpl +import io.mockative.any +import io.mockative.matching +import io.mockative.once +import io.mockative.verify +import kotlinx.coroutines.test.runTest +import kotlin.test.Test +import kotlin.test.assertIs + +class SendButtonActionMessageTest { + + @Test + fun givenSyncFailed_thenReturnError() = runTest { + val convId = ConversationId("conversation-id", "conversation-domain") + val (arrangement, useCase) = Arrangement() + .arrange { + withWaitUntilLiveOrFailure(Either.Left(StorageFailure.DataNotFound)) + } + + val result = useCase( + conversationId = convId, + messageId = "message-id", + buttonId = "button-id", + ) + + assertIs(result) + + verify(arrangement.messageMetaDataRepository) + .suspendFunction(arrangement.messageMetaDataRepository::originalSenderId) + .with(any(), any()) + .wasNotInvoked() + + verify(arrangement.messageSender) + .suspendFunction(arrangement.messageSender::sendMessage) + .with(any(), any()) + .wasNotInvoked() + + verify(arrangement.currentClientIdProvider) + .suspendFunction(arrangement.currentClientIdProvider::invoke) + .wasNotInvoked() + + verify(arrangement.syncManager) + .suspendFunction(arrangement.syncManager::waitUntilLiveOrFailure) + .wasInvoked(exactly = once) + } + + @Test + fun givenMessageSendingSuccess_thenReturnSuccess() = runTest { + val convId = ConversationId("conversation-id", "conversation-domain") + val originalSender = UserId("original-sender-id", "original-sender-domain") + val (arrangement, useCase) = Arrangement() + .arrange { + withWaitUntilLiveOrFailure(Either.Right(Unit)) + withCurrentClientIdSuccess(ClientId("client-id")) + withMessageOriginalSender(Either.Right(originalSender)) + withSendMessageSucceed() + } + + val result = useCase( + conversationId = convId, + messageId = "message-id", + buttonId = "button-id", + ) + + assertIs(result) + + verify(arrangement.messageMetaDataRepository) + .suspendFunction(arrangement.messageMetaDataRepository::originalSenderId) + .with(any(), any()) + .wasInvoked(exactly = once) + + verify(arrangement.messageSender) + .suspendFunction(arrangement.messageSender::sendMessage) + .with(any(), any()) + .wasInvoked(exactly = once) + + verify(arrangement.currentClientIdProvider) + .suspendFunction(arrangement.currentClientIdProvider::invoke) + .wasInvoked(exactly = once) + + verify(arrangement.syncManager) + .suspendFunction(arrangement.syncManager::waitUntilLiveOrFailure) + .wasInvoked(exactly = once) + } + + @Test + fun givenMessageSendingSuccess_thenMessageIsSentOnlyToOriginalSender() = runTest { + val convId = ConversationId("conversation-id", "conversation-domain") + val originalSender = UserId("original-sender-id", "original-sender-domain") + val (arrangement, useCase) = Arrangement() + .arrange { + withWaitUntilLiveOrFailure(Either.Right(Unit)) + withCurrentClientIdSuccess(ClientId("client-id")) + withMessageOriginalSender(Either.Right(originalSender)) + withSendMessageSucceed() + } + + val result = useCase( + conversationId = convId, + messageId = "message-id", + buttonId = "button-id", + ) + + assertIs(result) + + verify(arrangement.messageMetaDataRepository) + .suspendFunction(arrangement.messageMetaDataRepository::originalSenderId) + .with(any(), any()) + .wasInvoked(exactly = once) + + verify(arrangement.messageSender) + .suspendFunction(arrangement.messageSender::sendMessage) + .with(any(), matching { + it is MessageTarget.Users && it.userId == listOf(originalSender) + }) + .wasInvoked(exactly = once) + + verify(arrangement.currentClientIdProvider) + .suspendFunction(arrangement.currentClientIdProvider::invoke) + .wasInvoked(exactly = once) + + verify(arrangement.syncManager) + .suspendFunction(arrangement.syncManager::waitUntilLiveOrFailure) + .wasInvoked(exactly = once) + } + + private companion object { + val SELF_USER_ID: UserId = UserId("self-user-id", "self-user-domain") + } + + private class Arrangement : + MessageMetaDataRepositoryArrangement by MessageMetaDataRepositoryArrangementImpl(), + MessageSenderArrangement by MessageSenderArrangementImpl(), + SyncManagerArrangement by SyncManagerArrangementImpl(), + CurrentClientIdProviderArrangement by CurrentClientIdProviderArrangementImpl() { + + private lateinit var useCase: SendButtonActionMessageUseCase + + fun arrange(block: Arrangement.() -> Unit): Pair { + apply(block) + useCase = SendButtonActionMessageUseCase( + messageMetaDataRepository = messageMetaDataRepository, + messageSender = messageSender, + syncManager = syncManager, + currentClientIdProvider = currentClientIdProvider, + selfUserId = SELF_USER_ID, + ) + + return this to useCase + } + } +} diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/MessageSenderArrangement.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/MessageSenderArrangement.kt index 8c242a6cbd3..f5da5cd2563 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/MessageSenderArrangement.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/MessageSenderArrangement.kt @@ -17,29 +17,56 @@ */ package com.wire.kalium.logic.util.arrangement +import com.wire.kalium.logic.CoreFailure +import com.wire.kalium.logic.data.message.Message import com.wire.kalium.logic.feature.message.MessageSender +import com.wire.kalium.logic.feature.message.MessageTarget import com.wire.kalium.logic.functional.Either import io.mockative.Mock -import io.mockative.anything +import io.mockative.any import io.mockative.given +import io.mockative.matchers.Matcher import io.mockative.mock internal interface MessageSenderArrangement { @Mock val messageSender: MessageSender - fun withSendMessageSucceed() + fun withSendMessageSucceed( + message: Matcher = any(), + target: Matcher = any() + ) + + fun withMessageSenderFailure( + result: Either.Left, + message: Matcher = any(), + target: Matcher = any() + ) } internal open class MessageSenderArrangementImpl : MessageSenderArrangement { @Mock override val messageSender: MessageSender = mock(MessageSender::class) - override fun withSendMessageSucceed() { + override fun withSendMessageSucceed( + message: Matcher, + target: Matcher + ) { given(messageSender) .suspendFunction(messageSender::sendMessage) - .whenInvokedWith(anything(), anything()) + .whenInvokedWith(message, target) .thenReturn(Either.Right(Unit)) } + override fun withMessageSenderFailure( + result: Either.Left, + message: Matcher, + target: Matcher + ) { + given(messageSender) + .suspendFunction(messageSender::sendMessage) + .whenInvokedWith(message, target) + .thenReturn(result) + } + } diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/SyncManagerArrangement.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/SyncManagerArrangement.kt new file mode 100644 index 00000000000..e2f0e3bab6b --- /dev/null +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/SyncManagerArrangement.kt @@ -0,0 +1,45 @@ +/* + * Wire + * Copyright (C) 2023 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.logic.util.arrangement + +import com.wire.kalium.logic.CoreFailure +import com.wire.kalium.logic.functional.Either +import com.wire.kalium.logic.sync.SyncManager +import io.mockative.Mock +import io.mockative.given +import io.mockative.mock + +interface SyncManagerArrangement { + @Mock + val syncManager: SyncManager + + fun withWaitUntilLiveOrFailure(result: Either) +} + +class SyncManagerArrangementImpl : SyncManagerArrangement { + @Mock + override val syncManager: SyncManager = mock(SyncManager::class) + override fun withWaitUntilLiveOrFailure(result: Either) { + given(syncManager) + .suspendFunction(syncManager::waitUntilLiveOrFailure) + .whenInvoked() + .thenReturn(result) + } + + +} diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangment/dao/MemberDAOArrangement.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/dao/MemberDAOArrangement.kt similarity index 98% rename from logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangment/dao/MemberDAOArrangement.kt rename to logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/dao/MemberDAOArrangement.kt index cc30ee1b4c0..6215eefd7f8 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangment/dao/MemberDAOArrangement.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/dao/MemberDAOArrangement.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ -package com.wire.kalium.logic.util.arrangment.dao +package com.wire.kalium.logic.util.arrangement.dao import com.wire.kalium.persistence.dao.ConnectionEntity import com.wire.kalium.persistence.dao.QualifiedIDEntity diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/dao/MessageMetaDataDAOArrangement.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/dao/MessageMetaDataDAOArrangement.kt new file mode 100644 index 00000000000..adc0893aace --- /dev/null +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/dao/MessageMetaDataDAOArrangement.kt @@ -0,0 +1,54 @@ +/* + * Wire + * Copyright (C) 2023 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.logic.util.arrangement.dao + +import com.wire.kalium.persistence.dao.ConversationIDEntity +import com.wire.kalium.persistence.dao.UserIDEntity +import com.wire.kalium.persistence.dao.message.MessageMetaDataDAO +import io.mockative.Mock +import io.mockative.any +import io.mockative.given +import io.mockative.matchers.Matcher +import io.mockative.mock + +interface MessageMetaDataDAOArrangement { + @Mock + val messageMetaDataDAO: MessageMetaDataDAO + + fun withMessageOriginalSender( + result: UserIDEntity?, + conversationId: Matcher = any(), + messageId: Matcher = any() + ) +} + +class MessageMetaDataDAOArrangementImpl : MessageMetaDataDAOArrangement { + @Mock + override val messageMetaDataDAO: MessageMetaDataDAO = mock(MessageMetaDataDAO::class) + + override fun withMessageOriginalSender( + result: UserIDEntity?, + conversationId: Matcher, + messageId: Matcher + ) { + given(messageMetaDataDAO) + .suspendFunction(messageMetaDataDAO::originalSenderId) + .whenInvokedWith(conversationId, messageId) + .thenReturn(result) + } +} diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/CurrentClientIdProviderArrangement.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/provider/CurrentClientIdProviderArrangement.kt similarity index 97% rename from logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/CurrentClientIdProviderArrangement.kt rename to logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/provider/CurrentClientIdProviderArrangement.kt index 858f0d29e5e..8b65be951c0 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/CurrentClientIdProviderArrangement.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/provider/CurrentClientIdProviderArrangement.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ -package com.wire.kalium.logic.util.arrangement +package com.wire.kalium.logic.util.arrangement.provider import com.wire.kalium.logic.CoreFailure import com.wire.kalium.logic.StorageFailure diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/AssetRepositoryArrangement.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/repository/AssetRepositoryArrangement.kt similarity index 94% rename from logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/AssetRepositoryArrangement.kt rename to logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/repository/AssetRepositoryArrangement.kt index 891e777ff13..bf5dcb81ad5 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/AssetRepositoryArrangement.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/repository/AssetRepositoryArrangement.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ -package com.wire.kalium.logic.util.arrangement +package com.wire.kalium.logic.util.arrangement.repository import com.wire.kalium.logic.data.asset.AssetRepository import io.mockative.Mock diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/repository/MessageMetaDataRepositoryArrangement.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/repository/MessageMetaDataRepositoryArrangement.kt new file mode 100644 index 00000000000..4ba5f369703 --- /dev/null +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/repository/MessageMetaDataRepositoryArrangement.kt @@ -0,0 +1,58 @@ +/* + * Wire + * Copyright (C) 2023 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.logic.util.arrangement.repository + +import com.wire.kalium.logic.StorageFailure +import com.wire.kalium.logic.data.id.ConversationId +import com.wire.kalium.logic.data.id.MessageId +import com.wire.kalium.logic.data.message.MessageMetaDataRepository +import com.wire.kalium.logic.data.user.UserId +import com.wire.kalium.logic.functional.Either +import io.mockative.Mock +import io.mockative.any +import io.mockative.given +import io.mockative.matchers.Matcher +import io.mockative.mock + +interface MessageMetaDataRepositoryArrangement { + @Mock + val messageMetaDataRepository: MessageMetaDataRepository + + fun withMessageOriginalSender( + result: Either, + conversationId: Matcher = any(), + messageId: Matcher = any() + ) +} + +class MessageMetaDataRepositoryArrangementImpl : MessageMetaDataRepositoryArrangement { + @Mock + override val messageMetaDataRepository: MessageMetaDataRepository = mock(MessageMetaDataRepository::class) + + override fun withMessageOriginalSender( + result: Either, + conversationId: Matcher, + messageId: Matcher + ) { + given(messageMetaDataRepository) + .suspendFunction(messageMetaDataRepository::originalSenderId) + .whenInvokedWith(conversationId, messageId) + .thenReturn(result) + } + +} diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/MessageRepositoryArrangement.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/repository/MessageRepositoryArrangement.kt similarity index 98% rename from logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/MessageRepositoryArrangement.kt rename to logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/repository/MessageRepositoryArrangement.kt index 350ed16b215..865ea04c5d9 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/MessageRepositoryArrangement.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/util/arrangement/repository/MessageRepositoryArrangement.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ -package com.wire.kalium.logic.util.arrangement +package com.wire.kalium.logic.util.arrangement.repository import com.wire.kalium.logic.CoreFailure import com.wire.kalium.logic.StorageFailure diff --git a/persistence/src/commonMain/db_user/com/wire/kalium/persistence/MessageMetaData.sq b/persistence/src/commonMain/db_user/com/wire/kalium/persistence/MessageMetaData.sq new file mode 100644 index 00000000000..4d32483500b --- /dev/null +++ b/persistence/src/commonMain/db_user/com/wire/kalium/persistence/MessageMetaData.sq @@ -0,0 +1,3 @@ + +originalSenderId: +SELECT sender_user_id FROM Message WHERE conversation_id = :conversationId AND id = :messageId; diff --git a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageMetaDataDAO.kt b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageMetaDataDAO.kt new file mode 100644 index 00000000000..bcf8e2f2180 --- /dev/null +++ b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageMetaDataDAO.kt @@ -0,0 +1,38 @@ +/* + * Wire + * Copyright (C) 2023 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.persistence.dao.message + +import com.wire.kalium.persistence.MessageMetaDataQueries +import com.wire.kalium.persistence.dao.ConversationIDEntity +import com.wire.kalium.persistence.dao.UserIDEntity +import kotlinx.coroutines.withContext +import kotlin.coroutines.CoroutineContext + +interface MessageMetaDataDAO { + suspend fun originalSenderId(conversationId: ConversationIDEntity, messageId: String): UserIDEntity? +} + +internal class MessageMetaDataDAOImpl internal constructor( + private val metaDataQueries: MessageMetaDataQueries, + private val coroutineContext: CoroutineContext +) : MessageMetaDataDAO { + override suspend fun originalSenderId(conversationId: ConversationIDEntity, messageId: String): UserIDEntity? = + withContext(coroutineContext) { + metaDataQueries.originalSenderId(conversationId, messageId).executeAsOneOrNull() + } +} diff --git a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/db/UserDatabaseBuilder.kt b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/db/UserDatabaseBuilder.kt index af662683e2b..9f7b045be15 100644 --- a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/db/UserDatabaseBuilder.kt +++ b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/db/UserDatabaseBuilder.kt @@ -56,6 +56,8 @@ import com.wire.kalium.persistence.dao.message.CompositeMessageDAO import com.wire.kalium.persistence.dao.message.CompositeMessageDAOImpl import com.wire.kalium.persistence.dao.message.MessageDAO import com.wire.kalium.persistence.dao.message.MessageDAOImpl +import com.wire.kalium.persistence.dao.message.MessageMetaDataDAO +import com.wire.kalium.persistence.dao.message.MessageMetaDataDAOImpl import com.wire.kalium.persistence.dao.newclient.NewClientDAO import com.wire.kalium.persistence.dao.newclient.NewClientDAOImpl import com.wire.kalium.persistence.dao.reaction.ReactionDAO @@ -159,6 +161,9 @@ class UserDatabaseBuilder internal constructor( val userDAO: UserDAO get() = UserDAOImpl(database.usersQueries, userCache, databaseScope, queriesContext) + val messageMetaDataDAO: MessageMetaDataDAO + get() = MessageMetaDataDAOImpl(database.messageMetaDataQueries, queriesContext) + val userConfigDAO: UserConfigDAO get() = UserConfigDAOImpl(metadataDAO) diff --git a/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/message/MessageMetaDataDAOTest.kt b/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/message/MessageMetaDataDAOTest.kt new file mode 100644 index 00000000000..ce1d93fe624 --- /dev/null +++ b/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/message/MessageMetaDataDAOTest.kt @@ -0,0 +1,91 @@ +/* + * Wire + * Copyright (C) 2023 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.persistence.dao.message + +import com.wire.kalium.persistence.BaseDatabaseTest +import com.wire.kalium.persistence.dao.UserDAO +import com.wire.kalium.persistence.dao.UserIDEntity +import com.wire.kalium.persistence.dao.conversation.ConversationDAO +import com.wire.kalium.persistence.utils.stubs.newConversationEntity +import com.wire.kalium.persistence.utils.stubs.newRegularMessageEntity +import com.wire.kalium.persistence.utils.stubs.newUserEntity +import kotlinx.coroutines.test.runTest +import kotlinx.datetime.Instant +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNull +import kotlin.time.Duration.Companion.days + +class MessageMetaDataDAOTest : BaseDatabaseTest() { + + private lateinit var messageDAO: MessageDAO + private lateinit var conversationDAO: ConversationDAO + private lateinit var userDAO: UserDAO + private lateinit var messageMetaDataDAO: MessageMetaDataDAO + + private val conversationEntity1 = newConversationEntity("Test1") + private val userEntity1 = newUserEntity("userEntity1") + private val selfUserId = UserIDEntity("selfValue", "selfDomain") + + @BeforeTest + fun setUp() { + deleteDatabase(selfUserId) + val db = createDatabase(selfUserId, encryptedDBSecret, true) + messageDAO = db.messageDAO + conversationDAO = db.conversationDAO + userDAO = db.userDAO + messageMetaDataDAO = db.messageMetaDataDAO + } + + + @Test + fun givenMessage_whenGettingOriginalSender_thenReturnItsId() = runTest { + val messageId = "testMessageId" + val originalUser = userEntity1 + + conversationDAO.insertConversation(conversationEntity1) + userDAO.insertUser(originalUser) + + val originalMessage = newRegularMessageEntity( + id = messageId, + conversationId = conversationEntity1.id, + senderUserId = originalUser.id, + senderClientId = "initialClientId", + content = MessageEntityContent.Text("Howdy"), + date = Instant.DISTANT_FUTURE - 5.days, + visibility = MessageEntity.Visibility.VISIBLE + ) + + messageDAO.insertOrIgnoreMessage(originalMessage) + + + messageMetaDataDAO.originalSenderId(originalMessage.conversationId, originalMessage.id).also { + assertEquals(originalUser.id, it) + } + } + + @Test + fun givenNoMessagee_whenGettingOriginalSender_thenReturnNull() = runTest { + val messageId = "testMessageId" + + messageMetaDataDAO.originalSenderId(conversationEntity1.id, messageId).also { + assertNull(it) + } + } +}