Skip to content
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 @@ -27,7 +27,9 @@ import com.wire.kalium.logic.feature.debug.GetDebugE2EICertificateExpirationUseC
import com.wire.kalium.logic.feature.debug.GetFeatureConfigUseCase
import com.wire.kalium.logic.feature.debug.GetConversationCryptoStatsUseCase
import com.wire.kalium.logic.feature.debug.GetConversationEpochFromCCUseCase
import com.wire.kalium.logic.feature.debug.ObserveDebugCRLExpirationAfterOneMinuteUseCase
import com.wire.kalium.logic.feature.debug.RepairFaultyRemovalKeysUseCase
import com.wire.kalium.logic.feature.debug.SetDebugCRLExpirationAfterOneMinuteUseCase
import com.wire.kalium.logic.feature.debug.SetDebugE2EICertificateExpirationUseCase
import dagger.Module
import dagger.Provides
Expand Down Expand Up @@ -94,6 +96,20 @@ class DebugModule {
fun provideSetDebugE2EICertificateExpirationUseCase(debugScope: DebugScope): SetDebugE2EICertificateExpirationUseCase =
debugScope.setDebugE2EICertificateExpiration

@ViewModelScoped
@Provides
fun provideObserveDebugCRLExpirationAfterOneMinuteUseCase(
debugScope: DebugScope
): ObserveDebugCRLExpirationAfterOneMinuteUseCase =
debugScope.observeDebugCRLExpirationAfterOneMinute

@ViewModelScoped
@Provides
fun provideSetDebugCRLExpirationAfterOneMinuteUseCase(
debugScope: DebugScope
): SetDebugCRLExpirationAfterOneMinuteUseCase =
debugScope.setDebugCRLExpirationAfterOneMinute

@ViewModelScoped
@Provides
fun provideGetConversationEpochFromCCUseCase(debugScope: DebugScope): GetConversationEpochFromCCUseCase =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ fun DebugDataOptions(
handleE2EIEnrollmentResult = viewModel::handleE2EIEnrollmentResult,
dismissCertificateDialog = viewModel::dismissCertificateDialog,
checkCrlRevocationList = viewModel::checkCrlRevocationList,
forceCRLExpirationAfterOneMinute = viewModel.state.forceCRLExpirationAfterOneMinute,
onForceCRLExpirationAfterOneMinuteChange = viewModel::forceCRLExpirationAfterOneMinute,
onResendFCMToken = viewModel::forceSendFCMToken,
onEnableAsyncNotificationsChange = viewModel::enableAsyncNotifications,
onShowFeatureFlags = onShowFeatureFlags,
Expand All @@ -110,6 +112,8 @@ fun DebugDataOptionsContent(
handleE2EIEnrollmentResult: (FinalizeEnrollmentResult) -> Unit,
dismissCertificateDialog: () -> Unit,
checkCrlRevocationList: () -> Unit,
forceCRLExpirationAfterOneMinute: Boolean,
onForceCRLExpirationAfterOneMinuteChange: (Boolean) -> Unit,
onResendFCMToken: () -> Unit,
onShowFeatureFlags: () -> Unit,
onShowCryptoStats: () -> Unit,
Expand Down Expand Up @@ -248,6 +252,8 @@ fun DebugDataOptionsContent(
onRestartSlowSyncForRecovery = onRestartSlowSyncForRecovery,
onForceUpdateApiVersions = onForceUpdateApiVersions,
checkCrlRevocationList = checkCrlRevocationList,
forceCRLExpirationAfterOneMinute = forceCRLExpirationAfterOneMinute,
onForceCRLExpirationAfterOneMinuteChange = onForceCRLExpirationAfterOneMinuteChange,
onResendFCMToken = onResendFCMToken,
isAsyncNotificationsEnabled = state.isAsyncNotificationsEnabled,
onEnableAsyncNotificationsChange = onEnableAsyncNotificationsChange
Expand Down Expand Up @@ -408,6 +414,8 @@ fun PreviewOtherDebugOptions() = WireTheme {
handleE2EIEnrollmentResult = {},
dismissCertificateDialog = {},
checkCrlRevocationList = {},
forceCRLExpirationAfterOneMinute = false,
onForceCRLExpirationAfterOneMinuteChange = {},
onResendFCMToken = {},
onEnableAsyncNotificationsChange = {},
onShowFeatureFlags = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ data class DebugDataOptionsState(
val showCertificate: Boolean = false,
val startGettingE2EICertificate: Boolean = false,
val e2eiCertificateExpirationSeconds: Long = 360L,
val forceCRLExpirationAfterOneMinute: Boolean = false,
val analyticsTrackingId: String = "null",
val isFederationEnabled: Boolean = false,
val currentApiVersion: String = "null",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
import com.wire.kalium.logic.feature.debug.StartUsingAsyncNotificationsUseCase
import com.wire.kalium.logic.feature.debug.GetDebugE2EICertificateExpirationUseCase
import com.wire.kalium.logic.feature.debug.MIN_DEBUG_E2EI_CERTIFICATE_EXPIRATION_SECONDS
import com.wire.kalium.logic.feature.debug.ObserveDebugCRLExpirationAfterOneMinuteUseCase
import com.wire.kalium.logic.feature.debug.SetDebugCRLExpirationAfterOneMinuteUseCase
import com.wire.kalium.logic.feature.debug.SetDebugE2EICertificateExpirationUseCase
import com.wire.kalium.logic.feature.debug.TargetedRepairParam
import com.wire.kalium.logic.feature.e2ei.CheckCrlRevocationListUseCase
Expand Down Expand Up @@ -79,6 +81,7 @@
val e2eiCertificateExpirationInputState: TextFieldState get() = TextFieldState("6")
fun currentAccount(): UserId = UserId("value", "domain")
fun checkCrlRevocationList() {}
fun forceCRLExpirationAfterOneMinute(enabled: Boolean) {}

Check failure on line 84 in app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptionsViewModel.kt

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a nested comment explaining why this function is empty or complete the implementation.

See more on https://sonarcloud.io/project/issues?id=wireapp_wire-android&issues=AZ5BAkrmXXApSxIf7O9X&open=AZ5BAkrmXXApSxIf7O9X&pullRequest=4839

Check warning on line 84 in app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptionsViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptionsViewModel.kt#L84

Added line #L84 was not covered by tests
fun restartSlowSyncForRecovery() {}
fun enrollE2EICertificate() {}
fun updateE2EICertificateExpiration(seconds: Long) {}
Expand Down Expand Up @@ -113,6 +116,8 @@
private val repairFaultyRemovalKeys: RepairFaultyRemovalKeysUseCase,
private val getDebugE2EICertificateExpiration: GetDebugE2EICertificateExpirationUseCase,
private val setDebugE2EICertificateExpiration: SetDebugE2EICertificateExpirationUseCase,
private val observeDebugCRLExpirationAfterOneMinute: ObserveDebugCRLExpirationAfterOneMinuteUseCase,
private val setDebugCRLExpirationAfterOneMinute: SetDebugCRLExpirationAfterOneMinuteUseCase,
) : ViewModel(), DebugDataOptionsViewModel {
private companion object {
val DEFAULT_DEBUG_E2EI_CERTIFICATE_EXPIRATION_SECONDS = 90.days.inWholeSeconds
Expand All @@ -133,6 +138,7 @@
init {
observeAsyncNotificationsEnabledData()
observeMlsMetadata()
observeDebugCRLExpiration()
observeE2EICertificateExpirationInput()
setGitHashAndDeviceId()
setAnalyticsTrackingId()
Expand Down Expand Up @@ -205,6 +211,15 @@
}
}

override fun forceCRLExpirationAfterOneMinute(enabled: Boolean) {
viewModelScope.launch {
setDebugCRLExpirationAfterOneMinute(enabled)
if (enabled) {
checkCrlRevocationList(forceUpdate = true)
}
}
}

override fun restartSlowSyncForRecovery() {
viewModelScope.launch {
restartSlowSyncProcessForRecovery()
Expand Down Expand Up @@ -373,6 +388,14 @@
}
}

private fun observeDebugCRLExpiration() {
viewModelScope.launch {
observeDebugCRLExpirationAfterOneMinute().collect { enabled ->
state = state.copy(forceCRLExpirationAfterOneMinute = enabled)
}
}
}

private fun loadDebugE2EICertificateExpiration() {
viewModelScope.launch {
val currentExpiration = getDebugE2EICertificateExpiration()
Expand Down
41 changes: 41 additions & 0 deletions app/src/main/kotlin/com/wire/android/ui/debug/DebugToolsOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
onRestartSlowSyncForRecovery = {},
onForceUpdateApiVersions = {},
checkCrlRevocationList = {},
forceCRLExpirationAfterOneMinute = false,
onForceCRLExpirationAfterOneMinuteChange = {},
onResendFCMToken = {},
isAsyncNotificationsEnabled = true,
onEnableAsyncNotificationsChange = {}
Expand All @@ -63,6 +65,8 @@
onRestartSlowSyncForRecovery: () -> Unit,
onForceUpdateApiVersions: () -> Unit,
checkCrlRevocationList: () -> Unit,
forceCRLExpirationAfterOneMinute: Boolean,
onForceCRLExpirationAfterOneMinuteChange: (Boolean) -> Unit,
onResendFCMToken: () -> Unit,
isAsyncNotificationsEnabled: Boolean,
onEnableAsyncNotificationsChange: (Boolean) -> Unit,
Expand All @@ -76,6 +80,8 @@
onRestartSlowSyncForRecovery = onRestartSlowSyncForRecovery,
onForceUpdateApiVersions = onForceUpdateApiVersions,
checkCrlRevocationList = checkCrlRevocationList,
forceCRLExpirationAfterOneMinute = forceCRLExpirationAfterOneMinute,
onForceCRLExpirationAfterOneMinuteChange = onForceCRLExpirationAfterOneMinuteChange,
isAsyncNotificationsEnabled = isAsyncNotificationsEnabled,
onEnableAsyncNotificationsChange = onEnableAsyncNotificationsChange
)
Expand All @@ -85,12 +91,14 @@
}

@Composable
private fun PrivateBuildDebugToolsOptions(

Check warning on line 94 in app/src/main/kotlin/com/wire/android/ui/debug/DebugToolsOptions.kt

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This function has 9 parameters, which is greater than the 7 authorized.

See more on https://sonarcloud.io/project/issues?id=wireapp_wire-android&issues=AZ5BAkofXXApSxIf7O9W&open=AZ5BAkofXXApSxIf7O9W&pullRequest=4839
isEventProcessingEnabled: Boolean,
onDisableEventProcessingChange: (Boolean) -> Unit,
onRestartSlowSyncForRecovery: () -> Unit,
onForceUpdateApiVersions: () -> Unit,
checkCrlRevocationList: () -> Unit,
forceCRLExpirationAfterOneMinute: Boolean,
onForceCRLExpirationAfterOneMinuteChange: (Boolean) -> Unit,
isAsyncNotificationsEnabled: Boolean,
onEnableAsyncNotificationsChange: (Boolean) -> Unit,
) {
Expand All @@ -100,6 +108,10 @@
onCheckedChange = onDisableEventProcessingChange
)
RestartSlowSyncButton(onClick = onRestartSlowSyncForRecovery)
ForceCRLExpirationAfterOneMinuteSwitch(
isEnabled = forceCRLExpirationAfterOneMinute,
onCheckedChange = onForceCRLExpirationAfterOneMinuteChange
)
CheckCrlRevocationButton(onClick = checkCrlRevocationList)
ForceUpdateApiVersionsButton(onClick = onForceUpdateApiVersions)
EnableAsyncNotifications(isAsyncNotificationsEnabled, onEnableAsyncNotificationsChange)
Expand Down Expand Up @@ -142,6 +154,35 @@
)
}

@Composable
private fun ForceCRLExpirationAfterOneMinuteSwitch(
isEnabled: Boolean = false,
onCheckedChange: ((Boolean) -> Unit)?,
) {
RowItemTemplate(
title = {
Text(
style = MaterialTheme.wireTypography.body01,
color = MaterialTheme.wireColorScheme.onBackground,
text = "Force CRL expiry after 1 minute",
modifier = Modifier.padding(start = dimensions().spacing8x)
)
},
actions = {
WireSwitch(
checked = isEnabled,
onCheckedChange = onCheckedChange,
modifier = Modifier
.padding(end = dimensions().spacing8x)
.size(
width = dimensions().buttonSmallMinSize.width,
height = dimensions().buttonSmallMinSize.height
)
)
}
)
}

@Composable
private fun RestartSlowSyncButton(
onClick: () -> Unit,
Expand Down
19 changes: 18 additions & 1 deletion app/src/main/kotlin/com/wire/android/ui/home/AppSyncViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@
import androidx.lifecycle.viewModelScope
import com.wire.android.appLogger
import com.wire.android.util.dispatchers.DispatcherProvider
import com.wire.kalium.logic.feature.debug.ObserveDebugCRLExpirationAfterOneMinuteUseCase
import com.wire.kalium.logic.sync.ForegroundActionsUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
Expand All @@ -34,14 +37,27 @@
@HiltViewModel
class AppSyncViewModel @Inject constructor(
private val foregroundActionsUseCase: ForegroundActionsUseCase,
observeDebugCRLExpirationAfterOneMinute: ObserveDebugCRLExpirationAfterOneMinuteUseCase,
private val dispatcher: DispatcherProvider,
) : ViewModel() {

private val minIntervalBetweenPulls: Duration = MIN_INTERVAL_BETWEEN_PULLS
private var minIntervalBetweenPulls: Duration = MIN_INTERVAL_BETWEEN_PULLS

private var lastPullInstant: Instant? = null
private var syncDataJob: Job? = null

init {
observeDebugCRLExpirationAfterOneMinute()
.onEach { isForced ->
minIntervalBetweenPulls = if (isForced) {
MIN_INTERVAL_BETWEEN_FORCED_CRL_PULLS

Check warning on line 53 in app/src/main/kotlin/com/wire/android/ui/home/AppSyncViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/home/AppSyncViewModel.kt#L53

Added line #L53 was not covered by tests
} else {
MIN_INTERVAL_BETWEEN_PULLS
}
}
.launchIn(viewModelScope)
}

fun startSyncingAppConfig() {
if (isSyncing()) return

Expand Down Expand Up @@ -75,5 +91,6 @@

companion object {
val MIN_INTERVAL_BETWEEN_PULLS = 60.minutes
val MIN_INTERVAL_BETWEEN_FORCED_CRL_PULLS = 1.minutes
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@ package com.wire.android.ui.home

import com.wire.android.config.CoroutineTestExtension
import com.wire.android.config.TestDispatcherProvider
import com.wire.kalium.logic.feature.debug.ObserveDebugCRLExpirationAfterOneMinuteUseCase
import com.wire.kalium.logic.sync.ForegroundActionsUseCase
import io.mockk.MockKAnnotations
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
Expand Down Expand Up @@ -65,8 +68,12 @@ class AppSyncViewModelTest {
@MockK
lateinit var foregroundActionsUseCase: ForegroundActionsUseCase

@MockK
lateinit var observeDebugCRLExpirationAfterOneMinute: ObserveDebugCRLExpirationAfterOneMinuteUseCase

init {
MockKAnnotations.init(this)
every { observeDebugCRLExpirationAfterOneMinute() } returns flowOf(false)
}

fun withForegroundActionsUseCase(delayMs: Long = 0) {
Expand All @@ -78,6 +85,7 @@ class AppSyncViewModelTest {
fun arrange(testDispatcher: TestDispatcherProvider, block: Arrangement.() -> Unit) = apply(block).let {
this to AppSyncViewModel(
foregroundActionsUseCase = foregroundActionsUseCase,
observeDebugCRLExpirationAfterOneMinute = observeDebugCRLExpirationAfterOneMinute,
dispatcher = testDispatcher
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import com.wire.kalium.logic.feature.debug.StartUsingAsyncNotificationsResult
import com.wire.kalium.logic.feature.debug.StartUsingAsyncNotificationsUseCase
import com.wire.kalium.logic.feature.debug.GetDebugE2EICertificateExpirationUseCase
import com.wire.kalium.logic.feature.debug.MIN_DEBUG_E2EI_CERTIFICATE_EXPIRATION_SECONDS
import com.wire.kalium.logic.feature.debug.ObserveDebugCRLExpirationAfterOneMinuteUseCase
import com.wire.kalium.logic.feature.debug.SetDebugCRLExpirationAfterOneMinuteUseCase
import com.wire.kalium.logic.feature.debug.SetDebugE2EICertificateExpirationUseCase
import com.wire.kalium.logic.feature.e2ei.CheckCrlRevocationListUseCase
import com.wire.kalium.logic.feature.keypackage.MLSKeyPackageCountResult
Expand Down Expand Up @@ -287,6 +289,25 @@ class DebugDataOptionsViewModelTest {
coVerify(exactly = 1) { arrangement.setDebugE2EICertificateExpiration(420) }
assertEquals(420, viewModel.state.e2eiCertificateExpirationSeconds)
}

@Test
fun `given CRL force expiration is observed, then view state contains loaded value`() = runTest {
val (_, viewModel) = DebugDataOptionsHiltArrangement()
.withDebugCRLExpirationAfterOneMinute(true)
.arrange()

assertEquals(true, viewModel.state.forceCRLExpirationAfterOneMinute)
}

@Test
fun `when forcing CRL expiration after one minute, then setting use case is called`() = runTest {
val (arrangement, viewModel) = DebugDataOptionsHiltArrangement().arrange()

viewModel.forceCRLExpirationAfterOneMinute(true)

coVerify(exactly = 1) { arrangement.setDebugCRLExpirationAfterOneMinute(true) }
coVerify(exactly = 1) { arrangement.checkCrlRevocationList(forceUpdate = true) }
}
}

internal class DebugDataOptionsHiltArrangement {
Expand Down Expand Up @@ -335,6 +356,12 @@ internal class DebugDataOptionsHiltArrangement {
@MockK
lateinit var setDebugE2EICertificateExpiration: SetDebugE2EICertificateExpirationUseCase

@MockK
lateinit var observeDebugCRLExpirationAfterOneMinute: ObserveDebugCRLExpirationAfterOneMinuteUseCase

@MockK
lateinit var setDebugCRLExpirationAfterOneMinute: SetDebugCRLExpirationAfterOneMinuteUseCase

private val viewModel by lazy {
DebugDataOptionsViewModelImpl(
context = context,
Expand All @@ -352,7 +379,9 @@ internal class DebugDataOptionsHiltArrangement {
observeAsyncNotificationsEnabled = observeIsConsumableNotificationsEnabled,
repairFaultyRemovalKeys = repairFaultyRemovalKeysUseCase,
getDebugE2EICertificateExpiration = getDebugE2EICertificateExpiration,
setDebugE2EICertificateExpiration = setDebugE2EICertificateExpiration
setDebugE2EICertificateExpiration = setDebugE2EICertificateExpiration,
observeDebugCRLExpirationAfterOneMinute = observeDebugCRLExpirationAfterOneMinute,
setDebugCRLExpirationAfterOneMinute = setDebugCRLExpirationAfterOneMinute
)
}

Expand Down Expand Up @@ -393,13 +422,19 @@ internal class DebugDataOptionsHiltArrangement {
withObserveIsConsumableNotificationsEnabled(false)
coEvery { getDebugE2EICertificateExpiration() } returns 360
coEvery { setDebugE2EICertificateExpiration(any()) } returns Unit
every { observeDebugCRLExpirationAfterOneMinute() } returns flowOf(false)
coEvery { setDebugCRLExpirationAfterOneMinute(any()) } returns Unit
}
}

fun withDebugE2EICertificateExpiration(expiration: Long) = apply {
coEvery { getDebugE2EICertificateExpiration() } returns expiration
}

fun withDebugCRLExpirationAfterOneMinute(enabled: Boolean) = apply {
every { observeDebugCRLExpirationAfterOneMinute() } returns flowOf(enabled)
}

suspend fun withObserveIsConsumableNotificationsEnabled(isEnabled: Boolean = false) = apply {
coEvery {
observeIsConsumableNotificationsEnabled()
Expand Down
Loading