mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Exclude tracker credentials in backups
This commit is contained in:
		@@ -22,7 +22,7 @@ android {
 | 
			
		||||
    defaultConfig {
 | 
			
		||||
        applicationId = "eu.kanade.tachiyomi"
 | 
			
		||||
 | 
			
		||||
        versionCode = 106
 | 
			
		||||
        versionCode = 107
 | 
			
		||||
        versionName = "0.14.6"
 | 
			
		||||
 | 
			
		||||
        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.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")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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(
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user