Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add useSFTForOneToOneCalls flag (WPB-7153) #2889

Merged
merged 4 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ data class MLSMigrationModel(
)

data class ConferenceCallingModel(
val status: Status
val status: Status,
val useSFTForOneOnOneCalls: Boolean
)

data class E2EIModel(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ interface UserConfigRepository {
suspend fun getSupportedProtocols(): Either<StorageFailure, Set<SupportedProtocol>>
fun setConferenceCallingEnabled(enabled: Boolean): Either<StorageFailure, Unit>
fun isConferenceCallingEnabled(): Either<StorageFailure, Boolean>
fun setUseSFTForOneOnOneCalls(shouldUse: Boolean): Either<StorageFailure, Unit>
fun shouldUseSFTForOneOnOneCalls(): Either<StorageFailure, Boolean>
fun setSecondFactorPasswordChallengeStatus(isRequired: Boolean): Either<StorageFailure, Unit>
fun isSecondFactorPasswordChallengeRequired(): Either<StorageFailure, Boolean>
fun isReadReceiptsEnabled(): Flow<Either<StorageFailure, Boolean>>
Expand Down Expand Up @@ -292,6 +294,14 @@ internal class UserConfigDataSource internal constructor(
userConfigStorage.isConferenceCallingEnabled()
}

override fun setUseSFTForOneOnOneCalls(shouldUse: Boolean): Either<StorageFailure, Unit> = wrapStorageRequest {
userConfigStorage.persistUseSftForOneOnOneCalls(shouldUse)
}

override fun shouldUseSFTForOneOnOneCalls(): Either<StorageFailure, Boolean> = wrapStorageRequest {
userConfigStorage.shouldUseSftForOneOnOneCalls()
}

override fun setSecondFactorPasswordChallengeStatus(isRequired: Boolean): Either<StorageFailure, Unit> =
wrapStorageRequest {
userConfigStorage.persistSecondFactorPasswordChallengeStatus(isRequired)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ class FeatureConfigMapperImpl : FeatureConfigMapper {

override fun fromDTO(data: FeatureConfigData.ConferenceCalling): ConferenceCallingModel =
ConferenceCallingModel(
status = fromDTO(data.status)
status = fromDTO(data.status),
useSFTForOneOnOneCalls = data.config.useSFTForOneToOneCalls
)

override fun fromDTO(data: FeatureConfigData.E2EI?): E2EIModel =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ internal class SyncFeatureConfigsUseCaseImpl(
conferenceCallingConfigHandler.handle(it.conferenceCallingModel)
passwordChallengeConfigHandler.handle(it.secondFactorPasswordChallengeModel)
selfDeletingMessagesConfigHandler.handle(it.selfDeletingMessagesModel)
it.e2EIModel?.let { e2EIModel -> e2EIConfigHandler.handle(e2EIModel) }
it.e2EIModel.let { e2EIModel -> e2EIConfigHandler.handle(e2EIModel) }
appLockConfigHandler.handle(it.appLockModel)
Either.Right(Unit)
}.onFailure { networkFailure ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,16 @@ import com.wire.kalium.logic.configuration.UserConfigRepository
import com.wire.kalium.logic.data.featureConfig.ConferenceCallingModel
import com.wire.kalium.logic.data.featureConfig.Status
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.flatMap

class ConferenceCallingConfigHandler(
private val userConfigRepository: UserConfigRepository
) {
fun handle(conferenceCallingConfig: ConferenceCallingModel): Either<CoreFailure, Unit> {
val conferenceCallingEnabled = conferenceCallingConfig.status == Status.ENABLED
return userConfigRepository.setConferenceCallingEnabled(conferenceCallingEnabled)
val result = userConfigRepository.setConferenceCallingEnabled(conferenceCallingEnabled).flatMap {
userConfigRepository.setUseSFTForOneOnOneCalls(conferenceCallingConfig.useSFTForOneOnOneCalls)
}
return result
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.wire.kalium.logic.data.featureConfig.FeatureConfigMapperImpl
import com.wire.kalium.logic.data.featureConfig.Status
import com.wire.kalium.network.api.authenticated.featureConfigs.AppLockConfigDTO
import com.wire.kalium.network.api.authenticated.featureConfigs.ClassifiedDomainsConfigDTO
import com.wire.kalium.network.api.authenticated.featureConfigs.ConferenceCallingConfigDTO
import com.wire.kalium.network.api.authenticated.featureConfigs.FeatureConfigData
import com.wire.kalium.network.api.authenticated.featureConfigs.FeatureConfigResponse
import com.wire.kalium.network.api.authenticated.featureConfigs.FeatureFlagStatusDTO
Expand Down Expand Up @@ -141,7 +142,7 @@ class FeatureConfigMapperTest {
ClassifiedDomainsConfigDTO(listOf("wire.com")),
FeatureFlagStatusDTO.ENABLED
),
FeatureConfigData.ConferenceCalling(FeatureFlagStatusDTO.ENABLED),
FeatureConfigData.ConferenceCalling(FeatureFlagStatusDTO.ENABLED, ConferenceCallingConfigDTO(false)),
FeatureConfigData.ConversationGuestLinks(FeatureFlagStatusDTO.ENABLED),
FeatureConfigData.DigitalSignatures(FeatureFlagStatusDTO.ENABLED),
FeatureConfigData.FileSharing(FeatureFlagStatusDTO.ENABLED),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.wire.kalium.logic.util.shouldFail
import com.wire.kalium.logic.util.shouldSucceed
import com.wire.kalium.network.api.authenticated.featureConfigs.AppLockConfigDTO
import com.wire.kalium.network.api.authenticated.featureConfigs.ClassifiedDomainsConfigDTO
import com.wire.kalium.network.api.authenticated.featureConfigs.ConferenceCallingConfigDTO
import com.wire.kalium.network.api.authenticated.featureConfigs.E2EIConfigDTO
import com.wire.kalium.network.api.base.authenticated.featureConfigs.FeatureConfigApi
import com.wire.kalium.network.api.authenticated.featureConfigs.FeatureConfigData
Expand Down Expand Up @@ -59,7 +60,7 @@ class FeatureConfigRepositoryTest {
ClassifiedDomainsConfigModel(listOf()),
Status.ENABLED
),
ConferenceCallingModel(Status.ENABLED),
ConferenceCallingModel(Status.ENABLED, false),
ConfigsStatusModel(Status.ENABLED),
ConfigsStatusModel(Status.ENABLED),
ConfigsStatusModel(Status.ENABLED),
Expand Down Expand Up @@ -145,7 +146,7 @@ class FeatureConfigRepositoryTest {
AppLockConfigDTO(true, 0), FeatureFlagStatusDTO.ENABLED
),
FeatureConfigData.ClassifiedDomains(ClassifiedDomainsConfigDTO(listOf()), FeatureFlagStatusDTO.ENABLED),
FeatureConfigData.ConferenceCalling(FeatureFlagStatusDTO.ENABLED),
FeatureConfigData.ConferenceCalling(FeatureFlagStatusDTO.ENABLED, ConferenceCallingConfigDTO(false)),
FeatureConfigData.ConversationGuestLinks(FeatureFlagStatusDTO.ENABLED),
FeatureConfigData.DigitalSignatures(FeatureFlagStatusDTO.ENABLED),
FeatureConfigData.FileSharing(FeatureFlagStatusDTO.ENABLED),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ object FeatureConfigTest {
ClassifiedDomainsConfigModel(listOf()),
Status.ENABLED
),
conferenceCallingModel: ConferenceCallingModel = ConferenceCallingModel(Status.ENABLED),
conferenceCallingModel: ConferenceCallingModel = ConferenceCallingModel(Status.ENABLED, false),
conversationGuestLinksModel: ConfigsStatusModel = ConfigsStatusModel(Status.ENABLED),
digitalSignaturesModel: ConfigsStatusModel = ConfigsStatusModel(Status.ENABLED),
fileSharingModel: ConfigsStatusModel = ConfigsStatusModel(Status.ENABLED),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class SyncFeatureConfigsUseCaseTest {
fun givenConferenceCallingIsEnabled_whenSyncing_thenItShouldBeStoredAsEnabled() = runTest {
val (arrangement, syncFeatureConfigsUseCase) = Arrangement()
.withRemoteFeatureConfigsSucceeding(
FeatureConfigTest.newModel(conferenceCallingModel = ConferenceCallingModel(Status.ENABLED))
FeatureConfigTest.newModel(conferenceCallingModel = ConferenceCallingModel(Status.ENABLED, false))
)
.withGetTeamSettingsSelfDeletionStatusSuccessful()
.withGetSupportedProtocolsReturning(null)
Expand All @@ -136,7 +136,7 @@ class SyncFeatureConfigsUseCaseTest {
fun givenConferenceCallingIsDisasbled_whenSyncing_thenItShouldBeStoredAsDisabled() = runTest {
val (arrangement, syncFeatureConfigsUseCase) = Arrangement()
.withRemoteFeatureConfigsSucceeding(
FeatureConfigTest.newModel(conferenceCallingModel = ConferenceCallingModel(Status.DISABLED))
FeatureConfigTest.newModel(conferenceCallingModel = ConferenceCallingModel(Status.DISABLED, false))
)
.withGetTeamSettingsSelfDeletionStatusSuccessful()
.withGetSupportedProtocolsReturning(null)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Wire
* Copyright (C) 2024 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.featureConfig.handler

import com.wire.kalium.logic.StorageFailure
import com.wire.kalium.logic.configuration.UserConfigRepository
import com.wire.kalium.logic.data.featureConfig.ConferenceCallingModel
import com.wire.kalium.logic.data.featureConfig.Status
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.isLeft
import com.wire.kalium.logic.functional.isRight
import io.mockative.Mock
import io.mockative.any
import io.mockative.every
import io.mockative.mock
import io.mockative.once
import io.mockative.verify
import kotlin.test.Test
import kotlin.test.assertTrue

class ConferenceCallingConfigHandlerTest {

@Test
fun givenUserConfigRepositoryFailureForConferenceCallingEnabled_whenHandlingTheEvent_ThenReturnFailure() {
val conferenceCallingModel = ConferenceCallingModel(Status.ENABLED, false)
val (arrangement, conferenceCallingConfigHandler) = Arrangement()
.withSetConferenceCallingEnabledFailure()
.arrange()

val result = conferenceCallingConfigHandler.handle(conferenceCallingModel)

verify {
arrangement.userConfigRepository.setConferenceCallingEnabled(conferenceCallingModel.status.toBoolean())
}.wasInvoked(exactly = once)

verify {
arrangement.userConfigRepository.setUseSFTForOneOnOneCalls(any())
}.wasNotInvoked()

assertTrue { result.isLeft() }
}

@Test
fun givenUserConfigRepositoryFailureForUseSFTForOneOnOneCalls_whenHandlingTheEvent_ThenReturnFailure() {
val conferenceCallingModel = ConferenceCallingModel(Status.ENABLED, false)
val (arrangement, conferenceCallingConfigHandler) = Arrangement()
.withSetConferenceCallingEnabledSuccess()
.withSetUseSFTForOneOnOneCallsFailure()
.arrange()

val result = conferenceCallingConfigHandler.handle(conferenceCallingModel)

verify {
arrangement.userConfigRepository.setConferenceCallingEnabled(conferenceCallingModel.status.toBoolean())
}.wasInvoked(exactly = once)

verify {
arrangement.userConfigRepository.setUseSFTForOneOnOneCalls(any())
}.wasInvoked(exactly = once)

assertTrue { result.isLeft() }
}

@Test
fun givenUserConfigRepositorySuccess_whenHandlingTheEvent_ThenReturnUnit() {
val conferenceCallingModel = ConferenceCallingModel(Status.ENABLED, false)
val (arrangement, conferenceCallingConfigHandler) = Arrangement()
.withSetConferenceCallingEnabledSuccess()
.withSetUseSFTForOneOnOneCallsSuccess()
.arrange()

val result = conferenceCallingConfigHandler.handle(conferenceCallingModel)

verify {
arrangement.userConfigRepository.setConferenceCallingEnabled(conferenceCallingModel.status.toBoolean())
}.wasInvoked(exactly = once)

verify {
arrangement.userConfigRepository.setUseSFTForOneOnOneCalls(any())
}.wasInvoked(exactly = once)

assertTrue { result.isRight() }
}

private class Arrangement {

@Mock
val userConfigRepository: UserConfigRepository = mock(UserConfigRepository::class)

fun arrange() = run {
this@Arrangement to ConferenceCallingConfigHandler(
userConfigRepository = userConfigRepository
)
}

init {
every {
userConfigRepository.setAppLockStatus(any(), any(), any())
}.returns(Either.Right(Unit))
}

fun withSetConferenceCallingEnabledFailure() = apply {
every {
userConfigRepository.setConferenceCallingEnabled(any())
}.returns(Either.Left(StorageFailure.DataNotFound))
}

fun withSetConferenceCallingEnabledSuccess() = apply {
every {
userConfigRepository.setConferenceCallingEnabled(any())
}.returns(Either.Right(Unit))
}

fun withSetUseSFTForOneOnOneCallsFailure() = apply {
every {
userConfigRepository.setUseSFTForOneOnOneCalls(any())
}.returns(Either.Left(StorageFailure.DataNotFound))
}

fun withSetUseSFTForOneOnOneCallsSuccess() = apply {
every {
userConfigRepository.setUseSFTForOneOnOneCalls(any())
}.returns(Either.Right(Unit))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,35 +112,45 @@ class FeatureConfigEventReceiverTest {
}

@Test
fun givenConferenceCallingUpdatedEventGrantingAccess_whenProcessingEvent_ThenSetConferenceCallingEnabledToTrue() = runTest {
fun givenConferenceCallingEventEnabled_whenProcessingEvent_ThenSetConferenceCallingEnabledToTrueAndSetShouldUseSFTFlag() = runTest {
val (arrangement, featureConfigEventReceiver) = Arrangement()
.withSetUseSFTForOneOnOneCallsSuccessful()
.withSettingConferenceCallingEnabledSuccessful()
.arrange()

featureConfigEventReceiver.onEvent(
arrangement.newConferenceCallingUpdatedEvent(ConferenceCallingModel(Status.ENABLED)),
arrangement.newConferenceCallingUpdatedEvent(ConferenceCallingModel(Status.ENABLED, false)),
TestEvent.liveDeliveryInfo
)

verify {
arrangement.userConfigRepository.setConferenceCallingEnabled(eq(true))
}.wasInvoked(once)

verify {
arrangement.userConfigRepository.setUseSFTForOneOnOneCalls(eq(false))
}.wasInvoked(once)
}

@Test
fun givenConferenceCallingUpdatedEventGrantingAccess_whenProcessingEvent_ThenSetConferenceCallingEnabledToFalse() = runTest {
fun givenConferenceCallingEventDisabled_whenProcessingEvent_ThenSetConferenceCallingEnabledToFalseOnly() = runTest {
val (arrangement, featureConfigEventReceiver) = Arrangement()
.withSetUseSFTForOneOnOneCallsSuccessful()
.withSettingConferenceCallingEnabledSuccessful()
.arrange()

featureConfigEventReceiver.onEvent(
event = arrangement.newConferenceCallingUpdatedEvent(ConferenceCallingModel(Status.DISABLED)),
event = arrangement.newConferenceCallingUpdatedEvent(ConferenceCallingModel(Status.DISABLED, false)),
deliveryInfo = TestEvent.liveDeliveryInfo
)

verify {
arrangement.userConfigRepository.setConferenceCallingEnabled(eq(false))
}.wasInvoked(once)

verify {
arrangement.userConfigRepository.setUseSFTForOneOnOneCalls(eq(true))
}.wasNotInvoked()
}

@Test
Expand Down Expand Up @@ -339,6 +349,12 @@ class FeatureConfigEventReceiverTest {
}.returns(Either.Right(Unit))
}

fun withSetUseSFTForOneOnOneCallsSuccessful() = apply {
every {
userConfigRepository.setUseSFTForOneOnOneCalls(any())
}.returns(Either.Right(Unit))
}

fun withIsFileSharingEnabled(result: Either<StorageFailure, FileSharingStatus>) = apply {
every {
userConfigRepository.isFileSharingEnabled()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package com.wire.kalium.mocks.responses

import com.wire.kalium.network.api.authenticated.featureConfigs.AppLockConfigDTO
import com.wire.kalium.network.api.authenticated.featureConfigs.ClassifiedDomainsConfigDTO
import com.wire.kalium.network.api.authenticated.featureConfigs.ConferenceCallingConfigDTO
import com.wire.kalium.network.api.authenticated.featureConfigs.FeatureConfigData
import com.wire.kalium.network.api.authenticated.featureConfigs.FeatureConfigData.AppLock
import com.wire.kalium.network.api.authenticated.featureConfigs.FeatureConfigData.ClassifiedDomains
Expand Down Expand Up @@ -64,6 +65,9 @@ object FeatureConfigJson {
| "status": "enabled"
| },
| "conferenceCalling": {
| "config": {
| "useSFTForOneToOneCalls": false
| },
| "status": "enabled"
| },
| "conversationGuestLinks": {
Expand Down Expand Up @@ -116,7 +120,7 @@ object FeatureConfigJson {
AppLockConfigDTO(true, 0), FeatureFlagStatusDTO.ENABLED
),
ClassifiedDomains(ClassifiedDomainsConfigDTO(listOf()), FeatureFlagStatusDTO.ENABLED),
ConferenceCalling(FeatureFlagStatusDTO.ENABLED),
ConferenceCalling(FeatureFlagStatusDTO.ENABLED, ConferenceCallingConfigDTO(false)),
ConversationGuestLinks(FeatureFlagStatusDTO.ENABLED),
DigitalSignatures(FeatureFlagStatusDTO.ENABLED),
FileSharing(FeatureFlagStatusDTO.ENABLED),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.wire.kalium.mocks.responses

import com.wire.kalium.network.api.authenticated.featureConfigs.AppLockConfigDTO
import com.wire.kalium.network.api.authenticated.featureConfigs.ClassifiedDomainsConfigDTO
import com.wire.kalium.network.api.authenticated.featureConfigs.ConferenceCallingConfigDTO
import com.wire.kalium.network.api.authenticated.featureConfigs.E2EIConfigDTO
import com.wire.kalium.network.api.authenticated.featureConfigs.FeatureConfigData
import com.wire.kalium.network.api.authenticated.featureConfigs.FeatureConfigResponse
Expand Down Expand Up @@ -46,7 +47,7 @@ object FeatureConfigResponseJson {
ClassifiedDomainsConfigDTO(listOf("wire.com")),
FeatureFlagStatusDTO.ENABLED
),
FeatureConfigData.ConferenceCalling(FeatureFlagStatusDTO.ENABLED),
FeatureConfigData.ConferenceCalling(FeatureFlagStatusDTO.ENABLED, ConferenceCallingConfigDTO(false)),
FeatureConfigData.ConversationGuestLinks(FeatureFlagStatusDTO.ENABLED),
FeatureConfigData.DigitalSignatures(FeatureFlagStatusDTO.ENABLED),
FeatureConfigData.FileSharing(FeatureFlagStatusDTO.ENABLED),
Expand Down
Loading
Loading