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

[Identity reset] Remove instruction to reset identity on another client. #3355

Merged
merged 7 commits into from
Aug 29, 2024
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
@@ -1,5 +1,5 @@
appId: ${MAESTRO_APP_ID}
---
- extendedWaitUntil:
visible: "Confirm that it's you"
visible: "Confirm your identity"
timeout: 20000
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ interface SecureBackupEntryPoint : FeatureEntryPoint {
@Parcelize
data object EnterRecoveryKey : InitialTarget

@Parcelize
data object CreateNewRecoveryKey : InitialTarget

@Parcelize
data object ResetIdentity : InitialTarget
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.securebackup.api.SecureBackupEntryPoint
import io.element.android.features.securebackup.impl.createkey.CreateNewRecoveryKeyNode
import io.element.android.features.securebackup.impl.disable.SecureBackupDisableNode
import io.element.android.features.securebackup.impl.enable.SecureBackupEnableNode
import io.element.android.features.securebackup.impl.enter.SecureBackupEnterRecoveryKeyNode
Expand All @@ -52,7 +51,6 @@ class SecureBackupFlowNode @AssistedInject constructor(
initialElement = when (plugins.filterIsInstance<SecureBackupEntryPoint.Params>().first().initialElement) {
SecureBackupEntryPoint.InitialTarget.Root -> NavTarget.Root
SecureBackupEntryPoint.InitialTarget.EnterRecoveryKey -> NavTarget.EnterRecoveryKey
SecureBackupEntryPoint.InitialTarget.CreateNewRecoveryKey -> NavTarget.CreateNewRecoveryKey
is SecureBackupEntryPoint.InitialTarget.ResetIdentity -> NavTarget.ResetIdentity
},
savedStateMap = buildContext.savedStateMap,
Expand All @@ -79,9 +77,6 @@ class SecureBackupFlowNode @AssistedInject constructor(
@Parcelize
data object EnterRecoveryKey : NavTarget

@Parcelize
data object CreateNewRecoveryKey : NavTarget

@Parcelize
data object ResetIdentity : NavTarget
}
Expand Down Expand Up @@ -141,16 +136,9 @@ class SecureBackupFlowNode @AssistedInject constructor(
backstack.pop()
}
}

override fun onCreateNewRecoveryKey() {
backstack.push(NavTarget.CreateNewRecoveryKey)
}
}
createNode<SecureBackupEnterRecoveryKeyNode>(buildContext, plugins = listOf(callback))
}
NavTarget.CreateNewRecoveryKey -> {
createNode<CreateNewRecoveryKeyNode>(buildContext)
}
is NavTarget.ResetIdentity -> {
val callback = object : ResetIdentityFlowNode.Callback {
override fun onDone() {
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ class SecureBackupEnterRecoveryKeyNode @AssistedInject constructor(
) : Node(buildContext, plugins = plugins) {
interface Callback : Plugin {
fun onEnterRecoveryKeySuccess()
fun onCreateNewRecoveryKey()
}

private val callback = plugins<Callback>().first()
Expand All @@ -48,7 +47,6 @@ class SecureBackupEnterRecoveryKeyNode @AssistedInject constructor(
modifier = modifier,
onSuccess = callback::onEnterRecoveryKeySuccess,
onBackClick = ::navigateUp,
onCreateNewRecoveryKey = callback::onCreateNewRecoveryKey
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,13 @@ import io.element.android.libraries.designsystem.components.async.AsyncActionVie
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.ui.strings.CommonStrings

@Composable
fun SecureBackupEnterRecoveryKeyView(
state: SecureBackupEnterRecoveryKeyState,
onSuccess: () -> Unit,
onBackClick: () -> Unit,
onCreateNewRecoveryKey: () -> Unit,
modifier: Modifier = Modifier,
) {
AsyncActionView(
Expand All @@ -60,7 +58,7 @@ fun SecureBackupEnterRecoveryKeyView(
iconStyle = BigIcon.Style.Default(CompoundIcons.KeySolid()),
title = stringResource(id = R.string.screen_recovery_key_confirm_title),
subTitle = stringResource(id = R.string.screen_recovery_key_confirm_description),
buttons = { Buttons(state = state, onCreateRecoveryKey = onCreateNewRecoveryKey) }
buttons = { Buttons(state = state) }
) {
Content(state = state)
}
Expand All @@ -86,7 +84,6 @@ private fun Content(
@Composable
private fun ColumnScope.Buttons(
state: SecureBackupEnterRecoveryKeyState,
onCreateRecoveryKey: () -> Unit,
) {
Button(
text = stringResource(id = CommonStrings.action_continue),
Expand All @@ -97,12 +94,6 @@ private fun ColumnScope.Buttons(
state.eventSink.invoke(SecureBackupEnterRecoveryKeyEvents.Submit)
}
)
TextButton(
text = stringResource(id = R.string.screen_recovery_key_confirm_lost_recovery_key),
enabled = !state.submitAction.isLoading(),
modifier = Modifier.fillMaxWidth(),
onClick = onCreateRecoveryKey,
)
}

@PreviewsDayNight
Expand All @@ -114,6 +105,5 @@ internal fun SecureBackupEnterRecoveryKeyViewPreview(
state = state,
onSuccess = {},
onBackClick = {},
onCreateNewRecoveryKey = {},
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class ResetIdentityFlowManager @Inject constructor(
@SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope,
private val sessionVerificationService: SessionVerificationService,
) {
private val resetHandleFlow: MutableStateFlow<AsyncData<IdentityResetHandle>> = MutableStateFlow(AsyncData.Uninitialized)
val currentHandleFlow: StateFlow<AsyncData<IdentityResetHandle>> = resetHandleFlow
private val resetHandleFlow: MutableStateFlow<AsyncData<IdentityResetHandle?>> = MutableStateFlow(AsyncData.Uninitialized)
val currentHandleFlow: StateFlow<AsyncData<IdentityResetHandle?>> = resetHandleFlow
private var whenResetIsDoneWaitingJob: Job? = null

fun whenResetIsDone(block: () -> Unit) {
Expand All @@ -47,7 +47,7 @@ class ResetIdentityFlowManager @Inject constructor(
}
}

fun getResetHandle(): StateFlow<AsyncData<IdentityResetHandle>> {
fun getResetHandle(): StateFlow<AsyncData<IdentityResetHandle?>> {
return if (resetHandleFlow.value.isLoading() || resetHandleFlow.value.isSuccess()) {
resetHandleFlow
} else {
Expand All @@ -56,13 +56,11 @@ class ResetIdentityFlowManager @Inject constructor(
sessionCoroutineScope.launch {
matrixClient.encryptionService().startIdentityReset()
.onSuccess { handle ->
resetHandleFlow.value = if (handle != null) {
AsyncData.Success(handle)
} else {
AsyncData.Failure(IllegalStateException("Could not get a reset identity handle"))
}
resetHandleFlow.value = AsyncData.Success(handle)
}
.onFailure {
resetHandleFlow.value = AsyncData.Failure(it)
}
.onFailure { resetHandleFlow.value = AsyncData.Failure(it) }
}

resetHandleFlow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ class ResetIdentityFlowNode @AssistedInject constructor(
}
is AsyncData.Success -> {
when (val handle = state.data) {
null -> {
Timber.d("No reset handle return, the reset is done.")
}
is IdentityOidcResetHandle -> {
if (oidcEntryPoint.canUseCustomTab()) {
activity.openUrlInChromeCustomTab(null, false, handle.url)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<string name="screen_encryption_reset_bullet_2">"You will lose your existing message history"</string>
<string name="screen_encryption_reset_bullet_3">"You will need to verify all your existing devices and contacts again"</string>
<string name="screen_encryption_reset_footer">"Only reset your identity if you don’t have access to another signed-in device and you’ve lost your recovery key."</string>
<string name="screen_encryption_reset_subtitle">"If you’re not signed in to any other devices and you’ve lost your recovery key, then you’ll need to reset your identity to continue using the app. "</string>
<string name="screen_encryption_reset_subtitle">"If you’re not signed in to any other devices and you’ve lost your recovery key, then you’ll need to reset your identity to continue using the app."</string>
<string name="screen_encryption_reset_title">"Reset your identity in case you can’t confirm another way"</string>
<string name="screen_key_backup_disable_confirmation_action_turn_off">"Turn off"</string>
<string name="screen_key_backup_disable_confirmation_description">"You will lose your encrypted messages if you are signed out of all devices."</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,6 @@ class SecureBackupEnterRecoveryKeyViewTest {
recorder.assertSingle(SecureBackupEnterRecoveryKeyEvents.Submit)
}

@Test
@Config(qualifiers = "h1024dp")
fun `tapping on Lost your recovery key - calls onCreateNewRecoveryKey`() {
ensureCalledOnce { callback ->
rule.setSecureBackupEnterRecoveryKeyView(
aSecureBackupEnterRecoveryKeyState(),
onCreateNewRecoveryKey = callback,
)
rule.clickOn(R.string.screen_recovery_key_confirm_lost_recovery_key)
}
}

@Test
fun `when submit action succeeds - calls onDone`() {
ensureCalledOnce { callback ->
Expand All @@ -127,14 +115,12 @@ class SecureBackupEnterRecoveryKeyViewTest {
state: SecureBackupEnterRecoveryKeyState,
onDone: () -> Unit = EnsureNeverCalled(),
onBackClick: () -> Unit = EnsureNeverCalled(),
onCreateNewRecoveryKey: () -> Unit = EnsureNeverCalled(),
) {
setContent {
SecureBackupEnterRecoveryKeyView(
state = state,
onSuccess = onDone,
onBackClick = onBackClick,
onCreateNewRecoveryKey = onCreateNewRecoveryKey
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,16 @@ class ResetIdentityFlowManagerTest {
}

@Test
fun `getResetHandle - will fail if it receives a null reset handle`() = runTest {
fun `getResetHandle - will success if it receives a null reset handle`() = runTest {
val startResetLambda = lambdaRecorder<Result<IdentityResetHandle?>> { Result.success(null) }
val encryptionService = FakeEncryptionService(startIdentityResetLambda = startResetLambda)
val flowManager = createFlowManager(encryptionService = encryptionService)

flowManager.getResetHandle().test {
assertThat(awaitItem().isLoading()).isTrue()
assertThat(awaitItem().isFailure()).isTrue()
val finalItem = awaitItem()
assertThat(finalItem.isSuccess()).isTrue()
assertThat(finalItem.dataOrNull()).isNull()
startResetLambda.assertions().isCalledOnce()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<string name="screen_identity_confirmation_cannot_confirm">"Can\'t confirm?"</string>
<string name="screen_identity_confirmation_create_new_recovery_key">"Create a new recovery key"</string>
<string name="screen_identity_confirmation_subtitle">"Verify this device to set up secure messaging."</string>
<string name="screen_identity_confirmation_title">"Confirm that it\'s you"</string>
<string name="screen_identity_confirmation_title">"Confirm your identity"</string>
<string name="screen_identity_confirmation_use_another_device">"Use another device"</string>
<string name="screen_identity_confirmation_use_recovery_key">"Use recovery key"</string>
<string name="screen_identity_confirmed_subtitle">"Now you can read or send messages securely, and anyone you chat with can also trust this device."</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ interface EncryptionService {
/**
* A handle to reset the user's identity.
*/
interface IdentityResetHandle {
sealed interface IdentityResetHandle {
/**
* Cancel the reset process and drops the existing handle in the SDK.
*/
Expand Down
Loading
Loading