Browse Source

Merge pull request #3745 from andybalaam/andybalaam/enable-identity-violation-notifs-unconditionally

Enable identity pinning violation notifications unconditionally
pull/3780/head
Benoit Marty 23 hours ago committed by GitHub
parent
commit
a772f000e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 7
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStatePresenter.kt
  2. 46
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStatePresenterTest.kt
  3. 16
      libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt

7
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStatePresenter.kt

@ -15,8 +15,6 @@ import androidx.compose.runtime.rememberCoroutineScope
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoom
@ -41,7 +39,6 @@ import javax.inject.Inject
class IdentityChangeStatePresenter @Inject constructor( class IdentityChangeStatePresenter @Inject constructor(
private val room: MatrixRoom, private val room: MatrixRoom,
private val encryptionService: EncryptionService, private val encryptionService: EncryptionService,
private val featureFlagService: FeatureFlagService,
) : Presenter<IdentityChangeState> { ) : Presenter<IdentityChangeState> {
@Composable @Composable
override fun present(): IdentityChangeState { override fun present(): IdentityChangeState {
@ -64,11 +61,7 @@ class IdentityChangeStatePresenter @Inject constructor(
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
private fun ProduceStateScope<PersistentList<RoomMemberIdentityStateChange>>.observeRoomMemberIdentityStateChange() { private fun ProduceStateScope<PersistentList<RoomMemberIdentityStateChange>>.observeRoomMemberIdentityStateChange() {
featureFlagService.isFeatureEnabledFlow(FeatureFlags.IdentityPinningViolationNotifications)
.filter { it }
.flatMapLatest {
room.syncUpdateFlow room.syncUpdateFlow
}
.filter { .filter {
// Room cannot become unencrypted, so we can just apply a filter here. // Room cannot become unencrypted, so we can just apply a filter here.
room.isEncrypted room.isEncrypted

46
features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStatePresenterTest.kt

@ -9,9 +9,6 @@ package io.element.android.features.messages.impl.crypto.identity
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
@ -68,43 +65,6 @@ class IdentityChangeStatePresenterTest {
} }
} }
@Test
fun `present - when the room emits identity change, but the feature is disabled, the presenter does not emit new state`() = runTest {
val room = FakeMatrixRoom(
isEncrypted = true,
)
val featureFlagService = FakeFeatureFlagService(
initialState = mapOf(
FeatureFlags.IdentityPinningViolationNotifications.key to false,
)
)
val presenter = createIdentityChangeStatePresenter(
room = room,
featureFlagService = featureFlagService,
)
presenter.test {
val initialState = awaitItem()
assertThat(initialState.roomMemberIdentityStateChanges).isEmpty()
room.emitIdentityStateChanges(
listOf(
IdentityStateChange(
userId = A_USER_ID_2,
identityState = IdentityState.PinViolation,
),
)
)
// No item emitted.
expectNoEvents()
// Enable the feature
featureFlagService.setFeatureEnabled(FeatureFlags.IdentityPinningViolationNotifications, true)
val finalItem = awaitItem()
assertThat(finalItem.roomMemberIdentityStateChanges).hasSize(1)
val value = finalItem.roomMemberIdentityStateChanges.first()
assertThat(value.identityRoomMember.userId).isEqualTo(A_USER_ID_2)
assertThat(value.identityState).isEqualTo(IdentityState.PinViolation)
}
}
@Test @Test
fun `present - when the clear room emits identity change, the presenter does not emit new state`() = runTest { fun `present - when the clear room emits identity change, the presenter does not emit new state`() = runTest {
val room = FakeMatrixRoom(isEncrypted = false) val room = FakeMatrixRoom(isEncrypted = false)
@ -188,16 +148,10 @@ class IdentityChangeStatePresenterTest {
private fun createIdentityChangeStatePresenter( private fun createIdentityChangeStatePresenter(
room: MatrixRoom = FakeMatrixRoom(), room: MatrixRoom = FakeMatrixRoom(),
encryptionService: EncryptionService = FakeEncryptionService(), encryptionService: EncryptionService = FakeEncryptionService(),
featureFlagService: FeatureFlagService = FakeFeatureFlagService(
initialState = mapOf(
FeatureFlags.IdentityPinningViolationNotifications.key to true,
)
),
): IdentityChangeStatePresenter { ): IdentityChangeStatePresenter {
return IdentityChangeStatePresenter( return IdentityChangeStatePresenter(
room = room, room = room,
encryptionService = encryptionService, encryptionService = encryptionService,
featureFlagService = featureFlagService,
) )
} }
} }

16
libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt

@ -9,7 +9,6 @@ package io.element.android.libraries.featureflag.api
import io.element.android.appconfig.OnBoardingConfig import io.element.android.appconfig.OnBoardingConfig
import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.core.meta.BuildType
/** /**
* To enable or disable a FeatureFlags, change the `defaultValue` value. * To enable or disable a FeatureFlags, change the `defaultValue` value.
@ -125,18 +124,5 @@ enum class FeatureFlags(
" You'll have to stop and re-open the app manually for that setting to take effect.", " You'll have to stop and re-open the app manually for that setting to take effect.",
defaultValue = { false }, defaultValue = { false },
isFinished = false, isFinished = false,
), )
IdentityPinningViolationNotifications(
key = "feature.identityPinningViolationNotifications",
title = "Identity pinning violation notifications",
description = null,
defaultValue = { buildMeta ->
when (buildMeta.buildType) {
// Do not enable this feature in release builds
BuildType.RELEASE -> false
else -> true
}
},
isFinished = false,
),
} }

Loading…
Cancel
Save