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: create observer for team app lock config (WPB-4476) #2175

Merged
merged 7 commits into from
Nov 1, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import com.wire.kalium.logic.data.conversation.Conversation.Member
import com.wire.kalium.logic.data.conversation.Conversation.ReceiptMode
import com.wire.kalium.logic.data.conversation.Conversation.TypingIndicatorMode
import com.wire.kalium.logic.data.conversation.MutedConversationStatus
import com.wire.kalium.logic.data.featureConfig.AppLockModel
import com.wire.kalium.logic.data.featureConfig.ClassifiedDomainsModel
import com.wire.kalium.logic.data.featureConfig.ConferenceCallingModel
import com.wire.kalium.logic.data.featureConfig.ConfigsStatusModel
Expand Down Expand Up @@ -609,6 +610,19 @@ sealed class Event(open val id: String, open val transient: Boolean, open val li
"config" to model.config
)
}
data class AppLockUpdated(
override val id: String,
override val transient: Boolean,
override val live: Boolean,
val model: AppLockModel
) : FeatureConfig(id, transient, live) {
override fun toLogMap(): Map<String, Any?> = mapOf(
typeKey to "FeatureConfig.AppLockUpdated",
idKey to id.obfuscateId(),
featureStatusKey to model.status.name,
"config" to model.config
)
}

