Add temp advanced service to store encrypted elements

This commit is contained in:
J-Jamet
2020-12-07 17:03:26 +01:00
parent e600d8a56c
commit e2886c342a
7 changed files with 177 additions and 25 deletions

View File

@@ -174,13 +174,17 @@
android:enabled="true"
android:exported="false" />
<service
android:name=".notifications.AttachmentFileNotificationService"
android:name="com.kunzisoft.keepass.notifications.AttachmentFileNotificationService"
android:enabled="true"
android:exported="false" />
<service
android:name="com.kunzisoft.keepass.notifications.ClipboardEntryNotificationService"
android:enabled="true"
android:exported="false" />
<service
android:name="com.kunzisoft.keepass.notifications.AdvancedUnlockNotificationService"
android:enabled="true"
android:exported="false" />
<!-- Receiver for Autofill -->
<service
android:name="com.kunzisoft.keepass.autofill.KeeAutofillService"

View File

@@ -19,19 +19,69 @@
*/
package com.kunzisoft.keepass.app.database
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.net.Uri
import android.os.IBinder
import com.kunzisoft.keepass.notifications.AdvancedUnlockNotificationService
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.utils.SingletonHolderParameter
class CipherDatabaseAction(applicationContext: Context) {
class CipherDatabaseAction(context: Context) {
private val applicationContext = context.applicationContext
private val cipherDatabaseDao =
AppDatabase
.getDatabase(applicationContext)
.cipherDatabaseDao()
// Temp DAO to easily remove content if object no longer in memory
private val useTempDao = PreferencesUtil.isTempAdvancedUnlockEnable(applicationContext)
private val mIntentAdvancedUnlockService = Intent(applicationContext,
AdvancedUnlockNotificationService::class.java)
private var mBinder: AdvancedUnlockNotificationService.AdvancedUnlockBinder? = null
private var mServiceConnection: ServiceConnection? = null
fun initialize() {
applicationContext.startService(mIntentAdvancedUnlockService)
}
@Synchronized
private fun getTempCipherDao(tempCipherDaoRetrieved: (MutableList<CipherDatabaseEntity>?) -> Unit) {
// Check if a service is currently running else do nothing
if (mBinder != null) {
tempCipherDaoRetrieved.invoke(mBinder?.getTempCipherDao())
} else if (mServiceConnection == null) {
mServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) {
mBinder = (serviceBinder as AdvancedUnlockNotificationService.AdvancedUnlockBinder)
tempCipherDaoRetrieved.invoke(mBinder?.getTempCipherDao())
}
override fun onServiceDisconnected(name: ComponentName?) {
mBinder = null
mServiceConnection = null
}
}
// bind Service
mServiceConnection?.let {
applicationContext.bindService(mIntentAdvancedUnlockService,
it,
Context.BIND_ABOVE_CLIENT)
}
}
}
fun getCipherDatabase(databaseUri: Uri,
cipherDatabaseResultListener: (CipherDatabaseEntity?) -> Unit) {
if (useTempDao) {
getTempCipherDao { tempCipherDao ->
cipherDatabaseResultListener.invoke(tempCipherDao?.firstOrNull { it.databaseUri == databaseUri.toString()})
}
} else {
IOActionTask(
{
cipherDatabaseDao.getByDatabaseUri(databaseUri.toString())
@@ -41,6 +91,7 @@ class CipherDatabaseAction(applicationContext: Context) {
}
).execute()
}
}
fun containsCipherDatabase(databaseUri: Uri,
contains: (Boolean) -> Unit) {
@@ -51,10 +102,17 @@ class CipherDatabaseAction(applicationContext: Context) {
fun addOrUpdateCipherDatabase(cipherDatabaseEntity: CipherDatabaseEntity,
cipherDatabaseResultListener: (() -> Unit)? = null) {
if (useTempDao) {
getTempCipherDao { tempCipherDao ->
val cipherDatabaseRetrieve = tempCipherDao?.firstOrNull { it.databaseUri == cipherDatabaseEntity.databaseUri }
cipherDatabaseRetrieve?.replaceContent(cipherDatabaseEntity)
?: tempCipherDao?.add(cipherDatabaseEntity)
cipherDatabaseResultListener?.invoke()
}
} else {
IOActionTask(
{
val cipherDatabaseRetrieve = cipherDatabaseDao.getByDatabaseUri(cipherDatabaseEntity.databaseUri)
// Update values if element not yet in the database
if (cipherDatabaseRetrieve == null) {
cipherDatabaseDao.add(cipherDatabaseEntity)
@@ -67,9 +125,15 @@ class CipherDatabaseAction(applicationContext: Context) {
}
).execute()
}
}
fun deleteByDatabaseUri(databaseUri: Uri,
cipherDatabaseResultListener: (() -> Unit)? = null) {
getTempCipherDao { tempCipherDao ->
tempCipherDao?.firstOrNull { it.databaseUri == databaseUri.toString() }?.let {
tempCipherDao.remove(it)
}
}
IOActionTask(
{
cipherDatabaseDao.deleteByDatabaseUri(databaseUri.toString())
@@ -81,6 +145,9 @@ class CipherDatabaseAction(applicationContext: Context) {
}
fun deleteAll() {
getTempCipherDao { tempCipherDao ->
tempCipherDao?.clear()
}
IOActionTask(
{
cipherDatabaseDao.deleteAll()

View File

@@ -43,6 +43,11 @@ data class CipherDatabaseEntity(
parcel.readString()!!,
parcel.readString()!!)
fun replaceContent(copy: CipherDatabaseEntity) {
this.encryptedValue = copy.encryptedValue
this.specParameters = copy.specParameters
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(databaseUri)
parcel.writeString(encryptedValue)

View File

@@ -78,6 +78,7 @@ class AdvancedUnlockedManager(var context: FragmentActivity,
// Add old listener to enable the button, only be call here because of onCheckedChange bug
onCheckedPasswordChangeListener?.onCheckedChanged(compoundButton, checked)
}
cipherDatabaseAction.initialize()
}
/**

View File

@@ -0,0 +1,74 @@
package com.kunzisoft.keepass.notifications
import android.app.PendingIntent
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
class AdvancedUnlockNotificationService : NotificationService() {
private lateinit var mTempCipherDao: ArrayList<CipherDatabaseEntity>
private var mActionTaskBinder = AdvancedUnlockBinder()
inner class AdvancedUnlockBinder: Binder() {
fun getTempCipherDao(): MutableList<CipherDatabaseEntity> {
return mTempCipherDao
}
}
override val notificationId: Int = 593
override fun retrieveChannelId(): String {
return CHANNEL_ADVANCED_UNLOCK_ID
}
override fun onBind(intent: Intent): IBinder? {
super.onBind(intent)
return mActionTaskBinder
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)
val deleteIntent = Intent(this, AdvancedUnlockNotificationService::class.java).apply {
action = ACTION_REMOVE_KEYS
}
val pendingDeleteIntent = PendingIntent.getService(this, 0, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val notificationBuilder = buildNewNotification().apply {
setSmallIcon(R.drawable.bolt)
intent?.let {
setContentTitle(getString(R.string.advanced_unlock))
}
setContentText(getString(R.string.advanced_unlock_tap_delete))
setContentIntent(pendingDeleteIntent)
// Unfortunately swipe is disabled in lollipop+
setDeleteIntent(pendingDeleteIntent)
}
startForeground(notificationId, notificationBuilder.build())
if (intent?.action == ACTION_REMOVE_KEYS) {
stopSelf()
}
return START_STICKY
}
override fun onCreate() {
super.onCreate()
mTempCipherDao = ArrayList()
}
override fun onDestroy() {
mTempCipherDao.clear()
super.onDestroy()
}
companion object {
private const val CHANNEL_ADVANCED_UNLOCK_ID = "com.kunzisoft.keepass.notification.channel.unlock"
const val ACTION_REMOVE_KEYS = "ACTION_REMOVE_KEYS"
}
}

View File

@@ -319,6 +319,7 @@
<string name="lock_database_show_button_summary">Displays the lock button in the user interface</string>
<string name="content">Content</string>
<string name="advanced_unlock">Advanced unlock</string>
<string name="advanced_unlock_tap_delete">Tap to delete advanced unlocking keys</string>
<string name="advanced_unlock_explanation_summary">Use advanced unlocking to open a database more easily</string>
<string name="biometric_unlock_enable_title">Biometric unlocking</string>
<string name="biometric_unlock_enable_summary">Lets you scan your biometric to open the database</string>

View File

@@ -54,7 +54,7 @@
android:dependency="@string/temp_advanced_unlock_enable_key"
android:entries="@array/timeout_options"
android:entryValues="@array/timeout_values"
android:dialogTitle="@string/clipboard_timeout"
android:dialogTitle="@string/advanced_unlock_timeout"
android:defaultValue="@string/temp_advanced_unlock_timeout_default"/>
<Preference
android:key="@string/biometric_delete_all_key_key"