Skip to content
Open
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 @@ -42,6 +42,7 @@ import com.wire.kalium.logic.feature.user.GetSelfTeamIdUseCase
import com.wire.kalium.logic.feature.user.GetSelfUserUseCase
import com.wire.kalium.logic.feature.user.GetUserInfoUseCase
import com.wire.kalium.logic.feature.user.IsPasswordRequiredUseCase
import com.wire.kalium.logic.feature.user.IsPreventAdminlessGroupsEnabledUseCase
import com.wire.kalium.logic.feature.user.IsReadOnlyAccountUseCase
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
import com.wire.kalium.logic.feature.user.ObserveSelfUserWithTeamUseCase
Expand Down Expand Up @@ -161,6 +162,14 @@ class UserModule {
userScope: UserScope
): IsPasswordRequiredUseCase = userScope.isPasswordRequired

@ViewModelScoped
@Provides
fun provideIsPreventAdminlessGroupsEnabledUseCase(
@KaliumCoreLogic coreLogic: CoreLogic,
@CurrentAccount currentAccount: UserId,
): IsPreventAdminlessGroupsEnabledUseCase =
coreLogic.getSessionScope(currentAccount).isPreventAdminlessGroupsEnabled

@ViewModelScoped
@Provides
fun provideIsReadOnlyAccountUseCase(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.viewModelScope
import androidx.work.WorkManager
import com.wire.android.BuildConfig
import com.wire.android.appLogger
import com.wire.android.di.CurrentAccount
import com.wire.android.di.ViewModelScopedPreview
Expand Down Expand Up @@ -62,6 +61,7 @@ import com.wire.kalium.logic.feature.conversation.folder.RemoveConversationFromF
import com.wire.kalium.logic.feature.conversation.folder.RemoveConversationFromFolderUseCase
import com.wire.kalium.logic.feature.team.DeleteTeamConversationUseCase
import com.wire.kalium.logic.feature.team.Result
import com.wire.kalium.logic.feature.user.IsPreventAdminlessGroupsEnabledUseCase
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
import com.wire.kalium.util.DateTimeUtil
import dagger.hilt.android.lifecycle.HiltViewModel
Expand Down Expand Up @@ -124,6 +124,7 @@ class ConversationOptionsMenuViewModelImpl @Inject constructor(
private val markConversationAsDeletedLocally: MarkConversationAsDeletedLocallyUseCase,
private val leaveConversation: LeaveConversationUseCase,
private val checkConversationLeaveConditions: CheckConversationLeaveConditionsUseCase,
private val isPreventAdminlessGroupsEnabled: IsPreventAdminlessGroupsEnabledUseCase,
private val blockUser: BlockUserUseCase,
private val unblockUser: UnblockUserUseCase,
private val clearConversationContent: ClearConversationContentUseCase,
Expand Down Expand Up @@ -253,8 +254,8 @@ class ConversationOptionsMenuViewModelImpl @Inject constructor(
}

override fun onLeaveGroup(leaveGroupState: LeaveGroupDialogState) {
if (BuildConfig.ADMINLESS_GROUP_HANDLING_ENABLED) {
viewModelScope.launch {
viewModelScope.launch {
if (isPreventAdminlessGroupsEnabled()) {
when (val result = checkConversationLeaveConditions(leaveGroupState.conversationId)) {
CheckConversationLeaveConditionsUseCase.Result.Allow -> leaveGroupDialogState.show(leaveGroupState)
is CheckConversationLeaveConditionsUseCase.Result.DoNotAllow -> {
Expand All @@ -271,9 +272,9 @@ class ConversationOptionsMenuViewModelImpl @Inject constructor(
onMessage(HomeSnackBarMessage.LeaveConversationError)
}
}
} else {
leaveGroupDialogState.show(leaveGroupState)
}
} else {
leaveGroupDialogState.show(leaveGroupState)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class DebugFeatureFlagsViewModel @Inject constructor(
addFeature("Allowed Global Operations", allowedGlobalOperationsModel?.status, allowedGlobalOperationsModel)
addFeature("Wire Cells", cellsModel?.status)
addFeature("User Profile QR code", enableUserProfileQRCodeConfigModel?.status)
addFeature("Prevent Adminless Groups", preventAdminlessGroupsModel?.status)
add(
Feature(
name = "Channels",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.wire.android.assertIs
import com.wire.android.config.CoroutineTestExtension
import com.wire.android.config.TestDispatcherProvider
import com.wire.android.ui.home.HomeSnackBarMessage
import com.wire.android.ui.home.conversationslist.model.LeaveGroupDialogState
import com.wire.android.workmanager.worker.ConversationDeletionLocallyStatus
import com.wire.android.workmanager.worker.enqueueConversationDeletionLocally
import com.wire.kalium.common.error.CoreFailure
Expand Down Expand Up @@ -51,6 +52,7 @@ import com.wire.kalium.logic.feature.conversation.folder.RemoveConversationFromF
import com.wire.kalium.logic.feature.conversation.folder.RemoveConversationFromFolderUseCase
import com.wire.kalium.logic.feature.team.DeleteTeamConversationUseCase
import com.wire.kalium.logic.feature.team.Result
import com.wire.kalium.logic.feature.user.IsPreventAdminlessGroupsEnabledUseCase
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
import io.mockk.MockKAnnotations
import io.mockk.coEvery
Expand Down Expand Up @@ -589,6 +591,57 @@ class ConversationOptionsMenuViewModelTest {
}
}

@Test
fun `given preventAdminlessGroups disabled, when onLeaveGroup, then show simple leave dialog`() =
runTest(dispatcherProvider.main()) {
val (arrangement, viewModel) = Arrangement()
.withPreventAdminlessGroupsEnabled(false)
.arrange()

viewModel.onLeaveGroup(LeaveGroupDialogState(conversationId, "name"))

coVerify(exactly = 0) { arrangement.checkConversationLeaveConditions(any()) }
assertEquals(true, viewModel.leaveGroupDialogState.isVisible)
assertEquals(false, viewModel.leaveGroupOptionsDialogState.isVisible)
}

@Test
fun `given preventAdminlessGroups enabled and conditions allow, when onLeaveGroup, then show simple leave dialog`() =
runTest(dispatcherProvider.main()) {
val (arrangement, viewModel) = Arrangement()
.withPreventAdminlessGroupsEnabled(true)
.withCheckConversationLeaveConditions(CheckConversationLeaveConditionsUseCase.Result.Allow)
.arrange()

viewModel.onLeaveGroup(LeaveGroupDialogState(conversationId, "name"))

coVerify(exactly = 1) { arrangement.checkConversationLeaveConditions(conversationId) }
assertEquals(true, viewModel.leaveGroupDialogState.isVisible)
assertEquals(false, viewModel.leaveGroupOptionsDialogState.isVisible)
}

@Test
fun `given preventAdminlessGroups enabled and conditions error, when onLeaveGroup, then show snackbar error`() =
runTest(dispatcherProvider.main()) {
val (arrangement, viewModel) = Arrangement()
.withPreventAdminlessGroupsEnabled(true)
.withCheckConversationLeaveConditions(
CheckConversationLeaveConditionsUseCase.Result.Error(CoreFailure.Unknown(null))
)
.arrange()

viewModel.actions.test {
viewModel.onLeaveGroup(LeaveGroupDialogState(conversationId, "name"))

coVerify(exactly = 1) { arrangement.checkConversationLeaveConditions(conversationId) }
assertIs<ConversationOptionsMenuViewAction.Message>(awaitItem()).also {
assertIs<HomeSnackBarMessage.LeaveConversationError>(it.message)
}
assertEquals(false, viewModel.leaveGroupDialogState.isVisible)
cancelAndIgnoreRemainingEvents()
}
}

inner class Arrangement {
@MockK
lateinit var observeConversationDetails: ObserveConversationDetailsUseCase
Expand Down Expand Up @@ -623,6 +676,9 @@ class ConversationOptionsMenuViewModelTest {
@MockK
lateinit var checkConversationLeaveConditions: CheckConversationLeaveConditionsUseCase

@MockK
lateinit var isPreventAdminlessGroupsEnabled: IsPreventAdminlessGroupsEnabledUseCase

@MockK
lateinit var blockUser: BlockUserUseCase

Expand All @@ -638,6 +694,7 @@ class ConversationOptionsMenuViewModelTest {
init {
MockKAnnotations.init(this, relaxUnitFun = true)
mockkStatic("com.wire.android.workmanager.worker.DeleteConversationLocallyWorkerKt")
coEvery { isPreventAdminlessGroupsEnabled() } returns true
}

fun arrange() = this to ConversationOptionsMenuViewModelImpl(
Expand All @@ -653,6 +710,7 @@ class ConversationOptionsMenuViewModelTest {
markConversationAsDeletedLocally = markConversationAsDeletedLocally,
leaveConversation = leaveConversation,
checkConversationLeaveConditions = checkConversationLeaveConditions,
isPreventAdminlessGroupsEnabled = isPreventAdminlessGroupsEnabled,
blockUser = blockUser,
unblockUser = unblockUser,
clearConversationContent = clearConversationContent,
Expand Down Expand Up @@ -708,6 +766,14 @@ class ConversationOptionsMenuViewModelTest {
fun withClearConversationContent(result: ClearConversationContentUseCase.Result) = apply {
coEvery { clearConversationContent(any(), any()) } returns result
}

fun withPreventAdminlessGroupsEnabled(enabled: Boolean) = apply {
coEvery { isPreventAdminlessGroupsEnabled() } returns enabled
}

fun withCheckConversationLeaveConditions(result: CheckConversationLeaveConditionsUseCase.Result) = apply {
coEvery { checkConversationLeaveConditions(any()) } returns result
}
}

companion object {
Expand Down
4 changes: 1 addition & 3 deletions buildSrc/src/main/kotlin/customization/FeatureConfigs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,5 @@ enum class FeatureConfigs(val value: String, val configType: ConfigType) {

CALL_QUALITY_MENU_ENABLED("call_quality_menu_enabled", ConfigType.BOOLEAN),

CALL_REACTIONS_ENABLED("call_reactions_enabled", ConfigType.BOOLEAN),

ADMINLESS_GROUP_HANDLING_ENABLED("adminless_group_handling_enabled", ConfigType.BOOLEAN)
CALL_REACTIONS_ENABLED("call_reactions_enabled", ConfigType.BOOLEAN)
}
8 changes: 3 additions & 5 deletions default.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
"analytics_app_key": "8ffae535f1836ed5f58fd5c8a11c00eca07c5438",
"analytics_server_url": "https://wire.count.ly/",
"enable_new_registration": true,
"enforce_configuration_signature": true,
"enforce_configuration_signature": true
},
"internal": {
"application_id": "com.wire.internal",
Expand All @@ -88,8 +88,7 @@
"enforce_configuration_signature": true,
"use_strict_mls_filter": false,
"conversation_feeder_enabled": true,
"db_invalidation_control_enabled": false,
"adminless_group_handling_enabled": true
"db_invalidation_control_enabled": false
},
"fdroid": {
"application_id": "com.wire",
Expand Down Expand Up @@ -175,6 +174,5 @@
"enforce_configuration_signature": true,
"call_quality_menu_enabled": true,
"call_reactions_enabled": true,
"nomad_profiles_enabled": true,
"adminless_group_handling_enabled": false
"nomad_profiles_enabled": true
}
2 changes: 1 addition & 1 deletion kalium
Submodule kalium updated 19 files
+7 −0 core/data/src/commonMain/kotlin/com/wire/kalium/logic/data/featureConfig/FeatureConfigModel.kt
+9 −0 ...del/src/commonMain/kotlin/com/wire/kalium/network/api/authenticated/featureConfigs/FeatureConfigResponse.kt
+10 −0 data/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/UserConfigDAO.kt
+9 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/UserConfigRepository.kt
+12 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/event/Event.kt
+5 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/event/EventMapper.kt
+10 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/featureConfig/FeatureConfigMapper.kt
+12 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt
+3 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/featureConfig/SyncFeatureConfigsUseCase.kt
+47 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/user/IsPreventAdminlessGroupsEnabledUseCase.kt
+4 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/FeatureConfigEventReceiver.kt
+34 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/handler/PreventAdminlessGroupsConfigHandler.kt
+1 −0 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/event/FeatureConfigMapperTest.kt
+2 −0 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/featureConfig/FeatureConfigRepositoryTest.kt
+4 −0 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/featureConfig/FeatureConfigTest.kt
+2 −0 logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/featureConfig/SyncFeatureConfigsUseCaseTest.kt
+2 −0 logic/src/commonTest/kotlin/com/wire/kalium/logic/sync/receiver/FeatureConfigEventReceiverTest.kt
+1 −0 test/mocks/src/commonMain/kotlin/com/wire/kalium/mocks/responses/FeatureConfigJson.kt
+1 −0 test/mocks/src/commonMain/kotlin/com/wire/kalium/mocks/responses/FeatureConfigResponseJson.kt
Loading