From 509570a013cbffad5bbab60c7d5c5867f5b40dd9 Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Wed, 3 Jul 2024 12:07:24 +0200 Subject: [PATCH 1/3] Commit with unresolved merge conflicts --- .../kalium/logic/feature/UserSessionScope.kt | 1 + .../asset/ScheduleNewAssetMessageUseCase.kt | 31 ++- .../logic/feature/message/MessageScope.kt | 18 +- .../ScheduleNewAssetMessageUseCaseTest.kt | 224 ++++++++++++++++++ .../managed/ConversationRepository.kt | 65 +++-- 5 files changed, 312 insertions(+), 27 deletions(-) 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 b41285efc3e..7e3b492154c 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 @@ -1761,6 +1761,7 @@ class UserSessionScope internal constructor( messageMetadataRepository, staleEpochVerifier, legalHoldHandler, + observeFileSharingStatus, this, userScopedLogger, ) diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCase.kt index fa542a2d7c9..795fab0021a 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCase.kt @@ -24,6 +24,7 @@ import com.wire.kalium.cryptography.utils.AES256Key import com.wire.kalium.cryptography.utils.SHA256Key import com.wire.kalium.cryptography.utils.generateRandomAES256Key import com.wire.kalium.logic.CoreFailure +import com.wire.kalium.logic.configuration.FileSharingStatus import com.wire.kalium.logic.data.asset.AssetRepository import com.wire.kalium.logic.data.asset.AssetTransferStatus import com.wire.kalium.logic.data.asset.UploadedAssetId @@ -44,6 +45,7 @@ import com.wire.kalium.logic.data.user.UserId import com.wire.kalium.logic.feature.message.MessageSendFailureHandler import com.wire.kalium.logic.feature.message.MessageSender import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveSelfDeletionTimerSettingsForConversationUseCase +import com.wire.kalium.logic.feature.user.ObserveFileSharingStatusUseCase import com.wire.kalium.logic.functional.Either import com.wire.kalium.logic.functional.flatMap import com.wire.kalium.logic.functional.fold @@ -108,12 +110,14 @@ internal class ScheduleNewAssetMessageUseCaseImpl( private val userPropertyRepository: UserPropertyRepository, private val selfDeleteTimer: ObserveSelfDeletionTimerSettingsForConversationUseCase, private val scope: CoroutineScope, + private val observeFileSharingStatus: ObserveFileSharingStatusUseCase, + private val validateAssetMimeTypeUseCase: ValidateAssetMimeTypeUseCase, private val dispatcher: KaliumDispatcher, ) : ScheduleNewAssetMessageUseCase { private var outGoingAssetUploadJob: Job? = null - @Suppress("LongMethod") + @Suppress("LongMethod", "ReturnCount") override suspend fun invoke( conversationId: ConversationId, assetDataPath: Path, @@ -124,6 +128,19 @@ internal class ScheduleNewAssetMessageUseCaseImpl( assetHeight: Int?, audioLengthInMs: Long ): ScheduleNewAssetMessageResult { + observeFileSharingStatus().first().also { + when (it.state) { + FileSharingStatus.Value.Disabled -> return ScheduleNewAssetMessageResult.Failure.DisabledByTeam + FileSharingStatus.Value.EnabledAll -> { /* no-op*/ + } + + is FileSharingStatus.Value.EnabledSome -> if (!validateAssetMimeTypeUseCase(assetMimeType, it.state.allowedType)) { + kaliumLogger.e("The asset message trying to be processed has invalid content data") + return ScheduleNewAssetMessageResult.Failure.RestrictedFileType + } + } + } + slowSyncRepository.slowSyncStatus.first { it is SlowSyncStatus.Complete } @@ -165,7 +182,7 @@ internal class ScheduleNewAssetMessageUseCaseImpl( } } }.fold({ - ScheduleNewAssetMessageResult.Failure(it) + ScheduleNewAssetMessageResult.Failure.Generic(it) }, { (_, message) -> ScheduleNewAssetMessageResult.Success(message.id) }) @@ -345,9 +362,13 @@ internal class ScheduleNewAssetMessageUseCaseImpl( } } -sealed class ScheduleNewAssetMessageResult { - class Success(val messageId: String) : ScheduleNewAssetMessageResult() - class Failure(val coreFailure: CoreFailure) : ScheduleNewAssetMessageResult() +sealed interface ScheduleNewAssetMessageResult { + data class Success(val messageId: String) : ScheduleNewAssetMessageResult + sealed interface Failure : ScheduleNewAssetMessageResult { + data class Generic(val coreFailure: CoreFailure) : Failure + data object DisabledByTeam : Failure + data object RestrictedFileType : Failure + } } private data class AssetMessageMetadata( 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 fb2f1138ba9..ec0bf8cd10a 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 @@ -57,9 +57,18 @@ import com.wire.kalium.logic.feature.asset.ObserveAssetStatusesUseCase import com.wire.kalium.logic.feature.asset.ObserveAssetStatusesUseCaseImpl import com.wire.kalium.logic.feature.asset.ScheduleNewAssetMessageUseCase import com.wire.kalium.logic.feature.asset.ScheduleNewAssetMessageUseCaseImpl +<<<<<<< HEAD import com.wire.kalium.logic.feature.asset.UpdateAssetMessageTransferStatusUseCase import com.wire.kalium.logic.feature.asset.UpdateAssetMessageTransferStatusUseCaseImpl import com.wire.kalium.logic.feature.message.composite.SendButtonActionConfirmationMessageUseCase +======= +import com.wire.kalium.logic.feature.asset.UpdateAssetMessageDownloadStatusUseCase +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.asset.ValidateAssetMimeTypeUseCase +import com.wire.kalium.logic.feature.asset.ValidateAssetMimeTypeUseCaseImpl +>>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) import com.wire.kalium.logic.feature.message.composite.SendButtonActionMessageUseCase import com.wire.kalium.logic.feature.message.composite.SendButtonMessageUseCase import com.wire.kalium.logic.feature.message.draft.GetMessageDraftUseCase @@ -79,6 +88,7 @@ import com.wire.kalium.logic.feature.message.ephemeral.EphemeralMessageDeletionH import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveSelfDeletionTimerSettingsForConversationUseCase import com.wire.kalium.logic.feature.sessionreset.ResetSessionUseCase import com.wire.kalium.logic.feature.sessionreset.ResetSessionUseCaseImpl +import com.wire.kalium.logic.feature.user.ObserveFileSharingStatusUseCase import com.wire.kalium.logic.sync.SyncManager import com.wire.kalium.logic.sync.receiver.handler.legalhold.LegalHoldHandler import com.wire.kalium.logic.util.MessageContentEncoder @@ -115,8 +125,9 @@ class MessageScope internal constructor( private val messageMetadataRepository: MessageMetadataRepository, private val staleEpochVerifier: StaleEpochVerifier, private val legalHoldHandler: LegalHoldHandler, + private val observeFileSharingStatusUseCase: ObserveFileSharingStatusUseCase, private val scope: CoroutineScope, - private val kaliumLogger: KaliumLogger, + kaliumLogger: KaliumLogger, internal val dispatcher: KaliumDispatcher = KaliumDispatcherImpl, private val legalHoldStatusMapper: LegalHoldStatusMapper = LegalHoldStatusMapperImpl ) { @@ -152,6 +163,9 @@ class MessageScope internal constructor( protoContentMapper = protoContentMapper ) + private val validateAssetMimeTypeUseCase: ValidateAssetMimeTypeUseCase + get() = ValidateAssetMimeTypeUseCaseImpl() + private val messageContentEncoder = MessageContentEncoder() private val messageSendingInterceptor: MessageSendingInterceptor get() = MessageSendingInterceptorImpl(messageContentEncoder, messageRepository) @@ -256,6 +270,8 @@ class MessageScope internal constructor( userPropertyRepository, observeSelfDeletingMessages, scope, + observeFileSharingStatusUseCase, + validateAssetMimeTypeUseCase, dispatcher ) diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCaseTest.kt index bc7bc68dc6e..4e68ef7e390 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCaseTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCaseTest.kt @@ -22,6 +22,7 @@ import com.wire.kalium.cryptography.utils.SHA256Key import com.wire.kalium.logic.CoreFailure import com.wire.kalium.logic.NetworkFailure import com.wire.kalium.logic.StorageFailure +import com.wire.kalium.logic.configuration.FileSharingStatus import com.wire.kalium.logic.data.asset.AssetRepository import com.wire.kalium.logic.data.asset.AssetTransferStatus import com.wire.kalium.logic.data.asset.FakeKaliumFileSystem @@ -41,6 +42,11 @@ import com.wire.kalium.logic.data.sync.SlowSyncStatus import com.wire.kalium.logic.feature.message.MessageSendFailureHandler import com.wire.kalium.logic.feature.message.MessageSender import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveSelfDeletionTimerSettingsForConversationUseCase +<<<<<<< HEAD +======= +import com.wire.kalium.logic.data.message.SelfDeletionTimer +import com.wire.kalium.logic.feature.user.ObserveFileSharingStatusUseCase +>>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) import com.wire.kalium.logic.framework.TestAsset.dummyUploadedAssetId import com.wire.kalium.logic.framework.TestAsset.mockedLongAssetData import com.wire.kalium.logic.functional.Either @@ -93,6 +99,7 @@ class ScheduleNewAssetMessageUseCaseTest { .withObserveMessageVisibility() .withDeleteAssetLocally() .withSelfDeleteTimer(SelfDeletionTimer.Disabled) + .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledAll) .arrange() // When @@ -126,6 +133,7 @@ class ScheduleNewAssetMessageUseCaseTest { .withSelfDeleteTimer(SelfDeletionTimer.Disabled) .withDeleteAssetLocally() .withObserveMessageVisibility() + .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledAll) .arrange() // When @@ -159,6 +167,7 @@ class ScheduleNewAssetMessageUseCaseTest { .withSelfDeleteTimer(SelfDeletionTimer.Disabled) .withObserveMessageVisibility() .withDeleteAssetLocally() + .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledAll) .arrange() // When @@ -197,6 +206,7 @@ class ScheduleNewAssetMessageUseCaseTest { .withSelfDeleteTimer(SelfDeletionTimer.Disabled) .withObserveMessageVisibility() .withDeleteAssetLocally() + .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledAll) .arrange() // When @@ -243,7 +253,11 @@ class ScheduleNewAssetMessageUseCaseTest { .withSelfDeleteTimer(SelfDeletionTimer.Disabled) .withObserveMessageVisibility() .withDeleteAssetLocally() +<<<<<<< HEAD .withUpdateMessageAssetTransferStatus(UpdateTransferStatusResult.Success) +======= + .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledAll) +>>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) .arrange() // When @@ -261,6 +275,7 @@ class ScheduleNewAssetMessageUseCaseTest { advanceUntilIdle() // Then +<<<<<<< HEAD coVerify { arrangement.persistMessage.invoke(any()) }.wasInvoked(exactly = twice) @@ -273,6 +288,67 @@ class ScheduleNewAssetMessageUseCaseTest { coVerify { arrangement.messageSendFailureHandler.handleFailureAndUpdateMessageStatus(any(), any(), any(), any(), any()) }.wasInvoked(exactly = once) +======= + verify(arrangement.persistMessage) + .suspendFunction(arrangement.persistMessage::invoke) + .with(any()) + .wasInvoked(exactly = twice) + verify(arrangement.assetDataSource) + .suspendFunction(arrangement.assetDataSource::uploadAndPersistPrivateAsset) + .with(any(), any(), any(), any()) + .wasInvoked(exactly = once) + verify(arrangement.messageSender) + .suspendFunction(arrangement.messageSender::sendMessage) + .with(any()) + .wasInvoked(exactly = once) + verify(arrangement.messageSendFailureHandler) + .suspendFunction(arrangement.messageSendFailureHandler::handleFailureAndUpdateMessageStatus) + .with(any(), any(), any(), any(), any()) + .wasInvoked(exactly = once) + } + + @Test + fun givenASuccessfulSendAssetMessageRequest_whenCheckingTheMessageRepository_thenTheAssetIsMarkedAsSavedInternally() = + runTest(testDispatcher.default) { + // Given + val assetToSend = mockedLongAssetData() + val assetName = "some-asset.txt" + val conversationId = ConversationId("some-convo-id", "some-domain-id") + val dataPath = fakeKaliumFileSystem.providePersistentAssetPath(assetName) + val expectedAssetId = dummyUploadedAssetId + val expectedAssetSha256 = SHA256Key("some-asset-sha-256".toByteArray()) + val (arrangement, sendAssetUseCase) = Arrangement(this) + .withSuccessfulResponse(expectedAssetId, expectedAssetSha256) + .withSelfDeleteTimer(SelfDeletionTimer.Disabled) + .withObserveMessageVisibility() + .withDeleteAssetLocally() + .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledAll) + .arrange() + + // When + sendAssetUseCase.invoke( + conversationId = conversationId, + assetDataPath = dataPath, + assetDataSize = assetToSend.size.toLong(), + assetName = assetName, + assetMimeType = "text/plain", + assetWidth = null, + assetHeight = null, + audioLengthInMs = 0 + ) + advanceUntilIdle() + + // Then + verify(arrangement.persistMessage) + .suspendFunction(arrangement.persistMessage::invoke) + .with( + matching { + val content = it.content + content is MessageContent.Asset && content.value.downloadStatus == Message.DownloadStatus.SAVED_INTERNALLY + } + ) + .wasInvoked(exactly = twice) +>>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) } @Test @@ -288,6 +364,7 @@ class ScheduleNewAssetMessageUseCaseTest { .withSelfDeleteTimer(SelfDeletionTimer.Disabled) .withObserveMessageVisibility() .withDeleteAssetLocally() + .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledAll) .arrange() // When @@ -334,7 +411,11 @@ class ScheduleNewAssetMessageUseCaseTest { .withSelfDeleteTimer(SelfDeletionTimer.Disabled) .withObserveMessageVisibility() .withDeleteAssetLocally() +<<<<<<< HEAD .withUpdateMessageAssetTransferStatus(UpdateTransferStatusResult.Success) +======= + .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledAll) +>>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) .arrange() // When @@ -388,6 +469,7 @@ class ScheduleNewAssetMessageUseCaseTest { .withSelfDeleteTimer(SelfDeletionTimer.Disabled) .withObserveMessageVisibility() .withDeleteAssetLocally() + .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledAll) .arrange() // When @@ -439,6 +521,7 @@ class ScheduleNewAssetMessageUseCaseTest { .withSelfDeleteTimer(SelfDeletionTimer.Disabled) .withObserveMessageVisibility() .withDeleteAssetLocally() + .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledAll) .arrange() // When @@ -484,6 +567,7 @@ class ScheduleNewAssetMessageUseCaseTest { .withSelfDeleteTimer(SelfDeletionTimer.Enabled(expectedDuration)) .withObserveMessageVisibility() .withDeleteAssetLocally() + .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledAll) .arrange() // When @@ -512,6 +596,111 @@ class ScheduleNewAssetMessageUseCaseTest { } } + @Test + fun givenFileSendingRestrictedByTeam_whenSending_thenReturnDisabledByTeam() = runTest { + // Given + val assetToSend = mockedLongAssetData() + val assetName = "some-asset.txt" + val inputDataPath = fakeKaliumFileSystem.providePersistentAssetPath(assetName) + val conversationId = ConversationId("some-convo-id", "some-domain-id") + val (_, sendAssetUseCase) = Arrangement(this) + .withStoredData(assetToSend, inputDataPath) + .withObserveFileSharingStatusResult(FileSharingStatus.Value.Disabled) + .arrange() + + // When + val result = sendAssetUseCase.invoke( + conversationId = conversationId, + assetDataPath = inputDataPath, + assetDataSize = assetToSend.size.toLong(), + assetName = assetName, + assetMimeType = "text/plain", + assetWidth = null, + assetHeight = null, + audioLengthInMs = 0 + ) + advanceUntilIdle() + + // Then + assertTrue(result is ScheduleNewAssetMessageResult.Failure.DisabledByTeam) + } + + @Test + fun givenAseetMimeTypeRestricted_whenSending_thenReturnRestrictedFileType() = runTest { + // Given + val assetToSend = mockedLongAssetData() + val assetName = "some-asset.txt" + val inputDataPath = fakeKaliumFileSystem.providePersistentAssetPath(assetName) + val conversationId = ConversationId("some-convo-id", "some-domain-id") + val (arrangement, sendAssetUseCase) = Arrangement(this) + .withStoredData(assetToSend, inputDataPath) + .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledSome(listOf("png"))) + .withValidateAsseMimeTypeResult(false) + .arrange() + + // When + val result = sendAssetUseCase.invoke( + conversationId = conversationId, + assetDataPath = inputDataPath, + assetDataSize = assetToSend.size.toLong(), + assetName = assetName, + assetMimeType = "text/plain", + assetWidth = null, + assetHeight = null, + audioLengthInMs = 0 + ) + advanceUntilIdle() + + // Then + assertTrue(result is ScheduleNewAssetMessageResult.Failure.RestrictedFileType) + + verify(arrangement.validateAssetMimeTypeUseCase) + .function(arrangement.validateAssetMimeTypeUseCase::invoke) + .with(eq("text/plain"), eq(listOf("png"))) + .wasInvoked(exactly = once) + } + + @Test + fun givenAssetMimeTypeRestrictedAndFileAllowed_whenSending_thenReturnSendTheFile() = runTest(testDispatcher.default) { + // Given + val assetToSend = mockedLongAssetData() + val assetName = "some-asset.txt" + val inputDataPath = fakeKaliumFileSystem.providePersistentAssetPath(assetName) + val expectedAssetId = dummyUploadedAssetId + val expectedAssetSha256 = SHA256Key("some-asset-sha-256".toByteArray()) + val conversationId = ConversationId("some-convo-id", "some-domain-id") + val (arrangement, sendAssetUseCase) = Arrangement(this) + .withStoredData(assetToSend, inputDataPath) + .withSuccessfulResponse(expectedAssetId, expectedAssetSha256) + .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledSome(listOf("png"))) + .withValidateAsseMimeTypeResult(true) + .withSelfDeleteTimer(SelfDeletionTimer.Disabled) + .withObserveMessageVisibility() + .withDeleteAssetLocally() + .arrange() + + // When + val result = sendAssetUseCase.invoke( + conversationId = conversationId, + assetDataPath = inputDataPath, + assetDataSize = assetToSend.size.toLong(), + assetName = assetName, + assetMimeType = "image/png", + assetWidth = null, + assetHeight = null, + audioLengthInMs = 0 + ) + advanceUntilIdle() + + // Then + assertTrue(result is ScheduleNewAssetMessageResult.Success) + + verify(arrangement.validateAssetMimeTypeUseCase) + .function(arrangement.validateAssetMimeTypeUseCase::invoke) + .with(eq("image/png"), eq(listOf("png"))) + .wasInvoked(exactly = once) + } + private class Arrangement(val coroutineScope: CoroutineScope) { @Mock @@ -544,14 +733,47 @@ class ScheduleNewAssetMessageUseCaseTest { @Mock private val messageRepository: MessageRepository = mock(MessageRepository::class) + @Mock + val validateAssetMimeTypeUseCase: ValidateAssetMimeTypeUseCase = mock(ValidateAssetMimeTypeUseCase::class) + + @Mock + val observerFileSharingStatusUseCase: ObserveFileSharingStatusUseCase = mock(ObserveFileSharingStatusUseCase::class) + val someClientId = ClientId("some-client-id") val completeStateFlow = MutableStateFlow(SlowSyncStatus.Complete).asStateFlow() +<<<<<<< HEAD suspend fun withToggleReadReceiptsStatus(enabled: Boolean = false) = apply { coEvery { userPropertyRepository.getReadReceiptsStatus() }.returns(enabled) +======= + + init { + withToggleReadReceiptsStatus() + } + + fun withValidateAsseMimeTypeResult(result: Boolean) = apply { + given(validateAssetMimeTypeUseCase) + .function(validateAssetMimeTypeUseCase::invoke) + .whenInvokedWith(any(), any()) + .thenReturn(result) + } + + fun withObserveFileSharingStatusResult(result: FileSharingStatus.Value) = apply { + given(observerFileSharingStatusUseCase) + .function(observerFileSharingStatusUseCase::invoke) + .whenInvoked() + .thenReturn(flowOf(FileSharingStatus(result, false))) + } + + fun withToggleReadReceiptsStatus(enabled: Boolean = false) = apply { + given(userPropertyRepository) + .suspendFunction(userPropertyRepository::getReadReceiptsStatus) + .whenInvoked() + .thenReturn(enabled) +>>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) } fun withStoredData(data: ByteArray, dataPath: Path): Arrangement { @@ -704,6 +926,8 @@ class ScheduleNewAssetMessageUseCaseTest { userPropertyRepository, observeSelfDeletionTimerSettingsForConversation, coroutineScope, + observerFileSharingStatusUseCase, + validateAssetMimeTypeUseCase, testDispatcher ).also { withToggleReadReceiptsStatus() diff --git a/testservice/src/main/kotlin/com/wire/kalium/testservice/managed/ConversationRepository.kt b/testservice/src/main/kotlin/com/wire/kalium/testservice/managed/ConversationRepository.kt index 3920d0c48b8..0e41970066f 100644 --- a/testservice/src/main/kotlin/com/wire/kalium/testservice/managed/ConversationRepository.kt +++ b/testservice/src/main/kotlin/com/wire/kalium/testservice/managed/ConversationRepository.kt @@ -383,6 +383,7 @@ sealed class ConversationRepository { throw WebApplicationException("Instance ${instance.instanceId}: Could not get recent messages") } +<<<<<<< HEAD suspend fun getMessageReceipts( instance: Instance, conversationId: ConversationId, @@ -408,6 +409,9 @@ sealed class ConversationRepository { } @Suppress("LongParameterList", "LongMethod", "ThrowsCount") +======= + @Suppress("LongParameterList", "LongMethod", "ThrowsCount", "ComplexMethod") +>>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) suspend fun sendFile( instance: Instance, conversationId: ConversationId, @@ -462,16 +466,28 @@ sealed class ConversationRepository { } when (sendResult) { is ScheduleNewAssetMessageResult.Failure -> { - if (sendResult.coreFailure is StorageFailure.Generic) { - val rootCause = (sendResult.coreFailure as StorageFailure.Generic) - .rootCause.message - Response.status(Response.Status.INTERNAL_SERVER_ERROR) - .entity("Instance ${instance.instanceId}: Sending failed with $rootCause") - .build() - } else { - Response.status(Response.Status.INTERNAL_SERVER_ERROR) - .entity("Instance ${instance.instanceId}: Sending file $fileName failed") - .build() + // if the IDE tels you that this casting is unnecessary + // first check kotlin version + // if version < 2 then casting is necessary + // if version >= 2 then casting is unnecessary + when (val result = sendResult as ScheduleNewAssetMessageResult.Failure) { + ScheduleNewAssetMessageResult.Failure.RestrictedFileType, + ScheduleNewAssetMessageResult.Failure.DisabledByTeam -> { + throw WebApplicationException( + "Instance ${instance.instanceId}: Sending failed with $sendResult" + ) + } + + is ScheduleNewAssetMessageResult.Failure.Generic -> { + if (result.coreFailure is StorageFailure.Generic) { + val rootCause = (result.coreFailure as StorageFailure.Generic).rootCause.message + throw WebApplicationException( + "Instance ${instance.instanceId}: Sending failed with $rootCause" + ) + } else { + throw WebApplicationException("Instance ${instance.instanceId}: Sending failed") + } + } } } @@ -497,7 +513,7 @@ sealed class ConversationRepository { } } - @Suppress("LongParameterList") + @Suppress("LongParameterList", "ThrowsCount") suspend fun sendImage( instance: Instance, conversationId: ConversationId, @@ -533,17 +549,24 @@ sealed class ConversationRepository { height, 0L ) - if (sendResult is ScheduleNewAssetMessageResult.Failure) { - if (sendResult.coreFailure is StorageFailure.Generic) { - val rootCause = (sendResult.coreFailure as StorageFailure.Generic).rootCause.message - throw WebApplicationException( - "Instance ${instance.instanceId}: Sending failed with $rootCause" - ) - } else { - throw WebApplicationException("Instance ${instance.instanceId}: Sending failed") + when (sendResult) { + ScheduleNewAssetMessageResult.Failure.RestrictedFileType, + ScheduleNewAssetMessageResult.Failure.DisabledByTeam -> { + throw WebApplicationException("Instance ${instance.instanceId}: Sending failed with $sendResult") } - } else { - Response.status(Response.Status.OK).build() + + is ScheduleNewAssetMessageResult.Failure.Generic -> { + if (sendResult.coreFailure is StorageFailure.Generic) { + val rootCause = (sendResult.coreFailure as StorageFailure.Generic).rootCause.message + throw WebApplicationException( + "Instance ${instance.instanceId}: Sending failed with $rootCause" + ) + } else { + throw WebApplicationException("Instance ${instance.instanceId}: Sending failed") + } + } + + is ScheduleNewAssetMessageResult.Success -> Response.status(Response.Status.OK).build() } } } From bd405477304e72868774d0dac5dbafc47fe7c5f1 Mon Sep 17 00:00:00 2001 From: MohamadJaara Date: Wed, 3 Jul 2024 14:26:22 +0200 Subject: [PATCH 2/3] asset restriction --- .../asset/ScheduleNewAssetMessageUseCase.kt | 3 +- .../logic/feature/message/MessageScope.kt | 7 ---- .../ScheduleNewAssetMessageUseCaseTest.kt | 36 ++++--------------- .../managed/ConversationRepository.kt | 4 --- 4 files changed, 8 insertions(+), 42 deletions(-) diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCase.kt index 795fab0021a..650495fcbbe 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCase.kt @@ -131,8 +131,7 @@ internal class ScheduleNewAssetMessageUseCaseImpl( observeFileSharingStatus().first().also { when (it.state) { FileSharingStatus.Value.Disabled -> return ScheduleNewAssetMessageResult.Failure.DisabledByTeam - FileSharingStatus.Value.EnabledAll -> { /* no-op*/ - } + FileSharingStatus.Value.EnabledAll -> { /* no-op*/ } is FileSharingStatus.Value.EnabledSome -> if (!validateAssetMimeTypeUseCase(assetMimeType, it.state.allowedType)) { kaliumLogger.e("The asset message trying to be processed has invalid content data") 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 ec0bf8cd10a..a8c4def3bc0 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 @@ -57,18 +57,11 @@ import com.wire.kalium.logic.feature.asset.ObserveAssetStatusesUseCase import com.wire.kalium.logic.feature.asset.ObserveAssetStatusesUseCaseImpl import com.wire.kalium.logic.feature.asset.ScheduleNewAssetMessageUseCase import com.wire.kalium.logic.feature.asset.ScheduleNewAssetMessageUseCaseImpl -<<<<<<< HEAD import com.wire.kalium.logic.feature.asset.UpdateAssetMessageTransferStatusUseCase import com.wire.kalium.logic.feature.asset.UpdateAssetMessageTransferStatusUseCaseImpl import com.wire.kalium.logic.feature.message.composite.SendButtonActionConfirmationMessageUseCase -======= -import com.wire.kalium.logic.feature.asset.UpdateAssetMessageDownloadStatusUseCase -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.asset.ValidateAssetMimeTypeUseCase import com.wire.kalium.logic.feature.asset.ValidateAssetMimeTypeUseCaseImpl ->>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) import com.wire.kalium.logic.feature.message.composite.SendButtonActionMessageUseCase import com.wire.kalium.logic.feature.message.composite.SendButtonMessageUseCase import com.wire.kalium.logic.feature.message.draft.GetMessageDraftUseCase diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCaseTest.kt index 4e68ef7e390..6b99fbfd593 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCaseTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCaseTest.kt @@ -42,11 +42,7 @@ import com.wire.kalium.logic.data.sync.SlowSyncStatus import com.wire.kalium.logic.feature.message.MessageSendFailureHandler import com.wire.kalium.logic.feature.message.MessageSender import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveSelfDeletionTimerSettingsForConversationUseCase -<<<<<<< HEAD -======= -import com.wire.kalium.logic.data.message.SelfDeletionTimer import com.wire.kalium.logic.feature.user.ObserveFileSharingStatusUseCase ->>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) import com.wire.kalium.logic.framework.TestAsset.dummyUploadedAssetId import com.wire.kalium.logic.framework.TestAsset.mockedLongAssetData import com.wire.kalium.logic.functional.Either @@ -65,6 +61,7 @@ import io.mockative.matches import io.mockative.mock import io.mockative.once import io.mockative.twice +import io.mockative.verify import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow @@ -253,11 +250,8 @@ class ScheduleNewAssetMessageUseCaseTest { .withSelfDeleteTimer(SelfDeletionTimer.Disabled) .withObserveMessageVisibility() .withDeleteAssetLocally() -<<<<<<< HEAD .withUpdateMessageAssetTransferStatus(UpdateTransferStatusResult.Success) -======= .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledAll) ->>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) .arrange() // When @@ -275,7 +269,6 @@ class ScheduleNewAssetMessageUseCaseTest { advanceUntilIdle() // Then -<<<<<<< HEAD coVerify { arrangement.persistMessage.invoke(any()) }.wasInvoked(exactly = twice) @@ -288,23 +281,6 @@ class ScheduleNewAssetMessageUseCaseTest { coVerify { arrangement.messageSendFailureHandler.handleFailureAndUpdateMessageStatus(any(), any(), any(), any(), any()) }.wasInvoked(exactly = once) -======= - verify(arrangement.persistMessage) - .suspendFunction(arrangement.persistMessage::invoke) - .with(any()) - .wasInvoked(exactly = twice) - verify(arrangement.assetDataSource) - .suspendFunction(arrangement.assetDataSource::uploadAndPersistPrivateAsset) - .with(any(), any(), any(), any()) - .wasInvoked(exactly = once) - verify(arrangement.messageSender) - .suspendFunction(arrangement.messageSender::sendMessage) - .with(any()) - .wasInvoked(exactly = once) - verify(arrangement.messageSendFailureHandler) - .suspendFunction(arrangement.messageSendFailureHandler::handleFailureAndUpdateMessageStatus) - .with(any(), any(), any(), any(), any()) - .wasInvoked(exactly = once) } @Test @@ -339,6 +315,10 @@ class ScheduleNewAssetMessageUseCaseTest { advanceUntilIdle() // Then + verify { arrangement.assetDataSource.persistAsset(TODO(), any(), any(), any(), any()) } + .wasInvoked(exactly = twice) + + /* verify(arrangement.persistMessage) .suspendFunction(arrangement.persistMessage::invoke) .with( @@ -348,7 +328,8 @@ class ScheduleNewAssetMessageUseCaseTest { } ) .wasInvoked(exactly = twice) ->>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) + + */ } @Test @@ -411,11 +392,8 @@ class ScheduleNewAssetMessageUseCaseTest { .withSelfDeleteTimer(SelfDeletionTimer.Disabled) .withObserveMessageVisibility() .withDeleteAssetLocally() -<<<<<<< HEAD .withUpdateMessageAssetTransferStatus(UpdateTransferStatusResult.Success) -======= .withObserveFileSharingStatusResult(FileSharingStatus.Value.EnabledAll) ->>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) .arrange() // When diff --git a/testservice/src/main/kotlin/com/wire/kalium/testservice/managed/ConversationRepository.kt b/testservice/src/main/kotlin/com/wire/kalium/testservice/managed/ConversationRepository.kt index 0e41970066f..d1ee210273d 100644 --- a/testservice/src/main/kotlin/com/wire/kalium/testservice/managed/ConversationRepository.kt +++ b/testservice/src/main/kotlin/com/wire/kalium/testservice/managed/ConversationRepository.kt @@ -383,7 +383,6 @@ sealed class ConversationRepository { throw WebApplicationException("Instance ${instance.instanceId}: Could not get recent messages") } -<<<<<<< HEAD suspend fun getMessageReceipts( instance: Instance, conversationId: ConversationId, @@ -408,10 +407,7 @@ sealed class ConversationRepository { throw WebApplicationException("Instance ${instance.instanceId}: Could not get receipts from message") } - @Suppress("LongParameterList", "LongMethod", "ThrowsCount") -======= @Suppress("LongParameterList", "LongMethod", "ThrowsCount", "ComplexMethod") ->>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) suspend fun sendFile( instance: Instance, conversationId: ConversationId, From 14029482aab301757e94eaff912cd403bf9b3084 Mon Sep 17 00:00:00 2001 From: MohamadJaara Date: Wed, 3 Jul 2024 14:56:28 +0200 Subject: [PATCH 3/3] fix tests --- .../ScheduleNewAssetMessageUseCaseTest.kt | 59 ++++++------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCaseTest.kt index 6b99fbfd593..94ad32bd51c 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCaseTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/asset/ScheduleNewAssetMessageUseCaseTest.kt @@ -315,21 +315,17 @@ class ScheduleNewAssetMessageUseCaseTest { advanceUntilIdle() // Then - verify { arrangement.assetDataSource.persistAsset(TODO(), any(), any(), any(), any()) } - .wasInvoked(exactly = twice) - - /* - verify(arrangement.persistMessage) - .suspendFunction(arrangement.persistMessage::invoke) - .with( - matching { + coVerify { arrangement.assetDataSource.persistAsset(any(), any(), any(), any(), any()) } + .wasInvoked(exactly = once) + coVerify { + arrangement.persistMessage( + matches { val content = it.content - content is MessageContent.Asset && content.value.downloadStatus == Message.DownloadStatus.SAVED_INTERNALLY + content is MessageContent.Asset } ) - .wasInvoked(exactly = twice) + }.wasInvoked(exactly = twice) - */ } @Test @@ -632,10 +628,9 @@ class ScheduleNewAssetMessageUseCaseTest { // Then assertTrue(result is ScheduleNewAssetMessageResult.Failure.RestrictedFileType) - verify(arrangement.validateAssetMimeTypeUseCase) - .function(arrangement.validateAssetMimeTypeUseCase::invoke) - .with(eq("text/plain"), eq(listOf("png"))) - .wasInvoked(exactly = once) + verify { + arrangement.validateAssetMimeTypeUseCase(eq("text/plain"), eq(listOf("png"))) + }.wasInvoked(exactly = once) } @Test @@ -673,10 +668,9 @@ class ScheduleNewAssetMessageUseCaseTest { // Then assertTrue(result is ScheduleNewAssetMessageResult.Success) - verify(arrangement.validateAssetMimeTypeUseCase) - .function(arrangement.validateAssetMimeTypeUseCase::invoke) - .with(eq("image/png"), eq(listOf("png"))) - .wasInvoked(exactly = once) + verify { + arrangement.validateAssetMimeTypeUseCase(eq("image/png"), eq(listOf("png"))) + }.wasInvoked(exactly = once) } private class Arrangement(val coroutineScope: CoroutineScope) { @@ -721,37 +715,22 @@ class ScheduleNewAssetMessageUseCaseTest { val completeStateFlow = MutableStateFlow(SlowSyncStatus.Complete).asStateFlow() -<<<<<<< HEAD suspend fun withToggleReadReceiptsStatus(enabled: Boolean = false) = apply { coEvery { userPropertyRepository.getReadReceiptsStatus() }.returns(enabled) -======= - - init { - withToggleReadReceiptsStatus() } fun withValidateAsseMimeTypeResult(result: Boolean) = apply { - given(validateAssetMimeTypeUseCase) - .function(validateAssetMimeTypeUseCase::invoke) - .whenInvokedWith(any(), any()) - .thenReturn(result) + every { + validateAssetMimeTypeUseCase.invoke(any(), any()) + }.returns(result) } fun withObserveFileSharingStatusResult(result: FileSharingStatus.Value) = apply { - given(observerFileSharingStatusUseCase) - .function(observerFileSharingStatusUseCase::invoke) - .whenInvoked() - .thenReturn(flowOf(FileSharingStatus(result, false))) - } - - fun withToggleReadReceiptsStatus(enabled: Boolean = false) = apply { - given(userPropertyRepository) - .suspendFunction(userPropertyRepository::getReadReceiptsStatus) - .whenInvoked() - .thenReturn(enabled) ->>>>>>> 596eb022e3 (fix: asset restriction [WPB-9947] (#2831) (#2856) (#2861)) + every { + observerFileSharingStatusUseCase.invoke() + }.returns(flowOf(FileSharingStatus(result, false))) } fun withStoredData(data: ByteArray, dataPath: Path): Arrangement {