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: Show a dialog when current client's certificate is revoked (WPB-6145) #2594

Merged
merged 8 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
25 changes: 25 additions & 0 deletions app/src/main/kotlin/com/wire/android/ui/WireActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import com.wire.android.appLogger
import com.wire.android.config.CustomUiConfigurationProvider
import com.wire.android.config.LocalCustomUiConfigurationProvider
import com.wire.android.datastore.UserDataStore
import com.wire.android.feature.NavigationSwitchAccountActions
import com.wire.android.navigation.BackStackMode
import com.wire.android.navigation.NavigationCommand
Expand All @@ -65,6 +66,7 @@
import com.wire.android.ui.common.snackbar.LocalSnackbarHostState
import com.wire.android.ui.common.topappbar.CommonTopAppBar
import com.wire.android.ui.common.topappbar.CommonTopAppBarViewModel
import com.wire.android.ui.common.visbility.rememberVisibilityState
import com.wire.android.ui.destinations.ConversationScreenDestination
import com.wire.android.ui.destinations.E2eiCertificateDetailsScreenDestination
import com.wire.android.ui.destinations.HomeScreenDestination
Expand All @@ -77,6 +79,7 @@
import com.wire.android.ui.destinations.SelfDevicesScreenDestination
import com.wire.android.ui.destinations.SelfUserProfileScreenDestination
import com.wire.android.ui.destinations.WelcomeScreenDestination
import com.wire.android.ui.home.E2EICertificateRevokedDialog
import com.wire.android.ui.home.E2EIRequiredDialog
import com.wire.android.ui.home.E2EIResultDialog
import com.wire.android.ui.home.E2EISnoozeDialog
Expand All @@ -90,6 +93,8 @@
import com.wire.android.ui.legalhold.dialog.requested.LegalHoldRequestedViewModel
import com.wire.android.ui.theme.ThemeOption
import com.wire.android.ui.theme.WireTheme
import com.wire.android.ui.userprofile.self.dialog.LogoutOptionsDialog
import com.wire.android.ui.userprofile.self.dialog.LogoutOptionsDialogState
import com.wire.android.util.CurrentScreenManager
import com.wire.android.util.LocalSyncStateObserver
import com.wire.android.util.SyncStateObserver
Expand Down Expand Up @@ -325,6 +330,26 @@
hideDialogStatus = featureFlagNotificationViewModel::dismissSelfDeletingMessagesDialog
)
}
val logoutOptionsDialogState = rememberVisibilityState<LogoutOptionsDialogState>()

Check warning on line 333 in app/src/main/kotlin/com/wire/android/ui/WireActivity.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/WireActivity.kt#L333

Added line #L333 was not covered by tests

LogoutOptionsDialog(
dialogState = logoutOptionsDialogState,
checkboxEnabled = false,

Check warning on line 337 in app/src/main/kotlin/com/wire/android/ui/WireActivity.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/WireActivity.kt#L335-L337

Added lines #L335 - L337 were not covered by tests
logout = {
viewModel.doHardLogout(
{ UserDataStore(context, it) },
NavigationSwitchAccountActions(navigate)

Check warning on line 341 in app/src/main/kotlin/com/wire/android/ui/WireActivity.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/WireActivity.kt#L339-L341

Added lines #L339 - L341 were not covered by tests
)
logoutOptionsDialogState.dismiss()
}

Check warning on line 344 in app/src/main/kotlin/com/wire/android/ui/WireActivity.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/WireActivity.kt#L343-L344

Added lines #L343 - L344 were not covered by tests
)

if (shouldShowE2eiCertificateRevokedDialog) {
E2EICertificateRevokedDialog(
onLogout = { logoutOptionsDialogState.show(LogoutOptionsDialogState(shouldWipeData = true)) },
onContinue = featureFlagNotificationViewModel::dismissE2EICertificateRevokedDialog,

Check warning on line 350 in app/src/main/kotlin/com/wire/android/ui/WireActivity.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/WireActivity.kt#L348-L350

Added lines #L348 - L350 were not covered by tests
)
}

e2EIRequired?.let {
E2EIRequiredDialog(
Expand Down
22 changes: 22 additions & 0 deletions app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.wire.android.feature.AccountSwitchUseCase
import com.wire.android.feature.SwitchAccountActions
import com.wire.android.feature.SwitchAccountParam
import com.wire.android.feature.SwitchAccountResult
import com.wire.android.migration.MigrationManager
import com.wire.android.services.ServicesManager
import com.wire.android.ui.authentication.devices.model.displayName
Expand Down Expand Up @@ -289,6 +290,27 @@
}
}

