Exclude tracker credentials in backups
This commit is contained in:
parent
72024aa44a
commit
730f3a6e52
@ -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()}\"")
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,19 +236,21 @@ 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()
|
||||||
when (value) {
|
.filterKeys { !Preference.isPrivate(it) }
|
||||||
is Int -> BackupPreference(key, IntPreferenceValue(value))
|
.mapNotNull { (key, value) ->
|
||||||
is Long -> BackupPreference(key, LongPreferenceValue(value))
|
when (value) {
|
||||||
is Float -> BackupPreference(key, FloatPreferenceValue(value))
|
is Int -> BackupPreference(key, IntPreferenceValue(value))
|
||||||
is String -> BackupPreference(key, StringPreferenceValue(value))
|
is Long -> BackupPreference(key, LongPreferenceValue(value))
|
||||||
is Boolean -> BackupPreference(key, BooleanPreferenceValue(value))
|
is Float -> BackupPreference(key, FloatPreferenceValue(value))
|
||||||
is Set<*> -> (value as? Set<String>)?.let {
|
is String -> BackupPreference(key, StringPreferenceValue(value))
|
||||||
BackupPreference(key, StringSetPreferenceValue(it))
|
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 {
|
internal suspend fun restoreExistingManga(manga: Manga, dbManga: Mangas): Manga {
|
||||||
|
@ -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(
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user