Эх сурвалжийг харах

Exclude tracker credentials in backups

arkon 1 жил өмнө
parent
commit
730f3a6e52

+ 1 - 1
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()}\"")

+ 4 - 3
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")
     }
 }

+ 14 - 0
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
         }
 

+ 14 - 11
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<BackupPreference> {
         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<String>)?.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<String>)?.let {
+                        BackupPreference(key, StringSetPreferenceValue(it))
+                    }
+                    else -> null
                 }
-                else -> null
             }
-        }
     }
 
     internal suspend fun restoreExistingManga(manga: Manga, dbManga: Mangas): Manga {

+ 18 - 0
core/src/main/java/tachiyomi/core/preference/Preference.kt

@@ -21,6 +21,24 @@ interface Preference<T> {
     fun changes(): Flow<T>
 
     fun stateIn(scope: CoroutineScope): StateFlow<T>
+
+    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 <reified T, R : T> Preference<T>.getAndSet(crossinline block: (T) -> R) = set(

+ 1 - 1
i18n/src/main/res/values/strings.xml

@@ -504,7 +504,7 @@
     <string name="restoring_backup">Restoring backup</string>
     <string name="restoring_backup_error">Restoring backup failed</string>
     <string name="restoring_backup_canceled">Canceled restore</string>
-    <string name="backup_info">You should keep copies of backups in other places as well.</string>
+    <string name="backup_info">You should keep copies of backups in other places as well. Backups may contain sensitive data including any stored passwords; be careful if sharing.</string>
 
     <!-- Sync section -->
     <string name="syncing_library">Syncing library</string>