From 730f3a6e5209197c7a026c36371545d5aef85851 Mon Sep 17 00:00:00 2001 From: arkon Date: Sun, 8 Oct 2023 11:07:42 -0400 Subject: [PATCH] Exclude tracker credentials in backups --- app/build.gradle.kts | 2 +- .../domain/track/service/TrackPreferences.kt | 7 +++--- .../java/eu/kanade/tachiyomi/Migrations.kt | 14 +++++++++++ .../tachiyomi/data/backup/BackupManager.kt | 25 +++++++++++-------- .../tachiyomi/core/preference/Preference.kt | 18 +++++++++++++ i18n/src/main/res/values/strings.xml | 2 +- 6 files changed, 52 insertions(+), 16 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5b9540486d..5f8b6166eb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -22,7 +22,7 @@ android { defaultConfig { applicationId = "eu.kanade.tachiyomi" - versionCode = 106 + versionCode = 107 versionName = "0.14.6" buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"") diff --git a/app/src/main/java/eu/kanade/domain/track/service/TrackPreferences.kt b/app/src/main/java/eu/kanade/domain/track/service/TrackPreferences.kt index 418d794b9c..c7fb47581c 100644 --- a/app/src/main/java/eu/kanade/domain/track/service/TrackPreferences.kt +++ b/app/src/main/java/eu/kanade/domain/track/service/TrackPreferences.kt @@ -2,6 +2,7 @@ package eu.kanade.domain.track.service import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.anilist.Anilist +import tachiyomi.core.preference.Preference import tachiyomi.core.preference.PreferenceStore class TrackPreferences( @@ -24,10 +25,10 @@ class TrackPreferences( fun autoUpdateTrack() = preferenceStore.getBoolean("pref_auto_update_manga_sync_key", true) companion object { - fun trackUsername(syncId: Long) = "pref_mangasync_username_$syncId" + fun trackUsername(syncId: Long) = Preference.privateKey("pref_mangasync_username_$syncId") - private fun trackPassword(syncId: Long) = "pref_mangasync_password_$syncId" + private fun trackPassword(syncId: Long) = Preference.privateKey("pref_mangasync_password_$syncId") - private fun trackToken(syncId: Long) = "track_token_$syncId" + private fun trackToken(syncId: Long) = Preference.privateKey("track_token_$syncId") } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt index c3b4db0699..f341e26a64 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt @@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.isReleaseBuildType import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.workManager +import tachiyomi.core.preference.Preference import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.preference.TriState import tachiyomi.core.preference.getAndSet @@ -381,6 +382,19 @@ object Migrations { uiPreferences.relativeTime().set(false) } } + if (oldVersion < 107) { + preferenceStore.getAll() + .filter { it.key.startsWith("pref_mangasync_") || it.key.startsWith("track_token_") } + .forEach { (key, value) -> + if (value is String) { + preferenceStore + .getString(Preference.privateKey(key)) + .set(value) + + preferenceStore.getString(key).delete() + } + } + } return true } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt index 9418781090..1ae5ec202d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt @@ -39,6 +39,7 @@ import logcat.LogPriority import okio.buffer import okio.gzip import okio.sink +import tachiyomi.core.preference.Preference import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.util.system.logcat import tachiyomi.data.DatabaseHandler @@ -235,19 +236,21 @@ class BackupManager( private fun backupAppPreferences(flags: Int): List { if (flags and BACKUP_APP_PREFS_MASK != BACKUP_APP_PREFS) return emptyList() - return preferenceStore.getAll().mapNotNull { (key, value) -> - when (value) { - is Int -> BackupPreference(key, IntPreferenceValue(value)) - is Long -> BackupPreference(key, LongPreferenceValue(value)) - is Float -> BackupPreference(key, FloatPreferenceValue(value)) - is String -> BackupPreference(key, StringPreferenceValue(value)) - is Boolean -> BackupPreference(key, BooleanPreferenceValue(value)) - is Set<*> -> (value as? Set)?.let { - BackupPreference(key, StringSetPreferenceValue(it)) + return preferenceStore.getAll() + .filterKeys { !Preference.isPrivate(it) } + .mapNotNull { (key, value) -> + when (value) { + is Int -> BackupPreference(key, IntPreferenceValue(value)) + is Long -> BackupPreference(key, LongPreferenceValue(value)) + is Float -> BackupPreference(key, FloatPreferenceValue(value)) + is String -> BackupPreference(key, StringPreferenceValue(value)) + is Boolean -> BackupPreference(key, BooleanPreferenceValue(value)) + is Set<*> -> (value as? Set)?.let { + BackupPreference(key, StringSetPreferenceValue(it)) + } + else -> null } - else -> null } - } } internal suspend fun restoreExistingManga(manga: Manga, dbManga: Mangas): Manga { diff --git a/core/src/main/java/tachiyomi/core/preference/Preference.kt b/core/src/main/java/tachiyomi/core/preference/Preference.kt index e76ea23d43..e10f6e7fe2 100644 --- a/core/src/main/java/tachiyomi/core/preference/Preference.kt +++ b/core/src/main/java/tachiyomi/core/preference/Preference.kt @@ -21,6 +21,24 @@ interface Preference { fun changes(): Flow fun stateIn(scope: CoroutineScope): StateFlow + + val isPrivate: Boolean + get() = key().startsWith(PRIVATE_PREFIX) + + companion object { + /** + * A preference that should not be exposed in places like backups. + */ + fun isPrivate(key: String): Boolean { + return key.startsWith(PRIVATE_PREFIX) + } + + fun privateKey(key: String): String { + return "${PRIVATE_PREFIX}$key" + } + + private const val PRIVATE_PREFIX = "__PRIVATE_" + } } inline fun Preference.getAndSet(crossinline block: (T) -> R) = set( diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index 410ec9ec2a..caebd66b76 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -504,7 +504,7 @@ Restoring backup Restoring backup failed Canceled restore - You should keep copies of backups in other places as well. + You should keep copies of backups in other places as well. Backups may contain sensitive data including any stored passwords; be careful if sharing. Syncing library