diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt index d7f149202..96cfc7bdb 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt @@ -69,7 +69,6 @@ import com.kunzisoft.keepass.database.element.Attachment import com.kunzisoft.keepass.database.element.DateInstant import com.kunzisoft.keepass.database.element.Entry import com.kunzisoft.keepass.database.element.Field -import com.kunzisoft.keepass.database.element.node.Node import com.kunzisoft.keepass.database.element.node.NodeId import com.kunzisoft.keepass.database.element.template.Template import com.kunzisoft.keepass.education.EntryEditActivityEducation @@ -81,9 +80,9 @@ import com.kunzisoft.keepass.model.SearchInfo import com.kunzisoft.keepass.otp.OtpElement import com.kunzisoft.keepass.services.AttachmentFileNotificationService import com.kunzisoft.keepass.services.ClipboardEntryNotificationService -import com.kunzisoft.keepass.services.DatabaseTaskNotificationService import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_ENTRY_TASK import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK +import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.getNewEntry import com.kunzisoft.keepass.services.KeyboardEntryNotificationService import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.tasks.ActionRunnable @@ -433,41 +432,35 @@ class EntryEditActivity : DatabaseLockActivity(), ACTION_DATABASE_UPDATE_ENTRY_TASK -> { try { if (result.isSuccess) { - var newNodes: List = ArrayList() - result.data?.getBundle(DatabaseTaskNotificationService.NEW_NODES_KEY)?.let { newNodesBundle -> - newNodes = DatabaseTaskNotificationService.getListNodesFromBundle(database, newNodesBundle) - } - if (newNodes.size == 1) { - (newNodes[0] as? Entry?)?.let { entry -> - EntrySelectionHelper.doSpecialAction( - intent = intent, - defaultAction = { - // Finish naturally - finishForEntryResult(entry) - }, - searchAction = { - // Nothing when search retrieved - }, - saveAction = { - entryValidatedForSave(entry) - }, - keyboardSelectionAction = { - entryValidatedForKeyboardSelection(database, entry) - }, - autofillSelectionAction = { _, _ -> - entryValidatedForAutofillSelection(database, entry) - }, - autofillRegistrationAction = { - entryValidatedForAutofillRegistration(entry) - }, - passkeySelectionAction = { - entryValidatedForPasskeySelection(database, entry) - }, - passkeyRegistrationAction = { - entryValidatedForPasskeyRegistration(database, entry) - } - ) - } + result.data?.getNewEntry(database)?.let { entry -> + EntrySelectionHelper.doSpecialAction( + intent = intent, + defaultAction = { + // Finish naturally + finishForEntryResult(entry) + }, + searchAction = { + // Nothing when search retrieved + }, + saveAction = { + entryValidatedForSave(entry) + }, + keyboardSelectionAction = { + entryValidatedForKeyboardSelection(database, entry) + }, + autofillSelectionAction = { _, _ -> + entryValidatedForAutofillSelection(database, entry) + }, + autofillRegistrationAction = { + entryValidatedForAutofillRegistration(entry) + }, + passkeySelectionAction = { + entryValidatedForPasskeySelection(database, entry) + }, + passkeyRegistrationAction = { + entryValidatedForPasskeyRegistration(database, entry) + } + ) } } } catch (e: Exception) { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index aa7051457..b534201ec 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -39,7 +39,6 @@ import android.view.ViewGroup import android.widget.ImageView import android.widget.ProgressBar import android.widget.TextView -import android.widget.Toast import androidx.activity.result.ActivityResultLauncher import androidx.activity.viewModels import androidx.annotation.RequiresApi @@ -93,8 +92,7 @@ import com.kunzisoft.keepass.model.GroupInfo import com.kunzisoft.keepass.model.RegisterInfo import com.kunzisoft.keepass.model.SearchInfo import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK -import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.NEW_NODES_KEY -import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.getListNodesFromBundle +import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.getNewEntry import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.settings.SettingsActivity import com.kunzisoft.keepass.tasks.ActionRunnable @@ -700,9 +698,7 @@ class GroupActivity : DatabaseLockActivity(), var entry: Entry? = null try { - result.data?.getBundle(NEW_NODES_KEY)?.let { newNodesBundle -> - entry = getListNodesFromBundle(database, newNodesBundle)[0] as Entry - } + entry = result.data?.getNewEntry(database) } catch (e: Exception) { Log.e(TAG, "Unable to retrieve entry action for selection", e) } diff --git a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/activity/PasskeyLauncherActivity.kt b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/activity/PasskeyLauncherActivity.kt index fbc5031f6..519bf2d11 100644 --- a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/activity/PasskeyLauncherActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/activity/PasskeyLauncherActivity.kt @@ -25,7 +25,7 @@ import android.content.Intent import android.os.Build import android.os.Bundle import android.util.Log -import android.widget.Toast +import android.view.View import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels @@ -35,7 +35,7 @@ import androidx.lifecycle.lifecycleScope import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.FileDatabaseSelectActivity import com.kunzisoft.keepass.activities.GroupActivity -import com.kunzisoft.keepass.activities.legacy.DatabaseModeActivity +import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.addSpecialMode import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.addTypeMode import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.setActivityResult @@ -50,11 +50,14 @@ import com.kunzisoft.keepass.credentialprovider.viewmodel.PasskeyLauncherViewMod import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.model.AppOrigin import com.kunzisoft.keepass.model.SearchInfo +import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK +import com.kunzisoft.keepass.tasks.ActionRunnable +import com.kunzisoft.keepass.view.toastError import kotlinx.coroutines.launch import java.util.UUID @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) -class PasskeyLauncherActivity : DatabaseModeActivity() { +class PasskeyLauncherActivity : DatabaseLockActivity() { private val passkeyLauncherViewModel: PasskeyLauncherViewModel by viewModels() @@ -67,7 +70,7 @@ class PasskeyLauncherActivity : DatabaseModeActivity() { this.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { passkeyLauncherViewModel.manageRegistrationResult(it) } - + override fun applyCustomStyle(): Boolean { return false } @@ -76,6 +79,10 @@ class PasskeyLauncherActivity : DatabaseModeActivity() { return false } + override fun finishActivityIfDatabaseNotLoaded(): Boolean { + return false + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) lifecycleScope.launch { @@ -89,14 +96,13 @@ class PasskeyLauncherActivity : DatabaseModeActivity() { } is PasskeyLauncherViewModel.UIState.ShowAppPrivilegedDialog -> { showAppPrivilegedDialog( - database = uiState.database, temptingApp = uiState.temptingApp ) } is PasskeyLauncherViewModel.UIState.ShowAppSignatureDialog -> { showAppSignatureDialog( - database = uiState.database, - temptingApp = uiState.temptingApp + temptingApp = uiState.temptingApp, + nodeId = uiState.nodeId ) } is PasskeyLauncherViewModel.UIState.SetActivityResult -> { @@ -107,7 +113,8 @@ class PasskeyLauncherActivity : DatabaseModeActivity() { ) } is PasskeyLauncherViewModel.UIState.ShowError -> { - showError(uiState.error) + toastError(uiState.error) + passkeyLauncherViewModel.cancelResult() } is PasskeyLauncherViewModel.UIState.LaunchGroupActivityForSelection -> { GroupActivity.launchForPasskeySelectionResult( @@ -142,6 +149,9 @@ class PasskeyLauncherActivity : DatabaseModeActivity() { typeMode = uiState.typeMode ) } + is PasskeyLauncherViewModel.UIState.UpdateEntry -> { + updateEntry(uiState.oldEntry, uiState.newEntry) + } } } } @@ -149,14 +159,30 @@ class PasskeyLauncherActivity : DatabaseModeActivity() { override fun onDatabaseRetrieved(database: ContextualDatabase?) { super.onDatabaseRetrieved(database) - passkeyLauncherViewModel.onDatabaseRetrieved(intent, mSpecialMode, database) + passkeyLauncherViewModel.launchPasskeyActionIfNeeded(intent, mSpecialMode, database) + } + + override fun onDatabaseActionFinished( + database: ContextualDatabase, + actionTask: String, + result: ActionRunnable.Result + ) { + super.onDatabaseActionFinished(database, actionTask, result) + when (actionTask) { + ACTION_DATABASE_UPDATE_ENTRY_TASK -> { + passkeyLauncherViewModel.autoSelectPasskey(result, database) + } + } + } + + override fun viewToInvalidateTimeout(): View? { + return null } /** * Display a dialog that asks the user to add an app to the list of privileged apps. */ private fun showAppPrivilegedDialog( - database: ContextualDatabase, temptingApp: AndroidPrivilegedApp ) { Log.w(javaClass.simpleName, "No privileged apps file found") @@ -177,7 +203,7 @@ class PasskeyLauncherActivity : DatabaseModeActivity() { passkeyLauncherViewModel.saveCustomPrivilegedApp( intent = intent, specialMode = mSpecialMode, - database = database, + database = mDatabase, temptingApp = temptingApp ) } @@ -194,8 +220,8 @@ class PasskeyLauncherActivity : DatabaseModeActivity() { * Display a dialog that asks the user to add an app signature in an existing passkey */ private fun showAppSignatureDialog( - database: ContextualDatabase, - temptingApp: AppOrigin + temptingApp: AppOrigin, + nodeId: UUID ) { AlertDialog.Builder(this@PasskeyLauncherActivity).apply { setTitle(getString(R.string.passkeys_missing_signature_app_ask_title)) @@ -203,7 +229,7 @@ class PasskeyLauncherActivity : DatabaseModeActivity() { .append( getString( R.string.passkeys_missing_signature_app_ask_message, - temptingApp.toName() + temptingApp.toString() ) ) .append("\n\n") @@ -212,10 +238,9 @@ class PasskeyLauncherActivity : DatabaseModeActivity() { ) setPositiveButton(android.R.string.ok) { _, _ -> passkeyLauncherViewModel.saveAppSignature( - intent = intent, - specialMode = mSpecialMode, - database = database, - temptingApp = temptingApp + database = mDatabase, + temptingApp = temptingApp, + nodeId = nodeId ) } setNegativeButton(android.R.string.cancel) { _, _ -> @@ -227,11 +252,6 @@ class PasskeyLauncherActivity : DatabaseModeActivity() { }.create().show() } - private fun showError(e: Throwable) { - Log.e(TAG, "Passkey launch error", e) - Toast.makeText(this, e.localizedMessage, Toast.LENGTH_LONG).show() - } - companion object { private val TAG = PasskeyLauncherActivity::class.java.name diff --git a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/passkey/data/PublicKeyCredentialUsageParameters.kt b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/passkey/data/PublicKeyCredentialUsageParameters.kt index c59541ad7..5d914bca8 100644 --- a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/passkey/data/PublicKeyCredentialUsageParameters.kt +++ b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/passkey/data/PublicKeyCredentialUsageParameters.kt @@ -24,5 +24,5 @@ import com.kunzisoft.keepass.model.AppOrigin data class PublicKeyCredentialUsageParameters( val publicKeyCredentialRequestOptions: PublicKeyCredentialRequestOptions, val clientDataResponse: ClientDataResponse, - val appOrigin: AppOrigin + var appOrigin: AppOrigin ) \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/passkey/util/PasskeyHelper.kt b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/passkey/util/PasskeyHelper.kt index 943469843..67da38e0a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/passkey/util/PasskeyHelper.kt +++ b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/passkey/util/PasskeyHelper.kt @@ -118,11 +118,12 @@ object PasskeyHelper { extras: Bundle? = null ) { try { - entryInfo.passkey?.let { + entryInfo.passkey?.let { passkey -> val mReplyIntent = Intent() Log.d(javaClass.name, "Success Passkey manual selection") - mReplyIntent.putExtra(EXTRA_PASSKEY, entryInfo.passkey) - mReplyIntent.putExtra(EXTRA_APP_ORIGIN, entryInfo.appOrigin) + mReplyIntent.addPasskey(passkey) + mReplyIntent.addAppOrigin(entryInfo.appOrigin) + mReplyIntent.addNodeId(entryInfo.id) extras?.let { mReplyIntent.putExtras(it) } @@ -157,6 +158,15 @@ object PasskeyHelper { }) } + /** + * Add the passkey to the intent + */ + fun Intent.addPasskey(passkey: Passkey?) { + passkey?.let { + putExtra(EXTRA_PASSKEY, passkey) + } + } + /** * Retrieve the passkey from the intent */ diff --git a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/viewmodel/PasskeyLauncherViewModel.kt b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/viewmodel/PasskeyLauncherViewModel.kt index 9ea28a923..217954fc1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/viewmodel/PasskeyLauncherViewModel.kt +++ b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/viewmodel/PasskeyLauncherViewModel.kt @@ -33,14 +33,18 @@ import com.kunzisoft.keepass.credentialprovider.passkey.util.PasskeyHelper.retri import com.kunzisoft.keepass.credentialprovider.passkey.util.PrivilegedAllowLists import com.kunzisoft.keepass.credentialprovider.passkey.util.PrivilegedAllowLists.saveCustomPrivilegedApps import com.kunzisoft.keepass.database.ContextualDatabase +import com.kunzisoft.keepass.database.element.Entry import com.kunzisoft.keepass.database.element.node.NodeIdUUID +import com.kunzisoft.keepass.database.exception.RegisterInReadOnlyDatabaseException import com.kunzisoft.keepass.database.helper.SearchHelper import com.kunzisoft.keepass.model.AppOrigin import com.kunzisoft.keepass.model.Passkey import com.kunzisoft.keepass.model.RegisterInfo import com.kunzisoft.keepass.model.SearchInfo import com.kunzisoft.keepass.model.SignatureNotFoundException +import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.getNewEntry import com.kunzisoft.keepass.settings.PreferencesUtil +import com.kunzisoft.keepass.tasks.ActionRunnable import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow @@ -63,7 +67,6 @@ class PasskeyLauncherViewModel(application: Application): AndroidViewModel(appli private var mLockDatabase: Boolean = true private var isResultLauncherRegistered: Boolean = false - private var currentDatabase: ContextualDatabase? = null private val _uiState = MutableStateFlow(UIState.Loading) val uiState: StateFlow = _uiState @@ -74,31 +77,31 @@ class PasskeyLauncherViewModel(application: Application): AndroidViewModel(appli } fun showAppPrivilegedDialog( - database: ContextualDatabase, temptingApp: AndroidPrivilegedApp ) { - _uiState.value = UIState.ShowAppPrivilegedDialog(database, temptingApp) + _uiState.value = UIState.ShowAppPrivilegedDialog(temptingApp) } fun showAppSignatureDialog( - database: ContextualDatabase, - temptingApp: AppOrigin + temptingApp: AppOrigin, + nodeId: UUID ) { - _uiState.value = UIState.ShowAppSignatureDialog(database, temptingApp) + _uiState.value = UIState.ShowAppSignatureDialog(temptingApp, nodeId) } fun showError(error: Throwable) { + Log.e(TAG, "Error on passkey launch", error) _uiState.value = UIState.ShowError(error) } fun saveCustomPrivilegedApp( intent: Intent, specialMode: SpecialMode, - database: ContextualDatabase, + database: ContextualDatabase?, temptingApp: AndroidPrivilegedApp ) { viewModelScope.launch(CoroutineExceptionHandler { _, e -> - cancelResult() + showError(e) }) { saveCustomPrivilegedApps( context = getApplication(), @@ -113,20 +116,39 @@ class PasskeyLauncherViewModel(application: Application): AndroidViewModel(appli } fun saveAppSignature( - intent: Intent, - specialMode: SpecialMode, - database: ContextualDatabase, - temptingApp: AppOrigin + database: ContextualDatabase?, + temptingApp: AppOrigin, + nodeId: UUID ) { viewModelScope.launch(CoroutineExceptionHandler { _, e -> - cancelResult() + showError(e) }) { - // TODO Save app signature + // Update the entry with app signature + val entry = database + ?.getEntryById(NodeIdUUID(nodeId)) + ?: throw GetCredentialUnknownException( + "No passkey with nodeId $nodeId found" + ) + if (database.isReadOnly) + throw RegisterInReadOnlyDatabaseException() + val newEntry = Entry(entry) + val entryInfo = newEntry.getEntryInfo( + database, + raw = true, + removeTemplateConfiguration = false + ) + entryInfo.saveAppOrigin(database, temptingApp) + newEntry.setEntryInfo(database, entryInfo) + _uiState.value = UIState.UpdateEntry( + oldEntry = entry, + newEntry = newEntry + ) } } fun setResult(intent: Intent) { - currentDatabase = null + // Remove the launcher register + isResultLauncherRegistered = false _uiState.value = UIState.SetActivityResult( lockDatabase = mLockDatabase, resultCode = RESULT_OK, @@ -135,26 +157,25 @@ class PasskeyLauncherViewModel(application: Application): AndroidViewModel(appli } fun cancelResult() { - currentDatabase = null + isResultLauncherRegistered = false _uiState.value = UIState.SetActivityResult( lockDatabase = mLockDatabase, resultCode = RESULT_CANCELED ) } - fun onDatabaseRetrieved( + fun launchPasskeyActionIfNeeded( intent: Intent, specialMode: SpecialMode, database: ContextualDatabase? ) { - currentDatabase = database if (isResultLauncherRegistered.not()) { + isResultLauncherRegistered = true viewModelScope.launch(CoroutineExceptionHandler { _, e -> - if (e is PrivilegedAllowLists.PrivilegedException && database != null) { - showAppPrivilegedDialog(database, e.temptingApp) + if (e is PrivilegedAllowLists.PrivilegedException) { + showAppPrivilegedDialog(e.temptingApp) } else { showError(e) - cancelResult() } }) { launchPasskeyAction(intent, specialMode, database) @@ -170,7 +191,6 @@ class PasskeyLauncherViewModel(application: Application): AndroidViewModel(appli specialMode: SpecialMode, database: ContextualDatabase? ) { - isResultLauncherRegistered = true val searchInfo = intent.retrieveSearchInfo() ?: SearchInfo() val appOrigin = intent.retrieveAppOrigin() ?: AppOrigin(verified = false) val nodeId = intent.retrieveNodeId() @@ -257,6 +277,27 @@ class PasskeyLauncherViewModel(application: Application): AndroidViewModel(appli } } + fun autoSelectPasskey( + result: ActionRunnable.Result, + database: ContextualDatabase + ) { + viewModelScope.launch(CoroutineExceptionHandler { _, e -> + showError(e) + }) { + if (result.isSuccess) { + val entry = result.data?.getNewEntry(database) + ?: throw IOException("No passkey entry found") + autoSelectPasskeyAndSetResult( + database = database, + nodeId = entry.nodeId.id, + appOrigin = entry.getAppOrigin() + ?: throw IOException("No App origin found") + ) + } else throw result.exception + ?: IOException("Unable to auto select passkey") + } + } + private fun autoSelectPasskeyAndSetResult( database: ContextualDatabase?, nodeId: UUID, @@ -268,7 +309,7 @@ class PasskeyLauncherViewModel(application: Application): AndroidViewModel(appli ?.getEntryById(NodeIdUUID(nodeId)) ?.getEntryInfo(database) ?.passkey - ?: throw GetCredentialUnknownException( + ?: throw IOException( "No passkey with nodeId $nodeId found" ) // Build the response @@ -292,7 +333,7 @@ class PasskeyLauncherViewModel(application: Application): AndroidViewModel(appli setResult(result) } catch (e: SignatureNotFoundException) { // Request the dialog if signature exception - showAppSignatureDialog(database, e.temptingApp) + showAppSignatureDialog(e.temptingApp, nodeId) } } ?: throw IOException("Usage parameters is null") } @@ -337,21 +378,18 @@ class PasskeyLauncherViewModel(application: Application): AndroidViewModel(appli } setResult(responseIntent) } catch (e: SignatureNotFoundException) { - currentDatabase?.let { - showAppSignatureDialog(it, e.temptingApp) - } + intent?.retrieveNodeId()?.let { nodeId -> + showAppSignatureDialog(e.temptingApp, nodeId) + } ?: cancelResult() } catch (e: Exception) { Log.e(TAG, "Unable to create selection response for passkey", e) showError(e) - cancelResult() } } RESULT_CANCELED -> { cancelResult() } } - // Remove the launcher register - isResultLauncherRegistered = false } // ------------- @@ -474,12 +512,11 @@ class PasskeyLauncherViewModel(application: Application): AndroidViewModel(appli sealed class UIState { object Loading : UIState() data class ShowAppPrivilegedDialog( - val database: ContextualDatabase, val temptingApp: AndroidPrivilegedApp ): UIState() data class ShowAppSignatureDialog( - val database: ContextualDatabase, - val temptingApp: AppOrigin + val temptingApp: AppOrigin, + val nodeId: UUID ): UIState() data class LaunchGroupActivityForSelection( val database: ContextualDatabase @@ -504,6 +541,10 @@ class PasskeyLauncherViewModel(application: Application): AndroidViewModel(appli data class ShowError( val error: Throwable ): UIState() + data class UpdateEntry( + val oldEntry: Entry, + val newEntry: Entry + ): UIState() } companion object { diff --git a/app/src/main/java/com/kunzisoft/keepass/services/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/services/DatabaseTaskNotificationService.kt index 4cd6ee6da..85942603f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/services/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/services/DatabaseTaskNotificationService.kt @@ -1385,6 +1385,15 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress return nodesAction } + fun Bundle.getNewEntry(database: ContextualDatabase): Entry? { + getBundle(NEW_NODES_KEY) + ?.getParcelableList>(ENTRIES_ID_KEY) + ?.get(0)?.let { + return database.getEntryById(it) + } + return null + } + fun getBundleFromListNodes(nodes: List): Bundle { val groupsId = mutableListOf>() val entriesId = mutableListOf>() diff --git a/database/src/main/java/com/kunzisoft/keepass/model/AppOrigin.kt b/database/src/main/java/com/kunzisoft/keepass/model/AppOrigin.kt index 435cee70b..9bc902299 100644 --- a/database/src/main/java/com/kunzisoft/keepass/model/AppOrigin.kt +++ b/database/src/main/java/com/kunzisoft/keepass/model/AppOrigin.kt @@ -89,6 +89,14 @@ data class AppOrigin( } else null } + override fun toString(): String { + return if (androidOrigins.isNotEmpty()) { + androidOrigins.first().toString() + } else if (webOrigins.isNotEmpty()) { + webOrigins.first().toString() + } else super.toString() + } + companion object { private val TAG = AppOrigin::class.java.simpleName diff --git a/database/src/main/java/com/kunzisoft/keepass/model/EntryInfo.kt b/database/src/main/java/com/kunzisoft/keepass/model/EntryInfo.kt index 14a881300..a696cd61a 100644 --- a/database/src/main/java/com/kunzisoft/keepass/model/EntryInfo.kt +++ b/database/src/main/java/com/kunzisoft/keepass/model/EntryInfo.kt @@ -213,15 +213,19 @@ class EntryInfo : NodeInfo { registerInfo.password?.let { password = it } setCreditCard(registerInfo.creditCard) setPasskey(registerInfo.passkey) - setAppOrigin( - registerInfo.appOrigin, - database?.allowEntryCustomFields() == true - ) + saveAppOrigin(database, registerInfo.appOrigin) if (title.isEmpty()) { title = registerInfo.toString().toTitle() } } + /** + * Add AppOrigin + */ + fun saveAppOrigin(database: Database?, appOrigin: AppOrigin?) { + setAppOrigin(appOrigin, database?.allowEntryCustomFields() == true) + } + fun getVisualTitle(): String { return title.ifEmpty { url.ifEmpty {