From 9f4164a287cc9521a4dc1a4d928b3d20cfbebc03 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Jan 2024 14:02:40 +0100 Subject: [PATCH] Migrate preferencesDataStoreFile to a file using a hash, to fix a crash if the userId is too long. --- libraries/pushstore/impl/build.gradle.kts | 1 + .../pushstore/impl/UserPushStoreDataStore.kt | 24 ++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/libraries/pushstore/impl/build.gradle.kts b/libraries/pushstore/impl/build.gradle.kts index 17e0268af1..9b01588090 100644 --- a/libraries/pushstore/impl/build.gradle.kts +++ b/libraries/pushstore/impl/build.gradle.kts @@ -34,6 +34,7 @@ anvil { dependencies { implementation(libs.dagger) implementation(projects.libraries.architecture) + implementation(projects.libraries.androidutils) implementation(projects.libraries.core) implementation(projects.libraries.matrix.api) implementation(projects.libraries.pushstore.api) diff --git a/libraries/pushstore/impl/src/main/kotlin/io/element/android/libraries/pushstore/impl/UserPushStoreDataStore.kt b/libraries/pushstore/impl/src/main/kotlin/io/element/android/libraries/pushstore/impl/UserPushStoreDataStore.kt index a79eafbbfd..506652f98f 100644 --- a/libraries/pushstore/impl/src/main/kotlin/io/element/android/libraries/pushstore/impl/UserPushStoreDataStore.kt +++ b/libraries/pushstore/impl/src/main/kotlin/io/element/android/libraries/pushstore/impl/UserPushStoreDataStore.kt @@ -23,12 +23,15 @@ import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore +import androidx.datastore.preferences.preferencesDataStoreFile +import io.element.android.libraries.androidutils.hash.hash import io.element.android.libraries.core.bool.orTrue import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.pushstore.api.UserPushStore import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map +import timber.log.Timber /** * Store data related to push about a user. @@ -37,7 +40,24 @@ class UserPushStoreDataStore( private val context: Context, userId: SessionId, ) : UserPushStore { - private val Context.dataStore: DataStore by preferencesDataStore(name = "push_store_$userId") + // Hash the sessionId to get ride of exotic chars and take only the first 16 chars. + // The risk of collision is not high. + private val preferenceName = "push_store_${userId.value.hash().take(16)}" + + init { + // Migrate legacy data. Previous file can be too long if the userId is too long. The userId can be up to 255 chars. + // Example of long file path, with `averylonguserid` replacing a very longer name + // /data/user/0/io.element.android.x.debug/files/datastore/push_store_@averylonguserid:example.org.preferences_pb + val legacyFile = context.preferencesDataStoreFile("push_store_$userId") + if (legacyFile.exists()) { + Timber.d("Migrating legacy push data store for $userId") + if (!legacyFile.renameTo(context.preferencesDataStoreFile(preferenceName))) { + Timber.w("Failed to migrate legacy push data store for $userId") + } + } + } + + private val Context.dataStore: DataStore by preferencesDataStore(name = preferenceName) private val pushProviderName = stringPreferencesKey("pushProviderName") private val currentPushKey = stringPreferencesKey("currentPushKey") private val notificationEnabled = booleanPreferencesKey("notificationEnabled") @@ -81,4 +101,6 @@ class UserPushStoreDataStore( it.clear() } } + + } }