From f02e86fb50029487a1678d3e2fbe27142653fda3 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Wed, 19 Jan 2022 15:11:17 +0100 Subject: [PATCH] Confirm reload dialog if local modification #1196 --- .../activities/legacy/DatabaseLockActivity.kt | 8 +++-- .../database/action/DatabaseTaskProvider.kt | 14 ++++++++ .../keepass/database/element/Database.kt | 34 +++++++++++++++++++ app/src/main/res/values/strings.xml | 1 + 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/legacy/DatabaseLockActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/legacy/DatabaseLockActivity.kt index c2705d720..6b5e79d64 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/legacy/DatabaseLockActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/legacy/DatabaseLockActivity.kt @@ -93,7 +93,9 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(), } mDatabaseViewModel.reloadDatabase.observe(this) { fixDuplicateUuid -> - mDatabaseTaskProvider?.startDatabaseReload(fixDuplicateUuid) + mDatabaseTaskProvider?.askToStartDatabaseReload(mDatabase?.dataModifiedSinceLastLoading != false) { + mDatabaseTaskProvider?.startDatabaseReload(fixDuplicateUuid) + } } mDatabaseViewModel.saveName.observe(this) { @@ -266,7 +268,9 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(), } fun reloadDatabase() { - mDatabaseTaskProvider?.startDatabaseReload(false) + mDatabaseTaskProvider?.askToStartDatabaseReload(mDatabase?.dataModifiedSinceLastLoading != false) { + mDatabaseTaskProvider?.startDatabaseReload(false) + } } fun createEntry(newEntry: Entry, diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/DatabaseTaskProvider.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/DatabaseTaskProvider.kt index a5adea39d..c98a44eeb 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/DatabaseTaskProvider.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/DatabaseTaskProvider.kt @@ -27,6 +27,7 @@ import android.os.Bundle import android.os.IBinder import android.util.Log import android.widget.Toast +import androidx.appcompat.app.AlertDialog import androidx.fragment.app.FragmentActivity import androidx.lifecycle.lifecycleScope import com.kunzisoft.keepass.R @@ -369,6 +370,19 @@ class DatabaseTaskProvider { , ACTION_DATABASE_RELOAD_TASK) } + fun askToStartDatabaseReload(conditionToAsk: Boolean, approved: () -> Unit) { + if (conditionToAsk) { + AlertDialog.Builder(context) + .setMessage(R.string.warning_database_info_reloaded) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(android.R.string.ok) { _, _ -> + approved.invoke() + }.create().show() + } else { + approved.invoke() + } + } + fun startDatabaseAssignPassword(databaseUri: Uri, mainCredential: MainCredential) { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt index 8b0316d16..b3732bacc 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt @@ -94,6 +94,8 @@ class Database { */ var wasReloaded = false + var dataModifiedSinceLastLoading = false + var loadTimestamp: Long? = null private set @@ -213,6 +215,7 @@ class Database { set(name) { mDatabaseKDBX?.name = name mDatabaseKDBX?.nameChanged = DateInstant() + dataModifiedSinceLastLoading = true } val allowDescription: Boolean @@ -225,6 +228,7 @@ class Database { set(description) { mDatabaseKDBX?.description = description mDatabaseKDBX?.descriptionChanged = DateInstant() + dataModifiedSinceLastLoading = true } var defaultUsername: String @@ -235,6 +239,7 @@ class Database { mDatabaseKDB?.defaultUserName = username mDatabaseKDBX?.defaultUserName = username mDatabaseKDBX?.defaultUserNameChanged = DateInstant() + dataModifiedSinceLastLoading = true } var customColor: Int? @@ -255,6 +260,7 @@ class Database { ChromaUtil.getFormattedColorString(value, false) } mDatabaseKDBX?.settingsChanged = DateInstant() + dataModifiedSinceLastLoading = true } val allowOTP: Boolean @@ -279,6 +285,7 @@ class Database { mDatabaseKDBX?.compressionAlgorithm = it } mDatabaseKDBX?.settingsChanged = DateInstant() + dataModifiedSinceLastLoading = true } fun compressionForNewEntry(): Boolean { @@ -295,6 +302,7 @@ class Database { fun updateDataBinaryCompression(oldCompression: CompressionAlgorithm, newCompression: CompressionAlgorithm) { mDatabaseKDBX?.changeBinaryCompression(oldCompression, newCompression) + dataModifiedSinceLastLoading = true } val allowNoMasterKey: Boolean @@ -345,6 +353,7 @@ class Database { mDatabaseKDB?.numberKeyEncryptionRounds = numberRounds mDatabaseKDBX?.numberKeyEncryptionRounds = numberRounds mDatabaseKDBX?.settingsChanged = DateInstant() + dataModifiedSinceLastLoading = true } var memoryUsage: Long @@ -354,6 +363,7 @@ class Database { set(memory) { mDatabaseKDBX?.memoryUsage = memory mDatabaseKDBX?.settingsChanged = DateInstant() + dataModifiedSinceLastLoading = true } var parallelism: Long @@ -361,6 +371,7 @@ class Database { set(parallelism) { mDatabaseKDBX?.parallelism = parallelism mDatabaseKDBX?.settingsChanged = DateInstant() + dataModifiedSinceLastLoading = true } var masterKey: ByteArray @@ -369,6 +380,7 @@ class Database { mDatabaseKDB?.masterKey = masterKey mDatabaseKDBX?.masterKey = masterKey mDatabaseKDBX?.settingsChanged = DateInstant() + dataModifiedSinceLastLoading = true } var rootGroup: Group? @@ -420,6 +432,7 @@ class Database { set(value) { mDatabaseKDBX?.historyMaxItems = value mDatabaseKDBX?.settingsChanged = DateInstant() + dataModifiedSinceLastLoading = true } var historyMaxSize: Long @@ -429,6 +442,7 @@ class Database { set(value) { mDatabaseKDBX?.historyMaxSize = value mDatabaseKDBX?.settingsChanged = DateInstant() + dataModifiedSinceLastLoading = true } /** @@ -450,6 +464,7 @@ class Database { mDatabaseKDBX?.removeRecycleBin() } mDatabaseKDBX?.recycleBinChanged = DateInstant() + dataModifiedSinceLastLoading = true } val recycleBin: Group? @@ -471,6 +486,7 @@ class Database { mDatabaseKDBX?.removeRecycleBin() } mDatabaseKDBX?.recycleBinChanged = DateInstant() + dataModifiedSinceLastLoading = true } /** @@ -487,6 +503,7 @@ class Database { fun enableTemplates(enable: Boolean, templatesGroupName: String) { mDatabaseKDBX?.enableTemplatesGroup(enable, templatesGroupName) mDatabaseKDBX?.entryTemplatesGroupChanged = DateInstant() + dataModifiedSinceLastLoading = true } val templatesGroup: Group? @@ -505,6 +522,7 @@ class Database { mDatabaseKDBX?.removeTemplatesGroup() } mDatabaseKDBX?.entryTemplatesGroupChanged = DateInstant() + dataModifiedSinceLastLoading = true } val groupNamesNotAllowed: List @@ -531,6 +549,7 @@ class Database { this.fileUri = databaseUri // Set Database state this.loaded = true + this.dataModifiedSinceLastLoading = false } @Throws(LoadDatabaseException::class) @@ -641,6 +660,7 @@ class Database { throw LoadDatabaseException(e) } finally { keyFileInputStream?.close() + dataModifiedSinceLastLoading = false } } @@ -754,6 +774,8 @@ class Database { throw e } catch (e: Exception) { throw LoadDatabaseException(e) + } finally { + dataModifiedSinceLastLoading = false } } @@ -821,6 +843,7 @@ class Database { fun removeUnlinkedAttachments() { // No check in database KDB because unique attachment by entry mDatabaseKDBX?.removeUnlinkedAttachments(true) + dataModifiedSinceLastLoading = true } @Throws(DatabaseOutputException::class) @@ -881,6 +904,7 @@ class Database { } } this.fileUri = uri + this.dataModifiedSinceLastLoading = false } fun clearIndexesAndBinaries(filesDirectory: File? = null) { @@ -947,6 +971,7 @@ class Database { } fun createEntry(): Entry? { + dataModifiedSinceLastLoading = true mDatabaseKDB?.let { database -> return Entry(database.createEntry()).apply { nodeId = database.newEntryId() @@ -962,6 +987,7 @@ class Database { } fun createGroup(): Group? { + dataModifiedSinceLastLoading = true mDatabaseKDB?.let { database -> return Group(database.createGroup()).apply { setNodeId(database.newGroupId()) @@ -999,6 +1025,7 @@ class Database { } fun addEntryTo(entry: Entry, parent: Group) { + dataModifiedSinceLastLoading = true entry.entryKDB?.let { entryKDB -> mDatabaseKDB?.addEntryTo(entryKDB, parent.groupKDB) } @@ -1009,6 +1036,7 @@ class Database { } fun updateEntry(entry: Entry) { + dataModifiedSinceLastLoading = true entry.entryKDB?.let { entryKDB -> mDatabaseKDB?.updateEntry(entryKDB) } @@ -1018,6 +1046,7 @@ class Database { } fun removeEntryFrom(entry: Entry, parent: Group) { + dataModifiedSinceLastLoading = true entry.entryKDB?.let { entryKDB -> mDatabaseKDB?.removeEntryFrom(entryKDB, parent.groupKDB) } @@ -1028,6 +1057,7 @@ class Database { } fun addGroupTo(group: Group, parent: Group) { + dataModifiedSinceLastLoading = true group.groupKDB?.let { groupKDB -> mDatabaseKDB?.addGroupTo(groupKDB, parent.groupKDB) } @@ -1038,6 +1068,7 @@ class Database { } fun updateGroup(group: Group) { + dataModifiedSinceLastLoading = true group.groupKDB?.let { entryKDB -> mDatabaseKDB?.updateGroup(entryKDB) } @@ -1047,6 +1078,7 @@ class Database { } fun removeGroupFrom(group: Group, parent: Group) { + dataModifiedSinceLastLoading = true group.groupKDB?.let { groupKDB -> mDatabaseKDB?.removeGroupFrom(groupKDB, parent.groupKDB) } @@ -1085,6 +1117,7 @@ class Database { } fun deleteEntry(entry: Entry) { + dataModifiedSinceLastLoading = true entry.entryKDBX?.id?.let { entryId -> mDatabaseKDBX?.addDeletedObject(entryId) } @@ -1094,6 +1127,7 @@ class Database { } fun deleteGroup(group: Group) { + dataModifiedSinceLastLoading = true group.doForEachChildAndForIt( object : NodeHandler() { override fun operate(node: Entry): Boolean { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fc0dde2e9..6e5862a8a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -328,6 +328,7 @@ The content of the keyfile should never be changed, and in the best case, should contain randomly generated data. The information contained in your database file has been modified outside the app. Merge the data, overwrite the external modifications by saving the database or reload the database with the latest changes. + Reloading the database will delete the locally modified data. Access to the file revoked by the file manager, close the database and reopen it from its location. You have not allowed the app to use an exact alarm. As a result, the features requiring a timer will not be done with an exact time. Permission