Account deactivation.

This commit is contained in:
Benoit Marty 2024-09-17 13:19:46 +02:00
parent b94a5c9c51
commit b87bec6228
29 changed files with 1071 additions and 9 deletions

View file

@ -38,6 +38,7 @@ fun InfoListOrganism(
iconTint: Color = LocalContentColor.current,
iconSize: Dp = 20.dp,
textStyle: TextStyle = LocalTextStyle.current,
textColor: Color = ElementTheme.colors.textPrimary,
verticalArrangement: Arrangement.Vertical = Arrangement.spacedBy(4.dp),
) {
Column(
@ -56,7 +57,7 @@ fun InfoListOrganism(
Text(
text = item.message,
style = textStyle,
color = ElementTheme.colors.textPrimary,
color = textColor,
)
},
icon = {

View file

@ -138,4 +138,7 @@ interface MatrixClient : Closeable {
/** Returns `true` if the current session is using native sliding sync, `false` if it's using a proxy. */
fun isUsingNativeSlidingSync(): Boolean
fun canDeactivateAccount(): Boolean
suspend fun deactivateAccount(password: String, eraseData: Boolean): Result<Unit>
}

View file

@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl
import io.element.android.libraries.androidutils.file.getSizeOfFiles
import io.element.android.libraries.androidutils.file.safeDelete
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.core.coroutine.childScope
import io.element.android.libraries.matrix.api.MatrixClient
@ -89,6 +90,8 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import org.matrix.rustcomponents.sdk.AuthData
import org.matrix.rustcomponents.sdk.AuthDataPasswordDetails
import org.matrix.rustcomponents.sdk.Client
import org.matrix.rustcomponents.sdk.ClientException
import org.matrix.rustcomponents.sdk.IgnoredUsersListener
@ -493,6 +496,46 @@ class RustMatrixClient(
return result
}
override fun canDeactivateAccount(): Boolean {
return runCatching {
client.canDeactivateAccount()
}
.getOrNull()
.orFalse()
}
override suspend fun deactivateAccount(password: String, eraseData: Boolean): Result<Unit> = withContext(sessionDispatcher) {
Timber.w("Deactivating account")
syncService.stop()
runCatching {
// First call without AuthData, should fail
val firstAttempt = runCatching {
client.deactivateAccount(
authData = null,
eraseData = eraseData,
)
}
if (firstAttempt.isFailure) {
Timber.w(firstAttempt.exceptionOrNull(), "Expected failure, try again")
// This is expected, try again with the password
client.deactivateAccount(
authData = AuthData.Password(
passwordDetails = AuthDataPasswordDetails(
identifier = sessionId.value,
password = password,
),
),
eraseData = eraseData,
)
}
close()
deleteSessionDirectory(deleteCryptoDb = true)
sessionStore.removeSession(sessionId.value)
}.onFailure {
Timber.e(it, "Failed to deactivate account")
}
}
override suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result<String?> = withContext(sessionDispatcher) {
val rustAction = action?.toRustAction()
runCatching {

View file

@ -79,6 +79,8 @@ class FakeMatrixClient(
private val clearCacheLambda: () -> Unit = { lambdaError() },
private val userIdServerNameLambda: () -> String = { lambdaError() },
private val getUrlLambda: (String) -> Result<String> = { lambdaError() },
private val canDeactivateAccountResult: () -> Boolean = { lambdaError() },
private val deactivateAccountResult: (String, Boolean) -> Result<Unit> = { _, _ -> lambdaError() },
var isNativeSlidingSyncSupportedLambda: suspend () -> Boolean = { true },
var isSlidingSyncProxySupportedLambda: suspend () -> Boolean = { true },
var isUsingNativeSlidingSyncLambda: () -> Boolean = { true },
@ -175,6 +177,12 @@ class FakeMatrixClient(
return logoutLambda(ignoreSdkError, userInitiated)
}
override fun canDeactivateAccount() = canDeactivateAccountResult()
override suspend fun deactivateAccount(password: String, eraseData: Boolean): Result<Unit> = simulateLongTask {
deactivateAccountResult(password, eraseData)
}
override fun close() = Unit
override suspend fun getUserProfile(): Result<MatrixUser> = simulateLongTask {

View file

@ -42,12 +42,15 @@
<string name="action_close">"Close"</string>
<string name="action_complete_verification">"Complete verification"</string>
<string name="action_confirm">"Confirm"</string>
<string name="action_confirm_password">"Confirm password"</string>
<string name="action_continue">"Continue"</string>
<string name="action_copy">"Copy"</string>
<string name="action_copy_link">"Copy link"</string>
<string name="action_copy_link_to_message">"Copy link to message"</string>
<string name="action_create">"Create"</string>
<string name="action_create_a_room">"Create a room"</string>
<string name="action_deactivate">"Deactivate"</string>
<string name="action_deactivate_account">"Deactivate account"</string>
<string name="action_decline">"Decline"</string>
<string name="action_delete_poll">"Delete Poll"</string>
<string name="action_disable">"Disable"</string>
@ -291,6 +294,8 @@ Reason: %1$s."</string>
<string name="screen_resolve_send_failure_unsigned_device_primary_button_title">"Send message anyway"</string>
<string name="screen_resolve_send_failure_unsigned_device_subtitle">"%1$s is using one or more unverified devices. You can send the message anyway, or you can cancel for now and try again later after %2$s has verified all their devices."</string>
<string name="screen_resolve_send_failure_unsigned_device_title">"Your message was not sent because %1$s has not verified all devices"</string>
<string name="screen_resolve_send_failure_you_unsigned_device_subtitle">"One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."</string>
<string name="screen_resolve_send_failure_you_unsigned_device_title">"Your message was not sent because you have not verified one or more of your devices"</string>
<string name="screen_room_details_pinned_events_row_title">"Pinned messages"</string>
<string name="screen_room_error_failed_processing_media">"Failed processing media to upload, please try again."</string>
<string name="screen_room_error_failed_retrieving_user_details">"Could not retrieve user details"</string>
@ -314,6 +319,7 @@ Reason: %1$s."</string>
<string name="screen_share_this_location_action">"Share this location"</string>
<string name="screen_timeline_item_menu_send_failure_changed_identity">"Message not sent because %1$ss verified identity has changed."</string>
<string name="screen_timeline_item_menu_send_failure_unsigned_device">"Message not sent because %1$s has not verified all devices."</string>
<string name="screen_timeline_item_menu_send_failure_you_unsigned_device">"Message not sent because you have not verified one or more of your devices."</string>
<string name="screen_view_location_title">"Location"</string>
<string name="settings_version_number">"Version: %1$s (%2$s)"</string>
<string name="test_language_identifier">"en"</string>