fix: Refactoring database actions

This commit is contained in:
J-Jamet 2023-05-14 23:38:08 +02:00
parent 939b319563
commit 4bd12b8a95
16 changed files with 215 additions and 194 deletions

View file

@ -1126,15 +1126,19 @@ class GroupActivity : DatabaseLockActivity(),
return true return true
} }
override fun onAskMainCredentialDialogPositiveClick(databaseUri: Uri?, override fun onAskMainCredentialDialogPositiveClick(
mainCredential: MainCredential) { databaseUri: Uri?,
mainCredential: MainCredential
) {
databaseUri?.let { databaseUri?.let {
mergeDatabaseFrom(it, mainCredential) mergeDatabaseFrom(it, mainCredential)
} }
} }
override fun onAskMainCredentialDialogNegativeClick(databaseUri: Uri?, override fun onAskMainCredentialDialogNegativeClick(
mainCredential: MainCredential) { } databaseUri: Uri?,
mainCredential: MainCredential
) { }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()

View file

@ -6,10 +6,10 @@ import androidx.activity.viewModels
import com.kunzisoft.keepass.activities.stylish.StylishActivity import com.kunzisoft.keepass.activities.stylish.StylishActivity
import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.database.MainCredential import com.kunzisoft.keepass.database.MainCredential
import com.kunzisoft.keepass.database.action.DatabaseTaskProvider import com.kunzisoft.keepass.services.DatabaseTaskProvider
import com.kunzisoft.keepass.model.CipherEncryptDatabase import com.kunzisoft.keepass.model.CipherEncryptDatabase
import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ActionRunnable
import com.kunzisoft.keepass.utils.UriUtil.getBinaryDir import com.kunzisoft.keepass.utils.UriHelper.getBinaryDir
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
abstract class DatabaseActivity: StylishActivity(), DatabaseRetrieval { abstract class DatabaseActivity: StylishActivity(), DatabaseRetrieval {
@ -63,16 +63,20 @@ abstract class DatabaseActivity: StylishActivity(), DatabaseRetrieval {
// optional method implementation // optional method implementation
} }
fun createDatabase(databaseUri: Uri, fun createDatabase(
mainCredential: MainCredential) { databaseUri: Uri,
mainCredential: MainCredential
) {
mDatabaseTaskProvider?.startDatabaseCreate(databaseUri, mainCredential) mDatabaseTaskProvider?.startDatabaseCreate(databaseUri, mainCredential)
} }
fun loadDatabase(databaseUri: Uri, fun loadDatabase(
mainCredential: MainCredential, databaseUri: Uri,
readOnly: Boolean, mainCredential: MainCredential,
cipherEncryptDatabase: CipherEncryptDatabase?, readOnly: Boolean,
fixDuplicateUuid: Boolean) { cipherEncryptDatabase: CipherEncryptDatabase?,
fixDuplicateUuid: Boolean
) {
mDatabaseTaskProvider?.startDatabaseLoad(databaseUri, mainCredential, readOnly, cipherEncryptDatabase, fixDuplicateUuid) mDatabaseTaskProvider?.startDatabaseLoad(databaseUri, mainCredential, readOnly, cipherEncryptDatabase, fixDuplicateUuid)
} }

View file

@ -36,7 +36,7 @@ import androidx.autofill.inline.v1.InlineSuggestionUi
import com.kunzisoft.keepass.R import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.AutofillLauncherActivity import com.kunzisoft.keepass.activities.AutofillLauncherActivity
import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.database.action.DatabaseTaskProvider import com.kunzisoft.keepass.services.DatabaseTaskProvider
import com.kunzisoft.keepass.database.helper.SearchHelper import com.kunzisoft.keepass.database.helper.SearchHelper
import com.kunzisoft.keepass.model.CreditCard import com.kunzisoft.keepass.model.CreditCard
import com.kunzisoft.keepass.model.RegisterInfo import com.kunzisoft.keepass.model.RegisterInfo

View file

@ -21,8 +21,6 @@ package com.kunzisoft.keepass.database.action
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.database.MainCredential import com.kunzisoft.keepass.database.MainCredential
import com.kunzisoft.keepass.hardware.HardwareKey import com.kunzisoft.keepass.hardware.HardwareKey
@ -32,8 +30,15 @@ open class AssignMainCredentialInDatabaseRunnable (
database: ContextualDatabase, database: ContextualDatabase,
protected val mDatabaseUri: Uri, protected val mDatabaseUri: Uri,
mainCredential: MainCredential, mainCredential: MainCredential,
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray,
) : SaveDatabaseRunnable(context, database, true, mainCredential, challengeResponseRetriever) { private val assignMainCredentialResult: ((Result) -> Unit)?
) : SaveDatabaseRunnable(
context,
database,
true,
mainCredential,
challengeResponseRetriever
) {
private var mBackupKey: ByteArray? = null private var mBackupKey: ByteArray? = null
@ -53,13 +58,6 @@ open class AssignMainCredentialInDatabaseRunnable (
override fun onFinishRun() { override fun onFinishRun() {
super.onFinishRun() super.onFinishRun()
// Erase the biometric
CipherDatabaseAction.getInstance(context)
.deleteByDatabaseUri(mDatabaseUri)
// Erase the register keyfile
FileDatabaseHistoryAction.getInstance(context)
.deleteKeyFileByDatabaseUri(mDatabaseUri)
if (!result.isSuccess) { if (!result.isSuccess) {
// Erase the current master key // Erase the current master key
erase(database.masterKey) erase(database.masterKey)
@ -67,6 +65,8 @@ open class AssignMainCredentialInDatabaseRunnable (
database.masterKey = it database.masterKey = it
} }
} }
assignMainCredentialResult?.invoke(result)
} }
/** /**

View file

@ -21,13 +21,10 @@ package com.kunzisoft.keepass.database.action
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import android.util.Log
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.database.MainCredential import com.kunzisoft.keepass.database.MainCredential
import com.kunzisoft.keepass.hardware.HardwareKey import com.kunzisoft.keepass.hardware.HardwareKey
import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.utils.UriHelper.getBinaryDir
import com.kunzisoft.keepass.utils.UriUtil.getBinaryDir
class CreateDatabaseRunnable( class CreateDatabaseRunnable(
context: Context, context: Context,
@ -39,7 +36,14 @@ class CreateDatabaseRunnable(
val mainCredential: MainCredential, val mainCredential: MainCredential,
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray, challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray,
private val createDatabaseResult: ((Result) -> Unit)? private val createDatabaseResult: ((Result) -> Unit)?
) : AssignMainCredentialInDatabaseRunnable(context, mDatabase, databaseUri, mainCredential, challengeResponseRetriever) { ) : AssignMainCredentialInDatabaseRunnable(
context,
mDatabase,
databaseUri,
mainCredential,
challengeResponseRetriever,
createDatabaseResult
) {
override fun onStartRun() { override fun onStartRun() {
try { try {
@ -56,27 +60,6 @@ class CreateDatabaseRunnable(
super.onStartRun() super.onStartRun()
} }
override fun onActionRun() {
super.onActionRun()
if (result.isSuccess) {
// Add database to recent files
if (PreferencesUtil.rememberDatabaseLocations(context)) {
FileDatabaseHistoryAction.getInstance(context.applicationContext)
.addOrUpdateDatabaseUri(
mDatabaseUri,
if (PreferencesUtil.rememberKeyFileLocations(context)) mainCredential.keyFileUri else null,
if (PreferencesUtil.rememberHardwareKey(context)) mainCredential.hardwareKey else null,
)
}
// Register the current time to init the lock timer
PreferencesUtil.saveCurrentTime(context)
} else {
Log.e("CreateDatabaseRunnable", "Unable to create the database")
}
}
override fun onFinishRun() { override fun onFinishRun() {
super.onFinishRun() super.onFinishRun()

View file

@ -21,20 +21,16 @@ package com.kunzisoft.keepass.database.action
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.database.MainCredential import com.kunzisoft.keepass.database.MainCredential
import com.kunzisoft.keepass.database.element.binary.BinaryData import com.kunzisoft.keepass.database.element.binary.BinaryData
import com.kunzisoft.keepass.database.exception.DatabaseInputException import com.kunzisoft.keepass.database.exception.DatabaseInputException
import com.kunzisoft.keepass.database.exception.UnknownDatabaseLocationException import com.kunzisoft.keepass.database.exception.UnknownDatabaseLocationException
import com.kunzisoft.keepass.hardware.HardwareKey import com.kunzisoft.keepass.hardware.HardwareKey
import com.kunzisoft.keepass.model.CipherEncryptDatabase
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ActionRunnable
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
import com.kunzisoft.keepass.utils.UriHelper.getBinaryDir
import com.kunzisoft.keepass.utils.UriHelper.getUriInputStream import com.kunzisoft.keepass.utils.UriHelper.getUriInputStream
import com.kunzisoft.keepass.utils.UriUtil.getBinaryDir
class LoadDatabaseRunnable( class LoadDatabaseRunnable(
private val context: Context, private val context: Context,
@ -43,10 +39,9 @@ class LoadDatabaseRunnable(
private val mMainCredential: MainCredential, private val mMainCredential: MainCredential,
private val mChallengeResponseRetriever: (hardwareKey: HardwareKey, seed: ByteArray?) -> ByteArray, private val mChallengeResponseRetriever: (hardwareKey: HardwareKey, seed: ByteArray?) -> ByteArray,
private val mReadonly: Boolean, private val mReadonly: Boolean,
private val mCipherEncryptDatabase: CipherEncryptDatabase?,
private val mFixDuplicateUUID: Boolean, private val mFixDuplicateUUID: Boolean,
private val progressTaskUpdater: ProgressTaskUpdater?, private val progressTaskUpdater: ProgressTaskUpdater?,
private val mLoadDatabaseResult: ((Result) -> Unit)?, private val loadDatabaseResult: ((Result) -> Unit)?,
) : ActionRunnable() { ) : ActionRunnable() {
private val binaryDir = context.getBinaryDir() private val binaryDir = context.getBinaryDir()
@ -78,31 +73,12 @@ class LoadDatabaseRunnable(
setError(e) setError(e)
} }
if (result.isSuccess) { if (!result.isSuccess) {
// Save keyFile in app database
if (PreferencesUtil.rememberDatabaseLocations(context)) {
FileDatabaseHistoryAction.getInstance(context)
.addOrUpdateDatabaseUri(
mDatabaseUri,
if (PreferencesUtil.rememberKeyFileLocations(context)) mMainCredential.keyFileUri else null,
if (PreferencesUtil.rememberHardwareKey(context)) mMainCredential.hardwareKey else null,
)
}
// Register the biometric
mCipherEncryptDatabase?.let { cipherDatabase ->
CipherDatabaseAction.getInstance(context)
.addOrUpdateCipherDatabase(cipherDatabase) // return value not called
}
// Register the current time to init the lock timer
PreferencesUtil.saveCurrentTime(context)
} else {
mDatabase.clearAndClose(binaryDir) mDatabase.clearAndClose(binaryDir)
} }
} }
override fun onFinishRun() { override fun onFinishRun() {
mLoadDatabaseResult?.invoke(result) loadDatabaseResult?.invoke(result)
} }
} }

View file

@ -27,7 +27,6 @@ import com.kunzisoft.keepass.database.element.binary.BinaryData
import com.kunzisoft.keepass.database.exception.DatabaseException import com.kunzisoft.keepass.database.exception.DatabaseException
import com.kunzisoft.keepass.database.exception.UnknownDatabaseLocationException import com.kunzisoft.keepass.database.exception.UnknownDatabaseLocationException
import com.kunzisoft.keepass.hardware.HardwareKey import com.kunzisoft.keepass.hardware.HardwareKey
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
import com.kunzisoft.keepass.utils.UriHelper.getUriInputStream import com.kunzisoft.keepass.utils.UriHelper.getUriInputStream
@ -40,7 +39,7 @@ class MergeDatabaseRunnable(
saveDatabase: Boolean, saveDatabase: Boolean,
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray, challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray,
private val progressTaskUpdater: ProgressTaskUpdater?, private val progressTaskUpdater: ProgressTaskUpdater?,
private val mLoadDatabaseResult: ((Result) -> Unit)? private val mergeDatabaseResult: ((Result) -> Unit)?
) : SaveDatabaseRunnable(context, database, saveDatabase, null, challengeResponseRetriever) { ) : SaveDatabaseRunnable(context, database, saveDatabase, null, challengeResponseRetriever) {
override fun onStartRun() { override fun onStartRun() {
@ -66,15 +65,11 @@ class MergeDatabaseRunnable(
setError(e) setError(e)
} }
if (result.isSuccess) {
// Register the current time to init the lock timer
PreferencesUtil.saveCurrentTime(context)
}
super.onActionRun() super.onActionRun()
} }
override fun onFinishRun() { override fun onFinishRun() {
super.onFinishRun() super.onFinishRun()
mLoadDatabaseResult?.invoke(result) mergeDatabaseResult?.invoke(result)
} }
} }

View file

@ -24,17 +24,16 @@ import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.database.element.binary.BinaryData import com.kunzisoft.keepass.database.element.binary.BinaryData
import com.kunzisoft.keepass.database.exception.DatabaseException import com.kunzisoft.keepass.database.exception.DatabaseException
import com.kunzisoft.keepass.database.exception.UnknownDatabaseLocationException import com.kunzisoft.keepass.database.exception.UnknownDatabaseLocationException
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ActionRunnable
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
import com.kunzisoft.keepass.utils.UriHelper.getBinaryDir
import com.kunzisoft.keepass.utils.UriHelper.getUriInputStream import com.kunzisoft.keepass.utils.UriHelper.getUriInputStream
import com.kunzisoft.keepass.utils.UriUtil.getBinaryDir
class ReloadDatabaseRunnable( class ReloadDatabaseRunnable(
private val context: Context, private val context: Context,
private val mDatabase: ContextualDatabase, private val mDatabase: ContextualDatabase,
private val progressTaskUpdater: ProgressTaskUpdater?, private val progressTaskUpdater: ProgressTaskUpdater?,
private val mLoadDatabaseResult: ((Result) -> Unit)? private val reloadDatabaseResult: ((Result) -> Unit)?
) : ActionRunnable() { ) : ActionRunnable() {
private val binaryDir = context.getBinaryDir() private val binaryDir = context.getBinaryDir()
@ -58,15 +57,12 @@ class ReloadDatabaseRunnable(
setError(e) setError(e)
} }
if (result.isSuccess) { if (!result.isSuccess) {
// Register the current time to init the lock timer
PreferencesUtil.saveCurrentTime(context)
} else {
mDatabase.clearAndClose(binaryDir) mDatabase.clearAndClose(binaryDir)
} }
} }
override fun onFinishRun() { override fun onFinishRun() {
mLoadDatabaseResult?.invoke(result) reloadDatabaseResult?.invoke(result)
} }
} }

View file

@ -50,7 +50,7 @@ open class SaveDatabaseRunnable(
// Build temp database file to avoid file corruption if error // Build temp database file to avoid file corruption if error
database.saveData( database.saveData(
cacheFile = File(context.cacheDir, databaseCopyUri.hashCode().toString()), cacheFile = File(context.cacheDir, databaseCopyUri.hashCode().toString()),
databaseOutputStream = context.contentResolver databaseOutputStream = contentResolver
.getUriOutputStream(databaseCopyUri ?: database.fileUri), .getUriOutputStream(databaseCopyUri ?: database.fileUri),
isNewLocation = databaseCopyUri == null, isNewLocation = databaseCopyUri == null,
mainCredential?.toMasterCredential(contentResolver), mainCredential?.toMasterCredential(contentResolver),

View file

@ -44,7 +44,7 @@ import com.kunzisoft.keepass.activities.EntrySelectionLauncherActivity
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.adapters.FieldsAdapter import com.kunzisoft.keepass.adapters.FieldsAdapter
import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.database.action.DatabaseTaskProvider import com.kunzisoft.keepass.services.DatabaseTaskProvider
import com.kunzisoft.keepass.database.element.Field import com.kunzisoft.keepass.database.element.Field
import com.kunzisoft.keepass.database.element.node.NodeIdUUID import com.kunzisoft.keepass.database.element.node.NodeIdUUID
import com.kunzisoft.keepass.database.helper.SearchHelper import com.kunzisoft.keepass.database.helper.SearchHelper

View file

@ -30,7 +30,6 @@ import android.util.Log
import androidx.core.app.ServiceCompat import androidx.core.app.ServiceCompat
import com.kunzisoft.keepass.R import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.database.action.DatabaseTaskProvider
import com.kunzisoft.keepass.database.element.Attachment import com.kunzisoft.keepass.database.element.Attachment
import com.kunzisoft.keepass.model.AttachmentState import com.kunzisoft.keepass.model.AttachmentState
import com.kunzisoft.keepass.model.EntryAttachmentState import com.kunzisoft.keepass.model.EntryAttachmentState

View file

@ -31,6 +31,8 @@ import androidx.annotation.StringRes
import androidx.media.app.NotificationCompat import androidx.media.app.NotificationCompat
import com.kunzisoft.keepass.R import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.GroupActivity import com.kunzisoft.keepass.activities.GroupActivity
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.database.MainCredential import com.kunzisoft.keepass.database.MainCredential
import com.kunzisoft.keepass.database.action.* import com.kunzisoft.keepass.database.action.*
@ -47,6 +49,7 @@ import com.kunzisoft.keepass.hardware.HardwareKey
import com.kunzisoft.keepass.hardware.HardwareKeyActivity import com.kunzisoft.keepass.hardware.HardwareKeyActivity
import com.kunzisoft.keepass.model.CipherEncryptDatabase import com.kunzisoft.keepass.model.CipherEncryptDatabase
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ActionRunnable
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
import com.kunzisoft.keepass.timeout.TimeoutHelper import com.kunzisoft.keepass.timeout.TimeoutHelper
@ -348,98 +351,99 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
// Build and launch the action // Build and launch the action
if (actionRunnable != null) { if (actionRunnable != null) {
mainScope.launch { mainScope.launch {
executeAction(this@DatabaseTaskNotificationService, executeAction(
{ this@DatabaseTaskNotificationService,
mActionRunning++ {
if (isMainAction) { mActionRunning++
TimeoutHelper.temporarilyDisableTimeout() if (isMainAction) {
TimeoutHelper.temporarilyDisableTimeout()
sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply { sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply {
putExtra(DATABASE_TASK_TITLE_KEY, mProgressMessage.titleId) putExtra(DATABASE_TASK_TITLE_KEY, mProgressMessage.titleId)
putExtra(DATABASE_TASK_MESSAGE_KEY, mProgressMessage.messageId) putExtra(DATABASE_TASK_MESSAGE_KEY, mProgressMessage.messageId)
putExtra(DATABASE_TASK_WARNING_KEY, mProgressMessage.warningId) putExtra(DATABASE_TASK_WARNING_KEY, mProgressMessage.warningId)
}) })
mActionTaskListeners.forEach { actionTaskListener ->
actionTaskListener.onActionStarted(
database,
mProgressMessage
)
}
}
},
{
actionRunnable
},
{ result ->
if (isMainAction) {
try {
mActionTaskListeners.forEach { actionTaskListener -> mActionTaskListeners.forEach { actionTaskListener ->
actionTaskListener.onActionStarted( mTaskRemovedRequested = false
actionTaskListener.onActionFinished(
database, database,
mProgressMessage intentAction!!,
result
) )
} }
} } finally {
}, // Save the database info before performing action
{ when (intentAction) {
actionRunnable ACTION_DATABASE_LOAD_TASK,
}, ACTION_DATABASE_MERGE_TASK,
{ result -> ACTION_DATABASE_RELOAD_TASK -> {
if (isMainAction) { saveDatabaseInfo()
try {
mActionTaskListeners.forEach { actionTaskListener ->
mTaskRemovedRequested = false
actionTaskListener.onActionFinished(
database,
intentAction!!,
result
)
} }
} finally {
// Save the database info before performing action
when (intentAction) {
ACTION_DATABASE_LOAD_TASK,
ACTION_DATABASE_MERGE_TASK,
ACTION_DATABASE_RELOAD_TASK -> {
saveDatabaseInfo()
}
}
val save = !database.isReadOnly
&& (intentAction == ACTION_DATABASE_SAVE
|| intent?.getBooleanExtra(
SAVE_DATABASE_KEY,
false
) == true)
// Save the database info after performing save action
if (save) {
database.fileUri?.let {
val newSnapFileDatabaseInfo =
SnapFileDatabaseInfo.fromFileDatabaseInfo(
FileDatabaseInfo(applicationContext, it)
)
mLastLocalSaveTime = System.currentTimeMillis()
mSnapFileDatabaseInfo = newSnapFileDatabaseInfo
}
}
removeIntentData(intent)
TimeoutHelper.releaseTemporarilyDisableTimeout()
// Stop service after save if user remove task
if (save && mTaskRemovedRequested) {
actionOnLock()
} else if (TimeoutHelper.checkTimeAndLockIfTimeout(this@DatabaseTaskNotificationService)) {
if (!database.loaded) {
stopSelf()
} else {
// Restart the service to open lock notification
try {
startService(
Intent(
applicationContext,
DatabaseTaskNotificationService::class.java
)
)
} catch (e: IllegalStateException) {
Log.w(
TAG,
"Cannot restart the database task service",
e
)
}
}
}
mTaskRemovedRequested = false
} }
sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION)) val save = !database.isReadOnly
&& (intentAction == ACTION_DATABASE_SAVE
|| intent?.getBooleanExtra(
SAVE_DATABASE_KEY,
false
) == true)
// Save the database info after performing save action
if (save) {
database.fileUri?.let {
val newSnapFileDatabaseInfo =
SnapFileDatabaseInfo.fromFileDatabaseInfo(
FileDatabaseInfo(applicationContext, it)
)
mLastLocalSaveTime = System.currentTimeMillis()
mSnapFileDatabaseInfo = newSnapFileDatabaseInfo
}
}
removeIntentData(intent)
TimeoutHelper.releaseTemporarilyDisableTimeout()
// Stop service after save if user remove task
if (save && mTaskRemovedRequested) {
actionOnLock()
} else if (TimeoutHelper.checkTimeAndLockIfTimeout(this@DatabaseTaskNotificationService)) {
if (!database.loaded) {
stopSelf()
} else {
// Restart the service to open lock notification
try {
startService(
Intent(
applicationContext,
DatabaseTaskNotificationService::class.java
)
)
} catch (e: IllegalStateException) {
Log.w(
TAG,
"Cannot restart the database task service",
e
)
}
}
}
mTaskRemovedRequested = false
} }
mActionRunning-- sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION))
} }
mActionRunning--
}
) )
} }
} }
@ -715,6 +719,25 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
retrieveResponseFromChallenge(hardwareKey, seed) retrieveResponseFromChallenge(hardwareKey, seed)
} }
) { result -> ) { result ->
afterAssignMainCredential(databaseUri)
if (result.isSuccess) {
// Add database to recent files
if (PreferencesUtil.rememberDatabaseLocations(applicationContext)) {
FileDatabaseHistoryAction.getInstance(applicationContext)
.addOrUpdateDatabaseUri(
databaseUri,
if (PreferencesUtil.rememberKeyFileLocations(applicationContext))
mainCredential.keyFileUri else null,
if (PreferencesUtil.rememberHardwareKey(applicationContext))
mainCredential.hardwareKey else null,
)
}
// Register the current time to init the lock timer
PreferencesUtil.saveCurrentTime(applicationContext)
} else {
Log.e(TAG, "Unable to create the database")
}
// Pass result to activity
result.data = Bundle().apply { result.data = Bundle().apply {
putParcelable(DATABASE_URI_KEY, databaseUri) putParcelable(DATABASE_URI_KEY, databaseUri)
putParcelable(MAIN_CREDENTIAL_KEY, mainCredential) putParcelable(MAIN_CREDENTIAL_KEY, mainCredential)
@ -754,10 +777,31 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
retrieveResponseFromChallenge(hardwareKey, seed) retrieveResponseFromChallenge(hardwareKey, seed)
}, },
readOnly, readOnly,
cipherEncryptDatabase,
intent.getBooleanExtra(FIX_DUPLICATE_UUID_KEY, false), intent.getBooleanExtra(FIX_DUPLICATE_UUID_KEY, false),
this this
) { result -> ) { result ->
if (result.isSuccess) {
// Save keyFile in app database
if (PreferencesUtil.rememberDatabaseLocations(applicationContext)) {
FileDatabaseHistoryAction.getInstance(applicationContext)
.addOrUpdateDatabaseUri(
databaseUri,
if (PreferencesUtil.rememberKeyFileLocations(applicationContext))
mainCredential.keyFileUri else null,
if (PreferencesUtil.rememberHardwareKey(applicationContext))
mainCredential.hardwareKey else null,
)
}
// Register the biometric
cipherEncryptDatabase?.let { cipherDatabase ->
CipherDatabaseAction.getInstance(applicationContext)
.addOrUpdateCipherDatabase(cipherDatabase) // return value not called
}
// Register the current time to init the lock timer
PreferencesUtil.saveCurrentTime(applicationContext)
}
// Add each info to reload database after thrown duplicate UUID exception // Add each info to reload database after thrown duplicate UUID exception
result.data = Bundle().apply { result.data = Bundle().apply {
putParcelable(DATABASE_URI_KEY, databaseUri) putParcelable(DATABASE_URI_KEY, databaseUri)
@ -798,6 +842,9 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
}, },
this this
) { result -> ) { result ->
if (result.isSuccess) {
PreferencesUtil.saveCurrentTime(applicationContext)
}
// No need to add each info to reload database // No need to add each info to reload database
result.data = Bundle() result.data = Bundle()
} }
@ -811,6 +858,9 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
database, database,
this this
) { result -> ) { result ->
if (result.isSuccess) {
PreferencesUtil.saveCurrentTime(applicationContext)
}
// No need to add each info to reload database // No need to add each info to reload database
result.data = Bundle() result.data = Bundle()
} }
@ -828,15 +878,27 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
this, this,
database, database,
databaseUri, databaseUri,
intent.getParcelableExtra(MAIN_CREDENTIAL_KEY) ?: MainCredential() intent.getParcelableExtra(MAIN_CREDENTIAL_KEY) ?: MainCredential(),
) { hardwareKey, seed -> { hardwareKey, seed ->
retrieveResponseFromChallenge(hardwareKey, seed) retrieveResponseFromChallenge(hardwareKey, seed)
}
) {
afterAssignMainCredential(databaseUri)
} }
} else { } else {
null null
} }
} }
private fun afterAssignMainCredential(databaseUri: Uri) {
// Erase the biometric
CipherDatabaseAction.getInstance(this)
.deleteByDatabaseUri(databaseUri)
// Erase the register keyfile
FileDatabaseHistoryAction.getInstance(this)
.deleteKeyFileByDatabaseUri(databaseUri)
}
private inner class AfterActionNodesRunnable : AfterActionNodesFinish() { private inner class AfterActionNodesRunnable : AfterActionNodesFinish() {
override fun onActionNodesFinish( override fun onActionNodesFinish(
result: ActionRunnable.Result, result: ActionRunnable.Result,

View file

@ -17,7 +17,7 @@
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>. * along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
package com.kunzisoft.keepass.database.action package com.kunzisoft.keepass.services
import android.app.AlertDialog import android.app.AlertDialog
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
@ -41,6 +41,7 @@ import com.kunzisoft.keepass.activities.dialogs.DatabaseChangedDialogFragment
import com.kunzisoft.keepass.activities.dialogs.DatabaseChangedDialogFragment.Companion.DATABASE_CHANGED_DIALOG_TAG import com.kunzisoft.keepass.activities.dialogs.DatabaseChangedDialogFragment.Companion.DATABASE_CHANGED_DIALOG_TAG
import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.database.MainCredential import com.kunzisoft.keepass.database.MainCredential
import com.kunzisoft.keepass.database.action.ProgressMessage
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
import com.kunzisoft.keepass.database.element.Entry import com.kunzisoft.keepass.database.element.Entry
@ -51,7 +52,6 @@ import com.kunzisoft.keepass.database.element.node.NodeId
import com.kunzisoft.keepass.database.element.node.Type import com.kunzisoft.keepass.database.element.node.Type
import com.kunzisoft.keepass.model.CipherEncryptDatabase import com.kunzisoft.keepass.model.CipherEncryptDatabase
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_CHALLENGE_RESPONDED import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_CHALLENGE_RESPONDED
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_ASSIGN_PASSWORD_TASK import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_ASSIGN_PASSWORD_TASK
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_COPY_NODES_TASK import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_COPY_NODES_TASK

View file

@ -36,7 +36,7 @@ import com.kunzisoft.keepass.services.ClipboardEntryNotificationService
import com.kunzisoft.keepass.services.KeyboardEntryNotificationService import com.kunzisoft.keepass.services.KeyboardEntryNotificationService
import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.timeout.TimeoutHelper import com.kunzisoft.keepass.timeout.TimeoutHelper
import com.kunzisoft.keepass.utils.UriUtil.getBinaryDir import com.kunzisoft.keepass.utils.UriHelper.getBinaryDir
import com.kunzisoft.keepass.utils.UriUtil.releaseAllUnnecessaryPermissionUris import com.kunzisoft.keepass.utils.UriUtil.releaseAllUnnecessaryPermissionUris
const val DATABASE_START_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_START_TASK_ACTION" const val DATABASE_START_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_START_TASK_ACTION"

View file

@ -267,13 +267,5 @@ object UriUtil {
} }
} }
fun Context.getBinaryDir(): File {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
this.applicationContext.noBackupFilesDir
} else {
this.applicationContext.filesDir
}
}
private const val TAG = "UriUtil" private const val TAG = "UriUtil"
} }

View file

@ -21,7 +21,9 @@ package com.kunzisoft.keepass.utils
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.ContentResolver import android.content.ContentResolver
import android.content.Context
import android.net.Uri import android.net.Uri
import android.os.Build
import android.util.Log import android.util.Log
import java.io.* import java.io.*
import java.util.* import java.util.*
@ -37,6 +39,14 @@ object UriHelper {
return Uri.decode(this) ?: "" return Uri.decode(this) ?: ""
} }
fun Context.getBinaryDir(): File {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
this.applicationContext.noBackupFilesDir
} else {
this.applicationContext.filesDir
}
}
@Throws(FileNotFoundException::class) @Throws(FileNotFoundException::class)
fun ContentResolver.getUriInputStream(fileUri: Uri?): InputStream? { fun ContentResolver.getUriInputStream(fileUri: Uri?): InputStream? {
if (fileUri == null) if (fileUri == null)