Exclude tracker credentials in backups

This commit is contained in:
arkon 2023-10-08 11:07:42 -04:00
parent 72024aa44a
commit 730f3a6e52
6 changed files with 52 additions and 16 deletions

View File

@ -22,7 +22,7 @@ android {
defaultConfig { defaultConfig {
applicationId = "eu.kanade.tachiyomi" applicationId = "eu.kanade.tachiyomi"
versionCode = 106 versionCode = 107
versionName = "0.14.6" versionName = "0.14.6"
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"") buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")

View File

@ -2,6 +2,7 @@ package eu.kanade.domain.track.service
import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.data.track.anilist.Anilist import eu.kanade.tachiyomi.data.track.anilist.Anilist
import tachiyomi.core.preference.Preference
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.preference.PreferenceStore
class TrackPreferences( class TrackPreferences(
@ -24,10 +25,10 @@ class TrackPreferences(
fun autoUpdateTrack() = preferenceStore.getBoolean("pref_auto_update_manga_sync_key", true) fun autoUpdateTrack() = preferenceStore.getBoolean("pref_auto_update_manga_sync_key", true)
companion object { 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")
} }
} }

View File

@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.isReleaseBuildType import eu.kanade.tachiyomi.util.system.isReleaseBuildType
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.system.workManager import eu.kanade.tachiyomi.util.system.workManager
import tachiyomi.core.preference.Preference
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.preference.TriState import tachiyomi.core.preference.TriState
import tachiyomi.core.preference.getAndSet import tachiyomi.core.preference.getAndSet
@ -381,6 +382,19 @@ object Migrations {
uiPreferences.relativeTime().set(false) 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 return true
} }

View File

@ -39,6 +39,7 @@ import logcat.LogPriority
import okio.buffer import okio.buffer
import okio.gzip import okio.gzip
import okio.sink import okio.sink
import tachiyomi.core.preference.Preference
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import tachiyomi.data.DatabaseHandler import tachiyomi.data.DatabaseHandler
@ -235,7 +236,9 @@ class BackupManager(
private fun backupAppPreferences(flags: Int): List<BackupPreference> { private fun backupAppPreferences(flags: Int): List<BackupPreference> {
if (flags and BACKUP_APP_PREFS_MASK != BACKUP_APP_PREFS) return emptyList() if (flags and BACKUP_APP_PREFS_MASK != BACKUP_APP_PREFS) return emptyList()
return preferenceStore.getAll().mapNotNull { (key, value) -> return preferenceStore.getAll()
.filterKeys { !Preference.isPrivate(it) }
.mapNotNull { (key, value) ->
when (value) { when (value) {
is Int -> BackupPreference(key, IntPreferenceValue(value)) is Int -> BackupPreference(key, IntPreferenceValue(value))
is Long -> BackupPreference(key, LongPreferenceValue(value)) is Long -> BackupPreference(key, LongPreferenceValue(value))

View File

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

View File

@ -504,7 +504,7 @@
<string name="restoring_backup">Restoring backup</string> <string name="restoring_backup">Restoring backup</string>
<string name="restoring_backup_error">Restoring backup failed</string> <string name="restoring_backup_error">Restoring backup failed</string>
<string name="restoring_backup_canceled">Canceled restore</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 --> <!-- Sync section -->
<string name="syncing_library">Syncing library</string> <string name="syncing_library">Syncing library</string>