// TODO: needs to be covered with test once hard logout is validated to be used
fun doHardLogout(
clearUserData: (userId: UserId) -> Unit,
switchAccountActions: SwitchAccountActions
) {
viewModelScope.launch {

Check warning on line 298 in app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt#L298

Added line #L298 was not covered by tests
coreLogic.getGlobalScope().session.currentSession().takeIf {
it is CurrentSessionResult.Success

Check warning on line 300 in app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt#L300

Added line #L300 was not covered by tests
}?.let {
val currentUserId = (it as CurrentSessionResult.Success).accountInfo.userId
coreLogic.getSessionScope(currentUserId).logout(LogoutReason.SELF_HARD_LOGOUT)
clearUserData(currentUserId)
}
accountSwitch(SwitchAccountParam.TryToSwitchToNextAccount).also {

Check warning on line 306 in app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt#L302-L306

Added lines #L302 - L306 were not covered by tests
if (it == SwitchAccountResult.NoOtherAccountToSwitch) {
globalDataStore.clearAppLockPasscode()

Check warning on line 308 in app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt#L308

Added line #L308 was not covered by tests
}
}.callAction(switchAccountActions)
}
}

Check warning on line 312 in app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt#L310-L312

Added lines #L310 - L312 were not covered by tests

fun dismissNewClientsDialog(userId: UserId) {
globalAppState = globalAppState.copy(newClientDialog = null)
viewModelScope.launch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ fun WireLabelledCheckbox(
overflow: TextOverflow = TextOverflow.Visible,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
contentPadding: PaddingValues = PaddingValues(dimensions().spacing0x),
checkboxEnabled: Boolean = true,
modifier: Modifier = Modifier
) {
Row(
Expand All @@ -55,12 +56,17 @@ fun WireLabelledCheckbox(
.toggleable(
value = checked,
role = Role.Checkbox,
onValueChange = { onCheckClicked(!checked) }
onValueChange = {
if (checkboxEnabled) {
onCheckClicked(!checked)
}
}
)
.padding(contentPadding)
) {
Checkbox(
checked = checked,
enabled = checkboxEnabled,
onCheckedChange = null // null since we are handling the click on parent
)

Expand Down
50 changes: 40 additions & 10 deletions app/src/main/kotlin/com/wire/android/ui/home/E2EIDialogs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -363,81 +363,111 @@ private fun E2EIRenewNoSnoozeDialog(isLoading: Boolean, updateCertificate: () ->
)
}

@Composable
fun E2EICertificateRevokedDialog(
onLogout: () -> Unit,
onContinue: () -> Unit
) {
WireDialog(
title = stringResource(id = R.string.end_to_end_identity_certificate_revoked_dialog_title),
text = stringResource(id = R.string.end_to_end_identity_certificate_revoked_dialog_description),
onDismiss = onContinue,
optionButton1Properties = WireDialogButtonProperties(
onClick = onLogout,
text = stringResource(id = R.string.end_to_end_identity_certificate_revoked_dialog_button_logout),
type = WireDialogButtonType.Primary
),
optionButton2Properties = WireDialogButtonProperties(
onClick = onContinue,
text = stringResource(id = R.string.end_to_end_identity_certificate_revoked_dialog_button_continue),
type = WireDialogButtonType.Secondary,
),
buttonsHorizontalAlignment = false,
properties = DialogProperties(usePlatformDefaultWidth = false)
)
}

@PreviewMultipleThemes
@Composable
fun PreviewE2EICertificateRevokedDialog() {
E2EICertificateRevokedDialog({}, {})
}

@PreviewMultipleThemes
@Composable
fun previewE2EIdRequiredWithSnoozeDialog() {
fun PreviewE2EIdRequiredWithSnoozeDialog() {
WireTheme {
E2EIRequiredWithSnoozeDialog(false, {}) {}
}
}

@PreviewMultipleThemes
@Composable
fun previewE2EIdRequiredNoSnoozeDialog() {
fun PreviewE2EIdRequiredNoSnoozeDialog() {
WireTheme {
E2EIRequiredNoSnoozeDialog(false) {}
}
}

@PreviewMultipleThemes
@Composable
fun previewE2EIdRenewRequiredWithSnoozeDialog() {
fun PreviewE2EIdRenewRequiredWithSnoozeDialog() {
WireTheme {
E2EIRenewWithSnoozeDialog(false, {}) {}
}
}

@PreviewMultipleThemes
@Composable
fun previewE2EIdRenewRequiredNoSnoozeDialog() {
fun PreviewE2EIdRenewRequiredNoSnoozeDialog() {
WireTheme {
E2EIRenewNoSnoozeDialog(false) {}
}
}

@PreviewMultipleThemes
@Composable
fun previewE2EIdSnoozeDialog() {
fun PreviewE2EIdSnoozeDialog() {
WireTheme {
E2EISnoozeDialog(2.seconds) {}
}
}

@PreviewMultipleThemes
@Composable
fun previewE2EIRenewErrorDialogNoGracePeriod() {
fun PreviewE2EIRenewErrorDialogNoGracePeriod() {
WireTheme {
E2EIRenewErrorDialog(FeatureFlagState.E2EIRequired.NoGracePeriod.Renew, false, { }) {}
}
}

@PreviewMultipleThemes
@Composable
fun previewE2EIRenewErrorDialogWithGracePeriod() {
fun PreviewE2EIRenewErrorDialogWithGracePeriod() {
WireTheme {
E2EIRenewErrorDialog(FeatureFlagState.E2EIRequired.WithGracePeriod.Renew(2.days), false, { }) {}
}
}

@PreviewMultipleThemes
@Composable
fun previewE2EISuccessDialog() {
fun PreviewE2EISuccessDialog() {
WireTheme {
E2EISuccessDialog({ }) {}
}
}

@PreviewMultipleThemes
@Composable
fun previewE2EIRenewErrorNoSnoozeDialog() {
fun PreviewE2EIRenewErrorNoSnoozeDialog() {
WireTheme {
E2EIErrorNoSnoozeDialog(false) { }
}
}

@PreviewMultipleThemes
@Composable
fun previewE2EIRenewErrorWithSnoozeDialog() {
fun PreviewE2EIRenewErrorWithSnoozeDialog() {
WireTheme {
E2EIErrorWithSnoozeDialog(isE2EILoading = false, updateCertificate = {}) { }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ data class FeatureFlagState(
val isFileSharingEnabledState: Boolean = true,
val fileSharingRestrictedState: SharingRestrictedState? = null,
val shouldShowGuestRoomLinkDialog: Boolean = false,
val shouldShowE2eiCertificateRevokedDialog: Boolean = false,
val shouldShowTeamAppLockDialog: Boolean = false,
val isTeamAppLockEnabled: Boolean = false,
val isGuestRoomLinkEnabled: Boolean = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@
launch { setE2EIRequiredState(userId) }
launch { setTeamAppLockFeatureFlag(userId) }
launch { observeCallEndedBecauseOfConversationDegraded(userId) }
launch { observeShouldNotifyForRevokedCertificate(userId) }
}
}

Check warning on line 125 in app/src/main/kotlin/com/wire/android/ui/home/sync/FeatureFlagNotificationViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/home/sync/FeatureFlagNotificationViewModel.kt#L125

Added line #L125 was not covered by tests

private suspend fun observeShouldNotifyForRevokedCertificate(userId: UserId) {
coreLogic.getSessionScope(userId).observeShouldNotifyForRevokedCertificate().collect {
featureFlagState = featureFlagState.copy(shouldShowE2eiCertificateRevokedDialog = it)

Check warning on line 129 in app/src/main/kotlin/com/wire/android/ui/home/sync/FeatureFlagNotificationViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/home/sync/FeatureFlagNotificationViewModel.kt#L129

Added line #L129 was not covered by tests
}
}

Expand Down Expand Up @@ -232,6 +239,15 @@
}
}

fun dismissE2EICertificateRevokedDialog() {
featureFlagState = featureFlagState.copy(shouldShowE2eiCertificateRevokedDialog = false)
currentUserId?.let {
viewModelScope.launch {
coreLogic.getSessionScope(it).markNotifyForRevokedCertificateAsNotified()
}
}
}

fun dismissFileSharingDialog() {
featureFlagState = featureFlagState.copy(showFileSharingDialog = false)
viewModelScope.launch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ import com.wire.android.ui.common.visbility.VisibilityState
@Composable
fun LogoutOptionsDialog(
dialogState: VisibilityState<LogoutOptionsDialogState>,
logout: (Boolean) -> Unit
logout: (Boolean) -> Unit,
checkboxEnabled: Boolean = true
) {
VisibilityState(dialogState) { state ->
WireDialog(
Expand All @@ -61,15 +62,16 @@ fun LogoutOptionsDialog(
)
) {
WireLabelledCheckbox(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = dimensions().spacing16x)
.clip(RoundedCornerShape(size = dimensions().spacing4x)),
label = stringResource(R.string.dialog_logout_wipe_data_checkbox),
checked = state.shouldWipeData,
onCheckClicked = remember { { dialogState.show(state.copy(shouldWipeData = it)) } },
horizontalArrangement = Arrangement.Center,
contentPadding = PaddingValues(vertical = dimensions().spacing4x),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = dimensions().spacing16x)
.clip(RoundedCornerShape(size = dimensions().spacing4x))
checkboxEnabled = checkboxEnabled
)
}
}
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,10 @@
<string name="end_to_end_identity_renew_success_dialog_text">The certificate is updated and your device is verified.</string>
<string name="end_to_end_identity_renew_success_dialog_second_button">Certificate Details</string>
<string name="end_to_end_identity_ceritifcate">Certificate Details</string>
<string name="end_to_end_identity_certificate_revoked_dialog_title">End-to-end certificate revoked</string>
<string name="end_to_end_identity_certificate_revoked_dialog_description">Log out to reduce security risks. Then log in again, get a new certificate, and reset your password.\n\nIf you keep using this device, your conversations are no longer verified.</string>
<string name="end_to_end_identity_certificate_revoked_dialog_button_logout">Log out</string>
<string name="end_to_end_identity_certificate_revoked_dialog_button_continue">Continue Using This Device</string>
<!-- Record Audio -->
<string name="record_audio_start_label">Start Recording</string>
<string name="record_audio_recording_label">Recording Audio…</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import com.wire.kalium.logic.feature.session.CurrentSessionResult
import com.wire.kalium.logic.feature.user.E2EIRequiredResult
import com.wire.kalium.logic.feature.user.MarkEnablingE2EIAsNotifiedUseCase
import com.wire.kalium.logic.feature.user.MarkSelfDeletionStatusAsNotifiedUseCase
import com.wire.kalium.logic.feature.user.e2ei.MarkNotifyForRevokedCertificateAsNotifiedUseCase
import com.wire.kalium.logic.feature.user.guestroomlink.MarkGuestLinkFeatureFlagAsNotChangedUseCase
import io.mockk.MockKAnnotations
import io.mockk.coEvery
Expand Down Expand Up @@ -284,6 +285,19 @@ class FeatureFlagNotificationViewModelTest {
assertEquals(null, viewModel.featureFlagState.e2EIRequired)
}

@Test
fun givenADisplayedDialog_whenDismissingIt_thenInvokeMarkFileSharingStatusAsNotifiedUseCaseOnce() = runTest {
val (arrangement, viewModel) = Arrangement()
.withCurrentSessionsFlow(flowOf(CurrentSessionResult.Success(AccountInfo.Valid(UserId("value", "domain")))))
.arrange()
coEvery { arrangement.markNotifyForRevokedCertificateAsNotified() } returns Unit

viewModel.dismissE2EICertificateRevokedDialog()

assertEquals(false, viewModel.featureFlagState.shouldShowE2eiCertificateRevokedDialog)
coVerify(exactly = 1) { arrangement.markNotifyForRevokedCertificateAsNotified() }
}

private inner class Arrangement {

@MockK
Expand All @@ -310,6 +324,9 @@ class FeatureFlagNotificationViewModelTest {
@MockK
lateinit var globalDataStore: GlobalDataStore

@MockK
lateinit var markNotifyForRevokedCertificateAsNotified: MarkNotifyForRevokedCertificateAsNotifiedUseCase

val viewModel: FeatureFlagNotificationViewModel by lazy {
FeatureFlagNotificationViewModel(
coreLogic = coreLogic,
Expand All @@ -332,6 +349,9 @@ class FeatureFlagNotificationViewModelTest {
coEvery { coreLogic.getSessionScope(any()).observeGuestRoomLinkFeatureFlag.invoke() } returns flowOf()
coEvery { coreLogic.getSessionScope(any()).observeE2EIRequired.invoke() } returns flowOf()
coEvery { coreLogic.getSessionScope(any()).calls.observeEndCallDialog() } returns flowOf()
coEvery { coreLogic.getSessionScope(any()).observeShouldNotifyForRevokedCertificate() } returns flowOf()
every { coreLogic.getSessionScope(any()).markNotifyForRevokedCertificateAsNotified } returns
markNotifyForRevokedCertificateAsNotified
coEvery { ppLockTeamFeatureConfigObserver() } returns flowOf(null)
}

Expand Down
2 changes: 1 addition & 1 deletion kalium
Submodule kalium updated 36 files
+1 −0 cryptography/src/commonJvmAndroid/kotlin/com.wire.kalium.cryptography/MLSClientImpl.kt
+27 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/UserConfigRepository.kt
+7 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/client/ClientMapper.kt
+3 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/client/ClientModel.kt
+18 −3 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/client/remote/ClientRemoteRepository.kt
+30 −1 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/e2ei/E2EIRepository.kt
+23 −9 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt
+63 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/usecase/CheckRevocationListUseCase.kt
+5 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/usecase/EnrollE2EIUseCase.kt
+55 −0 ...nMain/kotlin/com/wire/kalium/logic/feature/legalhold/UpdateSelfClientCapabilityToLegalHoldConsentUseCase.kt
+14 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/MessageScope.kt
+122 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/composite/SendButtonMessageUseCase.kt
+35 −0 ...mmonMain/kotlin/com/wire/kalium/logic/feature/user/e2ei/MarkNotifyForRevokedCertificateAsNotifiedUseCase.kt
+47 −0 ...ommonMain/kotlin/com/wire/kalium/logic/feature/user/e2ei/ObserveShouldNotifyForRevokedCertificateUseCase.kt
+73 −45 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/client/ClientRemoteRepositoryTest.kt
+0 −4 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/client/ClientRepositoryTest.kt
+85 −0 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/E2EIRepositoryTest.kt
+120 −0 logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/EnrollE2EICertificateUseCaseTest.kt
+285 −0 logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/usecase/CheckRevocationListUseCaseTest.kt
+138 −0 ...t/kotlin/com/wire/kalium/logic/feature/legalhold/UpdateSelfClientCapabilityToLegalHoldConsentUseCaseTest.kt
+13 −3 logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/message/SendTextMessageCaseTest.kt
+165 −0 logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/message/composite/SendButtonMessageCaseTest.kt
+63 −0 ...Test/kotlin/com/wire/kalium/logic/feature/user/e2ei/MarkNotifyForRevokedCertificateAsNotifiedUseCaseTest.kt
+81 −0 ...nTest/kotlin/com/wire/kalium/logic/feature/user/e2ei/ObserveShouldNotifyForRevokedCertificateUseCaseTest.kt
+0 −12 logic/src/commonTest/kotlin/com/wire/kalium/logic/sync/receiver/UserEventReceiverTest.kt
+9 −1 network/src/commonMain/kotlin/com/wire/kalium/network/api/base/authenticated/client/ClientApi.kt
+6 −1 network/src/commonMain/kotlin/com/wire/kalium/network/api/base/authenticated/client/ClientRequest.kt
+16 −5 network/src/commonMain/kotlin/com/wire/kalium/network/api/base/unbound/acme/ACMEApi.kt
+20 −6 network/src/commonMain/kotlin/com/wire/kalium/network/api/v0/authenticated/ClientApiV0.kt
+25 −2 network/src/commonTest/kotlin/com/wire/kalium/api/common/ACMEApiTest.kt
+28 −2 network/src/commonTest/kotlin/com/wire/kalium/api/v0/user/client/ClientApiV0Test.kt
+2 −2 network/src/commonTest/kotlin/com/wire/kalium/model/UpdateClientRequestJson.kt
+11 −0 persistence/src/commonMain/kotlin/com/wire/kalium/persistence/config/UserConfigStorage.kt
+84 −7 persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/unread/UserConfigDAO.kt
+3 −2 testservice/src/main/kotlin/com/wire/kalium/testservice/api/v1/ConversationResources.kt
+12 −4 testservice/src/main/kotlin/com/wire/kalium/testservice/managed/ConversationRepository.kt
Loading