Skip to content

Commit

Permalink
feat: add useSFTForOneToOneCalls flag (WPB-7153) 🍒 (#2892)
Browse files Browse the repository at this point in the history
* feat: add useSFTForOneToOneCalls flag (WPB-7153) (#2889)

* feat: add useSFTForOneToOneCalls flag

* chore: uni test

* chore: unit test

* chore: Empty-Commit

---------

Co-authored-by: Oussama Hassine <[email protected]>
  • Loading branch information
github-actions[bot] and ohassine authored Jul 24, 2024
1 parent 69d3227 commit 5707160
Show file tree
Hide file tree
Showing 15 changed files with 221 additions and 17 deletions.
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 @@ -298,6 +300,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

0 comments on commit 5707160

Please sign in to comment.