data class UnknownFeatureUpdated(
override val id: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,13 @@ class EventMapper(
featureConfigMapper.fromDTO(featureConfigUpdatedDTO.data as FeatureConfigData.E2EI)
)

is FeatureConfigData.AppLock -> Event.FeatureConfig.AppLockUpdated(
id,
transient,
live,
featureConfigMapper.fromDTO(featureConfigUpdatedDTO.data as FeatureConfigData.AppLock)
)

else -> Event.FeatureConfig.UnknownFeatureUpdated(id, transient, live)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ import com.wire.kalium.logic.di.MapperProvider
import com.wire.kalium.logic.di.PlatformUserStorageProperties
import com.wire.kalium.logic.di.RootPathsProvider
import com.wire.kalium.logic.di.UserStorageProvider
import com.wire.kalium.logic.feature.applock.AppLockTeamFeatureConfigObserver
import com.wire.kalium.logic.feature.applock.AppLockTeamFeatureConfigObserverImpl
import com.wire.kalium.logic.feature.asset.ValidateAssetMimeTypeUseCase
import com.wire.kalium.logic.feature.asset.ValidateAssetMimeTypeUseCaseImpl
import com.wire.kalium.logic.feature.auth.AuthenticationScope
Expand Down Expand Up @@ -1578,6 +1580,9 @@ class UserSessionScope internal constructor(
val markGuestLinkFeatureFlagAsNotChanged: MarkGuestLinkFeatureFlagAsNotChangedUseCase
get() = MarkGuestLinkFeatureFlagAsNotChangedUseCaseImpl(userConfigRepository)

val appLockTeamFeatureConfigObserver: AppLockTeamFeatureConfigObserver
get() = AppLockTeamFeatureConfigObserverImpl(userConfigRepository)

val markSelfDeletingMessagesAsNotified: MarkSelfDeletionStatusAsNotifiedUseCase
get() = MarkSelfDeletionStatusAsNotifiedUseCaseImpl(userConfigRepository)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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.applock

import kotlin.time.Duration

data class AppLockTeamConfig(
val isEnabled: Boolean,
val timeout: Duration
)
Original file line number Diff line number Diff line change
@@ -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.feature.applock

import com.wire.kalium.logic.configuration.UserConfigRepository
import com.wire.kalium.logic.functional.fold
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlin.time.Duration.Companion.seconds

/**
* observe app lock feature flag of the team
*/
interface AppLockTeamFeatureConfigObserver {
operator fun invoke(): Flow<AppLockTeamConfig>
}

class AppLockTeamFeatureConfigObserverImpl(
private val userConfigRepository: UserConfigRepository
) : AppLockTeamFeatureConfigObserver {
override fun invoke(): Flow<AppLockTeamConfig> =
userConfigRepository.observeAppLockStatus().map {
it.fold({
AppLockTeamConfig(
isEnabled = false,
timeout = DEFAULT_TIMEOUT
)
}, { appLockModel ->
AppLockTeamConfig(
isEnabled = appLockModel.enforceAppLock,
timeout = appLockModel.inactivityTimeoutSecs.seconds
)
})
}

companion object {
val DEFAULT_TIMEOUT = 60.seconds
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ internal class FeatureConfigEventReceiverImpl internal constructor(
private val appLockConfigHandler: AppLockConfigHandler
) : FeatureConfigEventReceiver {

override suspend fun onEvent(event: Event.FeatureConfig): Either<CoreFailure, Unit> {
override suspend fun onEvent(event: Event.FeatureConfig): Either<CoreFailure, Unit> =
handleFeatureConfigEvent(event)
.onSuccess {
kaliumLogger.logEventProcessing(
Expand All @@ -76,11 +76,6 @@ internal class FeatureConfigEventReceiverImpl internal constructor(
)
}
}
// TODO: Make sure errors are accounted for.
// onEvent now requires Either, so we can propagate errors.
// Returning Either.Right is the equivalent of how it was originally working.
return Either.Right(Unit)
}

@Suppress("LongMethod", "ComplexMethod")
private suspend fun handleFeatureConfigEvent(event: Event.FeatureConfig): Either<CoreFailure, Unit> =
Expand All @@ -93,6 +88,7 @@ internal class FeatureConfigEventReceiverImpl internal constructor(
is Event.FeatureConfig.GuestRoomLinkUpdated -> guestRoomConfigHandler.handle(event.model)
is Event.FeatureConfig.SelfDeletingMessagesConfig -> selfDeletingMessagesConfigHandler.handle(event.model)
is Event.FeatureConfig.MLSE2EIUpdated -> e2EIConfigHandler.handle(event.model)
is Event.FeatureConfig.AppLockUpdated -> appLockConfigHandler.handle(event.model)
is Event.FeatureConfig.UnknownFeatureUpdated -> Either.Left(CoreFailure.FeatureNotImplemented)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* 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.applock

import com.wire.kalium.logic.StorageFailure
import com.wire.kalium.logic.configuration.UserConfigRepository
import com.wire.kalium.logic.data.featureConfig.AppLockConfigModel
import com.wire.kalium.logic.functional.Either
import io.mockative.Mock
import io.mockative.classOf
import io.mockative.given
import io.mockative.mock
import io.mockative.once
import io.mockative.verify
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.time.Duration.Companion.seconds

class AppLockTeamFeatureConfigObserverTest {

@Test
fun givenRepositoryFailure_whenObservingAppLock_thenEmitAppLockConfigWithDisabledStatus() =
runTest {
val expectedAppLockValue = AppLockTeamConfig(
false,
AppLockTeamFeatureConfigObserverImpl.DEFAULT_TIMEOUT
)
val (arrangement, observer) = Arrangement()
.withFailure()
.arrange()

val result = observer.invoke()

verify(arrangement.userConfigRepository)
.function(arrangement.userConfigRepository::observeAppLockStatus)
.wasInvoked(exactly = once)
assertEquals(expectedAppLockValue, result.first())
}

@Test
fun givenRepositorySuccess_whenObservingAppLock_thenEmitAppLockConfigWithValueFromRepository() {
runTest {
val expectedAppLockValue = AppLockTeamConfig(
appLockConfigModel.enforceAppLock,
appLockConfigModel.inactivityTimeoutSecs.seconds
)
val (arrangement, observer) = Arrangement()
.withSuccess()
.arrange()

val result = observer.invoke()

verify(arrangement.userConfigRepository)
.function(arrangement.userConfigRepository::observeAppLockStatus)
.wasInvoked(exactly = once)
assertEquals(expectedAppLockValue, result.first())
}
}

private class Arrangement {

@Mock
val userConfigRepository = mock(classOf<UserConfigRepository>())

fun withFailure(): Arrangement = apply {
given(userConfigRepository)
.function(userConfigRepository::observeAppLockStatus)
.whenInvoked()
.thenReturn(flowOf(Either.Left(StorageFailure.DataNotFound)))
}

fun withSuccess(): Arrangement = apply {
given(userConfigRepository)
.function(userConfigRepository::observeAppLockStatus)
.whenInvoked()
.thenReturn(flowOf(Either.Right(appLockConfigModel)))
}

fun arrange() = this to AppLockTeamFeatureConfigObserverImpl(userConfigRepository)
}

companion object {
val appLockConfigModel = AppLockConfigModel(true, 60)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import io.mockative.matching
import io.mockative.mock
import io.mockative.once
import io.mockative.verify
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import okio.Path
Expand All @@ -58,7 +57,6 @@ import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue

@OptIn(ExperimentalCoroutinesApi::class)
class GetMessageAssetUseCaseTest {

private fun getSuccessfulFlowArrangement(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,12 @@ import io.mockative.given
import io.mockative.mock
import io.mockative.once
import io.mockative.verify
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import okio.Path.Companion.toPath
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals

@OptIn(ExperimentalCoroutinesApi::class)
class GetPublicAssetUseCaseTest {

@Mock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,10 @@ import com.wire.kalium.logic.data.message.Message
import com.wire.kalium.logic.data.message.MessageRepository
import com.wire.kalium.logic.functional.Either
import io.mockative.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertTrue

@OptIn(ExperimentalCoroutinesApi::class)
class UpdateAssetMessageDownloadStatusUseCaseTest {

@Test
Expand Down
Loading