From b1ebbc34d4a0139e831c25c844e92cfd0beb121c Mon Sep 17 00:00:00 2001 From: DenBond7 Date: Mon, 1 Nov 2021 10:20:58 +0200 Subject: [PATCH] wip --- .../flowcrypt/email/api/email/EmailUtil.kt | 6 +- .../response/model/PublicKeyMsgBlock.kt | 10 +- .../email/database/dao/PubKeysDao.kt | 6 + .../email/database/dao/RecipientDao.kt | 5 +- .../email/database/entity/PublicKeyEntity.kt | 21 +- .../email/database/entity/RecipientEntity.kt | 20 +- .../entity/relation/RecipientWithPubKeys.kt | 12 + .../org/bouncycastle/openpgp/PGPKeyRingExt.kt | 6 - .../jetpack/viewmodel/AccountViewModel.kt | 4 +- .../jetpack/viewmodel/MsgDetailsViewModel.kt | 30 +- .../jetpack/viewmodel/PrivateKeysViewModel.kt | 66 ++-- .../jetpack/viewmodel/RecipientsViewModel.kt | 201 ++++++------ ...tactsWorker.kt => LoadRecipientsWorker.kt} | 42 +-- .../flowcrypt/email/model/KeyImportDetails.kt | 73 ++--- .../com/flowcrypt/email/model/PgpContact.kt | 105 ------- .../flowcrypt/email/model/PublicKeyInfo.kt | 12 - .../email/security/model/PgpKeyDetails.kt | 59 ++-- .../service/EmailAndNameUpdaterService.kt | 2 +- ...PrepareOutgoingMessagesJobIntentService.kt | 3 +- .../ui/activity/ImportPgpContactActivity.kt | 14 +- .../ui/activity/ImportPublicKeyActivity.kt | 21 +- .../PreviewImportPgpContactActivity.kt | 17 +- .../ui/activity/SelectContactsActivity.kt | 14 +- .../ui/activity/base/BaseSyncActivity.kt | 4 +- .../activity/fragment/ContactsListFragment.kt | 19 +- .../fragment/MessageDetailsFragment.kt | 45 ++- .../PreviewImportPgpContactFragment.kt | 97 +++--- .../fragment/PrivateKeyDetailsFragment.kt | 7 +- .../fragment/PublicKeyDetailsFragment.kt | 12 +- .../ui/activity/fragment/base/BaseFragment.kt | 2 +- .../fragment/base/CreateMessageFragment.kt | 297 ++++++++++-------- .../dialog/ChoosePublicKeyDialogFragment.kt | 14 +- .../dialog/NoPgpFoundDialogFragment.kt | 42 +-- .../email/ui/adapter/AttesterKeyAdapter.kt | 4 +- .../ImportPgpContactsRecyclerViewAdapter.kt | 44 +-- .../email/ui/adapter/PgpContactAdapter.kt | 4 +- .../adapter/PrivateKeysRecyclerViewAdapter.kt | 3 +- .../ui/adapter/PrvKeysRecyclerViewAdapter.kt | 2 +- ...er.kt => RecipientsRecyclerViewAdapter.kt} | 13 +- FlowCrypt/src/main/res/values/strings.xml | 2 +- 40 files changed, 645 insertions(+), 715 deletions(-) rename FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/workmanager/sync/{LoadContactsWorker.kt => LoadRecipientsWorker.kt} (87%) delete mode 100644 FlowCrypt/src/main/java/com/flowcrypt/email/model/PgpContact.kt rename FlowCrypt/src/main/java/com/flowcrypt/email/ui/adapter/{ContactsRecyclerViewAdapter.kt => RecipientsRecyclerViewAdapter.kt} (90%) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/EmailUtil.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/EmailUtil.kt index e7d0010d6e..bf74e8f203 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/EmailUtil.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/EmailUtil.kt @@ -201,9 +201,9 @@ class EmailUtil { * @param pgpKeyDetails The key details * @return A generated [AttachmentInfo]. */ - fun genAttInfoFromPubKey(pgpKeyDetails: PgpKeyDetails?): AttachmentInfo? { + fun genAttInfoFromPubKey(pgpKeyDetails: PgpKeyDetails?, email: String): AttachmentInfo? { if (pgpKeyDetails != null) { - val fileName = "0x" + pgpKeyDetails.fingerprint.toUpperCase(Locale.getDefault()) + ".asc" + val fileName = "0x" + pgpKeyDetails.fingerprint.uppercase() + ".asc" return if (!TextUtils.isEmpty(pgpKeyDetails.publicKey)) { val attachmentInfo = AttachmentInfo() @@ -212,7 +212,7 @@ class EmailUtil { attachmentInfo.encodedSize = pgpKeyDetails.publicKey.length.toLong() attachmentInfo.rawData = pgpKeyDetails.publicKey.toByteArray() attachmentInfo.type = Constants.MIME_TYPE_PGP_KEY - attachmentInfo.email = pgpKeyDetails.primaryPgpContact.email + attachmentInfo.email = email attachmentInfo.id = generateContentId() attachmentInfo.isEncryptionAllowed = false diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/model/PublicKeyMsgBlock.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/model/PublicKeyMsgBlock.kt index 790d6f916c..ca2c8d054c 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/model/PublicKeyMsgBlock.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/model/PublicKeyMsgBlock.kt @@ -7,7 +7,8 @@ package com.flowcrypt.email.api.retrofit.response.model import android.os.Parcel import android.os.Parcelable -import com.flowcrypt.email.model.PgpContact +import com.flowcrypt.email.database.entity.relation.RecipientWithPubKeys + import com.flowcrypt.email.security.model.PgpKeyDetails import com.google.gson.annotations.Expose @@ -29,7 +30,7 @@ data class PublicKeyMsgBlock constructor( @Expose override val type: MsgBlock.Type = MsgBlock.Type.PUBLIC_KEY - var existingPgpContact: PgpContact? = null + var existingRecipientWithPubKeys: RecipientWithPubKeys? = null constructor(parcel: Parcel) : this( parcel.readString(), @@ -37,7 +38,8 @@ data class PublicKeyMsgBlock constructor( parcel.readParcelable(PgpKeyDetails::class.java.classLoader), parcel.readParcelable(MsgBlockError::class.java.classLoader), ) { - existingPgpContact = parcel.readParcelable(PgpContact::class.java.classLoader) + existingRecipientWithPubKeys = + parcel.readParcelable(RecipientWithPubKeys::class.java.classLoader) } override fun writeToParcel(parcel: Parcel, flags: Int) = @@ -47,7 +49,7 @@ data class PublicKeyMsgBlock constructor( writeInt((if (complete) 1 else 0)) writeParcelable(keyDetails, flags) writeParcelable(error, flags) - writeParcelable(existingPgpContact, flags) + writeParcelable(existingRecipientWithPubKeys, flags) } override fun describeContents(): Int = 0 diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/database/dao/PubKeysDao.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/database/dao/PubKeysDao.kt index fde7f7d864..26f171beaf 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/database/dao/PubKeysDao.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/database/dao/PubKeysDao.kt @@ -29,4 +29,10 @@ interface PubKeysDao : BaseDao { @Query("SELECT * FROM public_keys WHERE fingerprint = :fingerprint") suspend fun getPublicKeysByFingerprint(fingerprint: String): List + + @Query("SELECT * FROM public_keys WHERE recipient = :recipient AND fingerprint = :fingerprint") + suspend fun getPublicKeysByRecipientAndFingerprint( + recipient: String, + fingerprint: String + ): PublicKeyEntity? } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/database/dao/RecipientDao.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/database/dao/RecipientDao.kt index 22d26dfe66..7b3b06ee37 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/database/dao/RecipientDao.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/database/dao/RecipientDao.kt @@ -50,8 +50,9 @@ interface RecipientDao : BaseDao { @Query("SELECT * FROM recipients WHERE email = :email") fun getRecipientByEmail(email: String): RecipientEntity? + @Transaction @Query("SELECT * FROM recipients WHERE email = :email") - fun getRecipientByEmailLD(email: String): LiveData + fun getRecipientsWithPubKeysByEmailsLD(email: String): LiveData //fixed @Transaction @@ -68,5 +69,5 @@ interface RecipientDao : BaseDao { @Transaction @Query("SELECT * FROM recipients WHERE email = :email") - fun getRecipientWithPubKeysByEmail(email: String): RecipientWithPubKeys? + suspend fun getRecipientWithPubKeysByEmail(email: String): RecipientWithPubKeys? } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/database/entity/PublicKeyEntity.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/database/entity/PublicKeyEntity.kt index 9ca55aa7ae..64b26f4ed6 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/database/entity/PublicKeyEntity.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/database/entity/PublicKeyEntity.kt @@ -11,8 +11,10 @@ import android.provider.BaseColumns import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.ForeignKey +import androidx.room.Ignore import androidx.room.Index import androidx.room.PrimaryKey +import com.flowcrypt.email.security.model.PgpKeyDetails /** * @author Denis Bondarenko @@ -49,18 +51,31 @@ data class PublicKeyEntity( @ColumnInfo(name = "fingerprint") val fingerprint: String, @ColumnInfo(name = "public_key") val publicKey: ByteArray ) : Parcelable { + + @Ignore + var pgpKeyDetails: PgpKeyDetails? = null + + @Ignore + var isNotUsable: Boolean? = null + constructor(parcel: Parcel) : this( parcel.readValue(Long::class.java.classLoader) as? Long, requireNotNull(parcel.readString()), requireNotNull(parcel.readString()), requireNotNull(parcel.createByteArray()) - ) + ) { + pgpKeyDetails = parcel.readParcelable(PgpKeyDetails::class.java.classLoader) + isNotUsable = parcel.readValue(Boolean::class.java.classLoader) as? Boolean + } + override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeValue(id) parcel.writeString(recipient) parcel.writeString(fingerprint) parcel.writeByteArray(publicKey) + parcel.writeParcelable(pgpKeyDetails, flags) + parcel.writeValue(isNotUsable) } override fun describeContents(): Int { @@ -77,6 +92,8 @@ data class PublicKeyEntity( if (recipient != other.recipient) return false if (fingerprint != other.fingerprint) return false if (!publicKey.contentEquals(other.publicKey)) return false + if (pgpKeyDetails != other.pgpKeyDetails) return false + if (isNotUsable != other.isNotUsable) return false return true } @@ -86,6 +103,8 @@ data class PublicKeyEntity( result = 31 * result + recipient.hashCode() result = 31 * result + fingerprint.hashCode() result = 31 * result + publicKey.contentHashCode() + result = 31 * result + (pgpKeyDetails?.hashCode() ?: 0) + result = 31 * result + (isNotUsable?.hashCode() ?: 0) return result } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/database/entity/RecipientEntity.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/database/entity/RecipientEntity.kt index 201fe278d1..aeb9ac5ba5 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/database/entity/RecipientEntity.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/database/entity/RecipientEntity.kt @@ -10,11 +10,8 @@ import android.os.Parcelable import android.provider.BaseColumns import androidx.room.ColumnInfo import androidx.room.Entity -import androidx.room.Ignore import androidx.room.Index import androidx.room.PrimaryKey -import com.flowcrypt.email.model.PgpContact -import com.flowcrypt.email.security.model.PgpKeyDetails /** * @author Denis Bondarenko @@ -37,26 +34,12 @@ data class RecipientEntity( @ColumnInfo(name = "last_use", defaultValue = "0") val lastUse: Long = 0 ) : Parcelable { - @Ignore - var pgpKeyDetails: PgpKeyDetails? = null - constructor(parcel: Parcel) : this( parcel.readValue(Long::class.java.classLoader) as? Long, requireNotNull(parcel.readString()), parcel.readString(), parcel.readLong() - ) { - pgpKeyDetails = parcel.readParcelable(PgpKeyDetails::class.java.classLoader) - } - - fun toPgpContact(): PgpContact { - return PgpContact( - email = email, - name = name, - lastUse = lastUse, - pgpKeyDetails = pgpKeyDetails - ) - } + ) //todo-denbond7 need to think about this class. enum class Type { @@ -68,7 +51,6 @@ data class RecipientEntity( parcel.writeString(email) parcel.writeString(name) parcel.writeLong(lastUse) - parcel.writeParcelable(pgpKeyDetails, flags) } override fun describeContents(): Int { diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/database/entity/relation/RecipientWithPubKeys.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/database/entity/relation/RecipientWithPubKeys.kt index 18a7d6137d..4fc4ad395d 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/database/entity/relation/RecipientWithPubKeys.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/database/entity/relation/RecipientWithPubKeys.kt @@ -42,6 +42,18 @@ data class RecipientWithPubKeys( return 0 } + fun hasPgp(): Boolean { + return publicKeys.isNotEmpty() + } + + fun hasNotExpiredKeys(): Boolean { + return publicKeys.any { it.pgpKeyDetails?.isExpired?.not() ?: false } + } + + fun hasUsableKeys(): Boolean { + return publicKeys.any { if (it.isNotUsable != null) it.isNotUsable?.not() ?: false else true } + } + companion object CREATOR : Parcelable.Creator { override fun createFromParcel(parcel: Parcel) = RecipientWithPubKeys(parcel) override fun newArray(size: Int): Array = arrayOfNulls(size) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/org/bouncycastle/openpgp/PGPKeyRingExt.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/org/bouncycastle/openpgp/PGPKeyRingExt.kt index 6527be5175..414b83e4ed 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/org/bouncycastle/openpgp/PGPKeyRingExt.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/org/bouncycastle/openpgp/PGPKeyRingExt.kt @@ -6,7 +6,6 @@ package com.flowcrypt.email.extensions.org.bouncycastle.openpgp import androidx.annotation.WorkerThread -import com.flowcrypt.email.model.PgpContact import com.flowcrypt.email.security.model.Algo import com.flowcrypt.email.security.model.KeyId import com.flowcrypt.email.security.model.PgpKeyDetails @@ -85,11 +84,6 @@ fun PGPKeyRing.toPgpKeyDetails(): PgpKeyDetails { ) } -fun PGPKeyRing.pgpContacts(): List { - val list = publicKey.userIDs.iterator().asSequence().toList() - return PgpContact.determinePgpContacts(list) -} - @Throws(IOException::class) fun PGPKeyRing.armor(headers: List>? = PgpArmor.FLOWCRYPT_HEADERS): String { ByteArrayOutputStream().use { out -> diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/AccountViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/AccountViewModel.kt index b6128533dd..3bf911daa4 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/AccountViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/AccountViewModel.kt @@ -17,7 +17,7 @@ import com.flowcrypt.email.R import com.flowcrypt.email.api.email.model.AuthCredentials import com.flowcrypt.email.api.retrofit.response.base.Result import com.flowcrypt.email.database.entity.AccountEntity -import com.flowcrypt.email.jetpack.workmanager.sync.LoadContactsWorker +import com.flowcrypt.email.jetpack.workmanager.sync.LoadRecipientsWorker import com.flowcrypt.email.security.KeyStoreCryptoManager import com.flowcrypt.email.service.IdleService import kotlinx.coroutines.Dispatchers @@ -84,7 +84,7 @@ open class AccountViewModel(application: Application) : RoomBasicViewModel(appli ) } - LoadContactsWorker.enqueue(getApplication()) + LoadRecipientsWorker.enqueue(getApplication()) addNewAccountLiveData.value = Result.success(true) } catch (e: Exception) { diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/MsgDetailsViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/MsgDetailsViewModel.kt index 3454035a48..665b5c5d3a 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/MsgDetailsViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/MsgDetailsViewModel.kt @@ -411,22 +411,22 @@ class MsgDetailsViewModel( private suspend fun preResultsProcessing(blocks: List) { for (block in blocks) { - if (block is PublicKeyMsgBlock) { - val keyDetails = block.keyDetails ?: continue - val pgpContact = keyDetails.primaryPgpContact - //todo-denbond7 need to rework on this code - val recipientEntity = - roomDatabase.recipientDao().getRecipientByEmailSuspend(pgpContact.email) - //block.existingPgpContact = recipientEntity?.toPgpContact() - } + when (block) { + is PublicKeyMsgBlock -> { + val keyDetails = block.keyDetails ?: continue + val recipient = keyDetails.mimeAddresses.firstOrNull()?.address ?: continue + block.existingRecipientWithPubKeys = + roomDatabase.recipientDao().getRecipientWithPubKeysByEmail(recipient) + } - if (block is DecryptErrorMsgBlock) { - if (block.decryptErr?.details?.type == PgpDecrypt.DecryptionErrorType.NEED_PASSPHRASE) { - val fingerprints = block.decryptErr.fingerprints ?: emptyList() - if (fingerprints.isEmpty()) { - ExceptionUtil.handleError(IllegalStateException("Fingerprints were not provided")) - } else { - passphraseNeededLiveData.postValue(fingerprints) + is DecryptErrorMsgBlock -> { + if (block.decryptErr?.details?.type == PgpDecrypt.DecryptionErrorType.NEED_PASSPHRASE) { + val fingerprints = block.decryptErr.fingerprints ?: emptyList() + if (fingerprints.isEmpty()) { + ExceptionUtil.handleError(IllegalStateException("Fingerprints were not provided")) + } else { + passphraseNeededLiveData.postValue(fingerprints) + } } } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt index 5264628386..4bef718228 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt @@ -30,11 +30,11 @@ import com.flowcrypt.email.api.retrofit.response.model.OrgRules import com.flowcrypt.email.database.entity.AccountEntity import com.flowcrypt.email.database.entity.ActionQueueEntity import com.flowcrypt.email.database.entity.KeyEntity +import com.flowcrypt.email.database.entity.RecipientEntity import com.flowcrypt.email.extensions.org.bouncycastle.openpgp.toPgpKeyDetails import com.flowcrypt.email.extensions.org.pgpainless.util.asString import com.flowcrypt.email.model.KeyImportDetails import com.flowcrypt.email.model.KeyImportModel -import com.flowcrypt.email.model.PgpContact import com.flowcrypt.email.security.KeyStoreCryptoManager import com.flowcrypt.email.security.KeysStorageImpl import com.flowcrypt.email.security.SecurityUtils @@ -205,13 +205,12 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat } if (roomDatabase.keysDao().getKeyByAccountAndFingerprintSuspend( - accountEntity.email.lowercase(Locale.US), - fingerprint + accountEntity.email.lowercase(), fingerprint ) == null ) { if (addAccountIfNotExist) { val existedAccount = roomDatabase.accountDao() - .getAccountSuspend(accountEntity.email.lowercase(Locale.US)) + .getAccountSuspend(accountEntity.email.lowercase()) if (existedAccount == null) { roomDatabase.accountDao().addAccountSuspend(accountEntity) } @@ -243,16 +242,24 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat passphraseType = KeyEntity.PassphraseType.RAM ) } - //update contacts table + + //update pub keys val recipientDao = roomDatabase.recipientDao() val pubKeysDao = roomDatabase.pubKeysDao() - for (pgpContact in keyDetails.pgpContacts) { - pgpContact.pubkey = keyDetails.publicKey - val recipientWithPubKeys = - recipientDao.getRecipientByEmailSuspend(pgpContact.email) - if (recipientWithPubKeys == null && GeneralUtil.isEmailValid(pgpContact.email)) { - recipientDao.insertWithReplaceSuspend(pgpContact.toRecipientEntity()) - pubKeysDao.insertWithReplaceSuspend(pgpContact.toPubKey()) + for (mimeAddress in keyDetails.mimeAddresses) { + val address = mimeAddress.address.lowercase() + val name = mimeAddress.personal + + val existedRecipientWithPubKeys = + recipientDao.getRecipientWithPubKeysByEmail(address) + if (existedRecipientWithPubKeys == null) { + recipientDao.insertSuspend(RecipientEntity(email = address, name = name)) + } + + val existedPubKeyEntity = + pubKeysDao.getPublicKeysByRecipientAndFingerprint(address, keyDetails.fingerprint) + if (existedPubKeyEntity == null) { + pubKeysDao.insertSuspend(keyDetails.toPublicKeyEntity(address)) } } } @@ -334,6 +341,7 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat createPrivateKeyLiveData.value = Result.loading() var pgpKeyDetails: PgpKeyDetails? = null try { + //use genUserIds() pgpKeyDetails = PGPainless.generateKeyRing().simpleEcKeyRing( UserId.nameAndEmail( accountEntity.displayName @@ -342,7 +350,7 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat ).toPgpKeyDetails().copy(passphraseType = passphraseType) val existedAccount = - roomDatabase.accountDao().getAccountSuspend(accountEntity.email.lowercase(Locale.US)) + roomDatabase.accountDao().getAccountSuspend(accountEntity.email.lowercase()) if (existedAccount == null) { roomDatabase.accountDao().addAccountSuspend(accountEntity) } @@ -369,10 +377,10 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat val allKeyEntitiesOfAccount = roomDatabase.keysDao().getAllKeysByAccountSuspend(accountEntity.email) val fingerprintListOfDeleteCandidates = keys.map { - it.fingerprint.lowercase(Locale.US) + it.fingerprint.lowercase() } val deleteCandidates = allKeyEntitiesOfAccount.filter { - fingerprintListOfDeleteCandidates.contains(it.fingerprint.lowercase(Locale.US)) + fingerprintListOfDeleteCandidates.contains(it.fingerprint.lowercase()) } if (keys.size == allKeyEntitiesOfAccount.size) { @@ -555,28 +563,36 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat } } - private suspend fun genContacts(accountEntity: AccountEntity): List = + private suspend fun genUserIds(accountEntity: AccountEntity): List = withContext(Dispatchers.IO) { - val pgpContactMain = PgpContact(accountEntity.email, accountEntity.displayName) - val contacts = ArrayList() + val userIds = ArrayList() + userIds.add(UserId.newBuilder().withEmail(accountEntity.email).apply { + accountEntity.displayName?.let { name -> + withName(name) + } + }.build()) - when (accountEntity.accountType) { - AccountEntity.ACCOUNT_TYPE_GOOGLE -> { - contacts.add(pgpContactMain) + if (accountEntity.accountType == AccountEntity.ACCOUNT_TYPE_GOOGLE) { + try { val gmail = GmailApiHelper.generateGmailApiService(getApplication(), accountEntity) val aliases = gmail.users().settings().sendAs().list(GmailApiHelper.DEFAULT_USER_ID).execute() for (alias in aliases.sendAs) { if (alias.verificationStatus != null) { - contacts.add(PgpContact(alias.sendAsEmail, alias.displayName)) + userIds.add(UserId.newBuilder().withEmail(alias.sendAsEmail).apply { + alias.displayName?.let { name -> + withName(name) + } + }.build()) } } + } catch (e: Exception) { + //skip any issues + e.printStackTrace() } - - else -> contacts.add(pgpContactMain) } - return@withContext contacts + return@withContext userIds } /** diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RecipientsViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RecipientsViewModel.kt index 63a5b49034..3b811a8726 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RecipientsViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RecipientsViewModel.kt @@ -6,21 +6,18 @@ package com.flowcrypt.email.jetpack.viewmodel import android.app.Application -import android.content.Context -import android.widget.Toast import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Transformations import androidx.lifecycle.liveData import androidx.lifecycle.viewModelScope -import com.flowcrypt.email.R import com.flowcrypt.email.api.retrofit.ApiRepository import com.flowcrypt.email.api.retrofit.FlowcryptApiRepository import com.flowcrypt.email.api.retrofit.response.attester.PubResponse import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.base.Result import com.flowcrypt.email.database.entity.RecipientEntity -import com.flowcrypt.email.model.PgpContact +import com.flowcrypt.email.database.entity.relation.RecipientWithPubKeys import com.flowcrypt.email.security.model.PgpKeyDetails import com.flowcrypt.email.security.pgp.PgpKey import com.flowcrypt.email.util.GeneralUtil @@ -66,13 +63,13 @@ class RecipientsViewModel(application: Application) : AccountViewModel(applicati emit(Result.success(foundContacts)) } } - val contactsToLiveData: MutableLiveData>> = MutableLiveData() - val contactsCcLiveData: MutableLiveData>> = MutableLiveData() - val contactsBccLiveData: MutableLiveData>> = MutableLiveData() + val recipientsToLiveData: MutableLiveData>> = MutableLiveData() + val recipientsCcLiveData: MutableLiveData>> = MutableLiveData() + val recipientsBccLiveData: MutableLiveData>> = MutableLiveData() val pubKeysFromServerLiveData: MutableLiveData> = MutableLiveData() - fun copyPubKeysToRecipient(pgpContact: PgpContact, pgpContactFromKey: PgpContact) { + /*fun copyPubKeysToRecipient(pgpContact: RecipientWithPubKeys, pgpContactFromKey: RecipientWithPubKeys) { viewModelScope.launch { val recipient = roomDatabase.recipientDao().getRecipientByEmailSuspend(pgpContact.email) if (recipient != null) { @@ -99,10 +96,10 @@ class RecipientsViewModel(application: Application) : AccountViewModel(applicati pubKeysOfCopyCandidate.map { it.copy(id = null, recipient = email) } ) } - } + }*/ - fun contactChangesLiveData(recipientEntity: RecipientEntity): LiveData { - return roomDatabase.recipientDao().getRecipientByEmailLD(recipientEntity.email) + fun contactChangesLiveData(recipientEntity: RecipientEntity): LiveData { + return roomDatabase.recipientDao().getRecipientsWithPubKeysByEmailsLD(recipientEntity.email) } /** @@ -116,15 +113,15 @@ class RecipientsViewModel(application: Application) : AccountViewModel(applicati * call * to see if you can now get the pubkey. If a pubkey is available, save it back to the database. * c) no record in the db found: - * 1. save an empty record eg `new PgpContact(email, null);` - this means we don't know if they have PGP yet + * 1. save an empty record eg `new RecipientWithPubKeys(email, null);` - this means we don't know if they have PGP yet * 1. look up the email on `flowcrypt.com/attester/pub/EMAIL>` - * 1. if pubkey comes back, create something like `new PgpContact(js, email, null, pubkey, - * client);`. The PgpContact constructor will define has_pgp, fingerprint, etc + * 1. if pubkey comes back, create something like `new RecipientWithPubKeys(js, email, null, pubkey, + * client);`. The RecipientWithPubKeys constructor will define has_pgp, fingerprint, etc * for you. Then save that object into database. - * 1. if no pubkey found, create `new PgpContact(js, email, null, null, null, null);` - this + * 1. if no pubkey found, create `new RecipientWithPubKeys(js, email, null, null, null, null);` - this * means we know they don't currently have PGP */ - fun fetchAndUpdateInfoAboutContacts(type: RecipientEntity.Type, emails: List) { + fun fetchAndUpdateInfoAboutRecipients(type: RecipientEntity.Type, emails: List) { viewModelScope.launch { if (emails.isEmpty()) { return@launch @@ -132,67 +129,70 @@ class RecipientsViewModel(application: Application) : AccountViewModel(applicati setResultForRemoteContactsLiveData(type, Result.loading()) - val pgpContacts = ArrayList() + val recipients = ArrayList() try { for (email in emails) { if (GeneralUtil.isEmailValid(email)) { val emailLowerCase = email.lowercase(Locale.getDefault()) - var cachedRecipientEntity = - roomDatabase.recipientDao().getRecipientByEmailSuspend(emailLowerCase) - - if (cachedRecipientEntity == null) { - cachedRecipientEntity = PgpContact(emailLowerCase, null).toRecipientEntity() - roomDatabase.recipientDao().insertSuspend(cachedRecipientEntity) - cachedRecipientEntity = - roomDatabase.recipientDao().getRecipientByEmailSuspend(emailLowerCase) + var cachedRecipientWithPubKeys = + roomDatabase.recipientDao().getRecipientWithPubKeysByEmail(emailLowerCase) + + if (cachedRecipientWithPubKeys == null) { + roomDatabase.recipientDao().insertSuspend(RecipientEntity(email = emailLowerCase)) + cachedRecipientWithPubKeys = + roomDatabase.recipientDao().getRecipientWithPubKeysByEmail(emailLowerCase) } else { - try { - /*cachedRecipientEntity.publicKey?.let { - val result = PgpKey.parseKeys(it).pgpKeyDetailsList - cachedRecipientEntity?.pgpKeyDetails = result.firstOrNull() - }*/ - } catch (e: Exception) { - e.printStackTrace() - pgpContacts.add( - cachedRecipientEntity.toPgpContact().copy(hasNotUsablePubKey = true) - ) - continue + for (publicKeyEntity in cachedRecipientWithPubKeys.publicKeys) { + try { + val result = PgpKey.parseKeys(publicKeyEntity.publicKey).pgpKeyDetailsList + publicKeyEntity.pgpKeyDetails = result.firstOrNull() + } catch (e: Exception) { + e.printStackTrace() + publicKeyEntity.isNotUsable = true + } } } try { - if (true) { - getPgpContactInfoFromServer(email = emailLowerCase)?.let { - cachedRecipientEntity = - updateCachedInfoWithAttesterInfo(cachedRecipientEntity, it, emailLowerCase) + if (cachedRecipientWithPubKeys?.hasPgp() == false) { + getPgpInfoFromServer(email = emailLowerCase)?.let { pgpKeyDetailsList -> + cachedRecipientWithPubKeys = cachedRecipientWithPubKeys?.let { + updateCachedInfoWithPubKeysFromAttester(it, pgpKeyDetailsList, emailLowerCase) + } } } else { - cachedRecipientEntity?.pgpKeyDetails?.fingerprint?.let { fingerprint -> - getPgpContactInfoFromServer(fingerprint = fingerprint)?.let { - val cacheLastModified = cachedRecipientEntity?.pgpKeyDetails?.lastModified ?: 0 - val attesterLastModified = it.pgpKeyDetails?.lastModified ?: 0 - val attesterFingerprint = it.pgpKeyDetails?.fingerprint - - if (attesterLastModified > cacheLastModified && fingerprint.equals( - attesterFingerprint, - true - ) + //todo-denbond7 need to think about this code. Clarify can we have a few pubkeys as a single source + for (publicKeyEntity in cachedRecipientWithPubKeys?.publicKeys ?: emptyList()) { + val pgpKeyDetails = publicKeyEntity.pgpKeyDetails ?: continue + getPgpInfoFromServer(fingerprint = publicKeyEntity.fingerprint)?.let { + val cacheLastModified = pgpKeyDetails.lastModified ?: 0 + val attesterLastModified = it.firstOrNull()?.lastModified ?: 0 + val attesterFingerprint = it.firstOrNull()?.fingerprint + + if (attesterLastModified > cacheLastModified + && publicKeyEntity.fingerprint.equals(attesterFingerprint, true) ) { - cachedRecipientEntity = - updateCachedInfoWithAttesterInfo(cachedRecipientEntity, it, emailLowerCase) + cachedRecipientWithPubKeys = + cachedRecipientWithPubKeys?.let { recipientWithPubKeys -> + updateCachedInfoWithPubKeysFromAttester( + recipientWithPubKeys, + listOf(pgpKeyDetails), + emailLowerCase + ) + } } } } } - cachedRecipientEntity?.let { pgpContacts.add(it.toPgpContact()) } + cachedRecipientWithPubKeys?.let { recipients.add(it) } } catch (e: Exception) { e.printStackTrace() ExceptionUtil.handleError(e) } } } - setResultForRemoteContactsLiveData(type, Result.success(pgpContacts)) + setResultForRemoteContactsLiveData(type, Result.success(recipients)) } catch (e: Exception) { e.printStackTrace() ExceptionUtil.handleError(e) @@ -201,35 +201,23 @@ class RecipientsViewModel(application: Application) : AccountViewModel(applicati } } - private suspend fun updateCachedInfoWithAttesterInfo( - cachedRecipientEntity: RecipientEntity?, - attesterPgpContact: PgpContact, emailLowerCase: String - ): RecipientEntity? { - cachedRecipientEntity ?: return null - val updateCandidate = if ( - cachedRecipientEntity.name.isNullOrEmpty() - && cachedRecipientEntity.email.equals(attesterPgpContact.email, ignoreCase = true) - ) { - attesterPgpContact.toRecipientEntity().copy( - id = cachedRecipientEntity.id, - email = cachedRecipientEntity.email - ) - } else { - attesterPgpContact.toRecipientEntity().copy( - id = cachedRecipientEntity.id, - name = cachedRecipientEntity.name, - email = cachedRecipientEntity.email - ) + private suspend fun updateCachedInfoWithPubKeysFromAttester( + cachedRecipientEntity: RecipientWithPubKeys, + list: List, emailLowerCase: String + ): RecipientWithPubKeys { + val publicKeyEntities = list.map { it.toPublicKeyEntity(cachedRecipientEntity.recipient.email) } + roomDatabase.pubKeysDao().insertWithReplaceSuspend(publicKeyEntities) + val lastVersion = + requireNotNull(roomDatabase.recipientDao().getRecipientWithPubKeysByEmail(emailLowerCase)) + for (publicKeyEntity in lastVersion.publicKeys) { + try { + val result = PgpKey.parseKeys(publicKeyEntity.publicKey).pgpKeyDetailsList + publicKeyEntity.pgpKeyDetails = result.firstOrNull() + } catch (e: Exception) { + e.printStackTrace() + publicKeyEntity.isNotUsable = true + } } - - roomDatabase.recipientDao().updateSuspend(updateCandidate) - val lastVersion = roomDatabase.recipientDao().getRecipientByEmailSuspend(emailLowerCase) - - /*lastVersion?.publicKey?.let { - val result = PgpKey.parseKeys(it).pgpKeyDetailsList - lastVersion.pgpKeyDetails = result.firstOrNull() - }*/ - return lastVersion } @@ -239,9 +227,9 @@ class RecipientsViewModel(application: Application) : AccountViewModel(applicati } } - fun addContact(pgpContact: PgpContact) { + fun addContact(pgpContact: RecipientWithPubKeys) { viewModelScope.launch { - val contact = roomDatabase.recipientDao().getRecipientByEmailSuspend(pgpContact.email) + /*val contact = roomDatabase.recipientDao().getRecipientByEmailSuspend(pgpContact.email) if (contact == null) { val isInserted = roomDatabase.recipientDao().insertSuspend(pgpContact.toRecipientEntity()) > 0 @@ -254,31 +242,29 @@ class RecipientsViewModel(application: Application) : AccountViewModel(applicati context.getString(R.string.could_not_save_new_recipient), Toast.LENGTH_LONG ).show() } - } + }*/ } } - fun updateContact(pgpContact: PgpContact) { + fun updateContact(pgpContact: RecipientWithPubKeys) { viewModelScope.launch { - val contact = roomDatabase.recipientDao().getRecipientByEmailSuspend(pgpContact.email) + /*val contact = roomDatabase.recipientDao().getRecipientByEmailSuspend(pgpContact.email) if (contact != null) { val updateCandidate = pgpContact.toRecipientEntity().copy(id = contact.id) roomDatabase.recipientDao().updateSuspend(updateCandidate) - } + }*/ } } fun copyPubKeysToRecipient(recipientEntity: RecipientEntity?, pgpKeyDetails: PgpKeyDetails) { viewModelScope.launch { recipientEntity?.let { - val recipientEntityFromPrimaryPgpContact = - pgpKeyDetails.primaryPgpContact.toRecipientEntity() - roomDatabase.recipientDao().updateSuspend( - recipientEntityFromPrimaryPgpContact.copy( - id = recipientEntity.id, - email = recipientEntity.email.lowercase(Locale.US), - ) - ) + val existedPubKey = roomDatabase.pubKeysDao() + .getPublicKeysByRecipientAndFingerprint(recipientEntity.email, pgpKeyDetails.fingerprint) + if (existedPubKey == null) { + roomDatabase.pubKeysDao() + .insertSuspend(pgpKeyDetails.toPublicKeyEntity(recipientEntity.email)) + } } } } @@ -310,34 +296,34 @@ class RecipientsViewModel(application: Application) : AccountViewModel(applicati private fun setResultForRemoteContactsLiveData( type: RecipientEntity.Type, - result: Result> + result: Result> ) { when (type) { RecipientEntity.Type.TO -> { - contactsToLiveData.value = result + recipientsToLiveData.value = result } RecipientEntity.Type.CC -> { - contactsCcLiveData.value = result + recipientsCcLiveData.value = result } RecipientEntity.Type.BCC -> { - contactsBccLiveData.value = result + recipientsBccLiveData.value = result } } } /** - * Get information about [PgpContact] from the remote server. + * Get information about [RecipientWithPubKeys] from the remote server. * * @param email Used to generate a request to the server. - * @return [PgpContact] + * @return [RecipientWithPubKeys] * @throws IOException */ - private suspend fun getPgpContactInfoFromServer( + private suspend fun getPgpInfoFromServer( email: String? = null, fingerprint: String? = null - ): PgpContact? = withContext(Dispatchers.IO) { + ): List? = withContext(Dispatchers.IO) { try { val activeAccount = getActiveAccountSuspend() val response = apiRepository.pubLookup( @@ -350,10 +336,9 @@ class RecipientsViewModel(application: Application) : AccountViewModel(applicati Result.Status.SUCCESS -> { val pubKeyString = response.data?.pubkey if (pubKeyString?.isNotEmpty() == true) { - PgpKey.parseKeys(pubKeyString).pgpKeyDetailsList.firstOrNull()?.let { - val pgpContact = it.primaryPgpContact - pgpContact.pgpKeyDetails = it - return@withContext pgpContact + val parsedResult = PgpKey.parseKeys(pubKeyString).pgpKeyDetailsList + if (parsedResult.isNotEmpty()) { + return@withContext parsedResult } } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/workmanager/sync/LoadContactsWorker.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/workmanager/sync/LoadRecipientsWorker.kt similarity index 87% rename from FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/workmanager/sync/LoadContactsWorker.kt rename to FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/workmanager/sync/LoadRecipientsWorker.kt index c0f8b2cc4d..0da073b3ed 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/workmanager/sync/LoadContactsWorker.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/workmanager/sync/LoadRecipientsWorker.kt @@ -35,14 +35,14 @@ import javax.mail.Store import javax.mail.internet.InternetAddress /** - * This [CoroutineWorker] loads information about contacts from the SENT folder. + * This [CoroutineWorker] loads information about recipients from the SENT folder. * * @author Denis Bondarenko * Date: 23.04.2018 * Time: 14:53 * E-mail: DenBond7@gmail.com */ -class LoadContactsWorker(context: Context, params: WorkerParameters) : +class LoadRecipientsWorker(context: Context, params: WorkerParameters) : BaseSyncWorker(context, params) { override suspend fun runIMAPAction(accountEntity: AccountEntity, store: Store) { fetchContacts(accountEntity, store) @@ -65,9 +65,9 @@ class LoadContactsWorker(context: Context, params: WorkerParameters) : if (msgs.isNotEmpty()) { val fetchProfile = FetchProfile() - fetchProfile.add(Message.RecipientType.TO.toString().uppercase(Locale.getDefault())) - fetchProfile.add(Message.RecipientType.CC.toString().uppercase(Locale.getDefault())) - fetchProfile.add(Message.RecipientType.BCC.toString().uppercase(Locale.getDefault())) + fetchProfile.add(Message.RecipientType.TO.toString().uppercase()) + fetchProfile.add(Message.RecipientType.CC.toString().uppercase()) + fetchProfile.add(Message.RecipientType.BCC.toString().uppercase()) imapFolder.fetch(msgs, fetchProfile) return@fetchContactsInternal msgs @@ -160,36 +160,36 @@ class LoadContactsWorker(context: Context, params: WorkerParameters) : } val recipientDao = FlowCryptRoomDatabase.getDatabase(applicationContext).recipientDao() - val availableContacts = recipientDao.getAllRecipients() + val availableRecipients = recipientDao.getAllRecipients() - val contactsInDatabase = HashSet() - val contactsWhichWillBeUpdated = HashSet() - val contactsWhichWillBeCreated = HashSet() - val contactsByEmailMap = HashMap() + val recipientsInDatabase = HashSet() + val recipientsWhichWillBeUpdated = HashSet() + val recipientsWhichWillBeCreated = HashSet() + val recipientsByEmailMap = HashMap() val newCandidates = mutableListOf() val updateCandidates = mutableListOf() - for (contact in availableContacts) { - contactsInDatabase.add(contact.email.lowercase()) - contactsByEmailMap[contact.email.lowercase()] = contact + for (recipientEntity in availableRecipients) { + recipientsInDatabase.add(recipientEntity.email.lowercase()) + recipientsByEmailMap[recipientEntity.email.lowercase()] = recipientEntity } for (emailAndNamePair in emailAndNamePairs) { - if (contactsInDatabase.contains(emailAndNamePair.email)) { - val recipientEntity = contactsByEmailMap[emailAndNamePair.email] + if (recipientsInDatabase.contains(emailAndNamePair.email)) { + val recipientEntity = recipientsByEmailMap[emailAndNamePair.email] if (recipientEntity?.email.isNullOrEmpty()) { - if (!contactsWhichWillBeUpdated.contains(emailAndNamePair.email)) { + if (!recipientsWhichWillBeUpdated.contains(emailAndNamePair.email)) { emailAndNamePair.email?.let { - contactsWhichWillBeUpdated.add(it) + recipientsWhichWillBeUpdated.add(it) } recipientEntity?.copy(name = emailAndNamePair.name)?.let { updateCandidates.add(it) } } } } else { - if (!contactsWhichWillBeCreated.contains(emailAndNamePair.email)) { + if (!recipientsWhichWillBeCreated.contains(emailAndNamePair.email)) { emailAndNamePair.email?.let { - contactsWhichWillBeCreated.add(it) + recipientsWhichWillBeCreated.add(it) newCandidates.add(RecipientEntity(email = it, name = emailAndNamePair.name)) } } @@ -222,7 +222,7 @@ class LoadContactsWorker(context: Context, params: WorkerParameters) : for (address in addresses) { emailAndNamePairs.add( EmailAndNamePair( - address.address.lowercase(Locale.getDefault()), address.personal + address.address.lowercase(), address.personal ) ) } @@ -254,7 +254,7 @@ class LoadContactsWorker(context: Context, params: WorkerParameters) : .enqueueUniqueWork( GROUP_UNIQUE_TAG, ExistingWorkPolicy.KEEP, - OneTimeWorkRequestBuilder() + OneTimeWorkRequestBuilder() .addTag(TAG_SYNC) .setConstraints(constraints) .build() diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/model/KeyImportDetails.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/model/KeyImportDetails.kt index 4155e8b356..1e71c1f154 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/model/KeyImportDetails.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/model/KeyImportDetails.kt @@ -7,6 +7,7 @@ package com.flowcrypt.email.model import android.os.Parcel import android.os.Parcelable +import com.flowcrypt.email.database.entity.relation.RecipientWithPubKeys import com.flowcrypt.email.security.model.PrivateKeySourceType /** @@ -28,18 +29,45 @@ data class KeyImportDetails constructor( val value: String, val sourceType: SourceType, val isPrivateKey: Boolean = false, - val pgpContact: PgpContact? = null + val recipientWithPubKeys: RecipientWithPubKeys? = null ) : Parcelable { - constructor(value: String, sourceType: SourceType) : this(null, value, sourceType, true) + constructor(parcel: Parcel) : this( + parcel.readString(), + parcel.readString()!!, + parcel.readParcelable(SourceType::class.java.classLoader)!!, + parcel.readByte() != 0.toByte(), + parcel.readParcelable(RecipientWithPubKeys::class.java.classLoader) + ) + + constructor(value: String, sourceType: SourceType) : this( + keyName = null, + value = value, + sourceType = sourceType, + isPrivateKey = true + ) + constructor(value: String, sourceType: SourceType, isPrivateKey: Boolean) : this( - null, - value, - sourceType, - isPrivateKey, - null + keyName = null, + value = value, + sourceType = sourceType, + isPrivateKey = isPrivateKey, + recipientWithPubKeys = null ) + override fun describeContents(): Int { + return 0 + } + + override fun writeToParcel(dest: Parcel, flags: Int) = + with(dest) { + writeString(keyName) + writeString(value) + writeParcelable(sourceType, flags) + writeInt((if (isPrivateKey) 1 else 0)) + writeParcelable(recipientWithPubKeys, flags) + } + /** * The key available types. */ @@ -71,33 +99,8 @@ data class KeyImportDetails constructor( } } - constructor(source: Parcel) : this( - source.readString(), - source.readString()!!, - source.readParcelable(SourceType::class.java.classLoader)!!, - source.readInt() == 1, - source.readParcelable(PgpContact::class.java.classLoader)!! - ) - - override fun describeContents(): Int { - return 0 - } - - override fun writeToParcel(dest: Parcel, flags: Int) = - with(dest) { - writeString(keyName) - writeString(value) - writeParcelable(sourceType, flags) - writeInt((if (isPrivateKey) 1 else 0)) - writeParcelable(pgpContact, flags) - } - - companion object { - @JvmField - val CREATOR: Parcelable.Creator = - object : Parcelable.Creator { - override fun createFromParcel(source: Parcel): KeyImportDetails = KeyImportDetails(source) - override fun newArray(size: Int): Array = arrayOfNulls(size) - } + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): KeyImportDetails = KeyImportDetails(parcel) + override fun newArray(size: Int): Array = arrayOfNulls(size) } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/model/PgpContact.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/model/PgpContact.kt deleted file mode 100644 index 223acdd797..0000000000 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/model/PgpContact.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com - * Contributors: DenBond7 - */ - -package com.flowcrypt.email.model - -import android.os.Parcel -import android.os.Parcelable -import com.flowcrypt.email.database.entity.PublicKeyEntity -import com.flowcrypt.email.database.entity.RecipientEntity -import com.flowcrypt.email.security.model.PgpKeyDetails -import java.util.ArrayList -import javax.mail.internet.AddressException -import javax.mail.internet.InternetAddress - -data class PgpContact constructor( - var email: String, - var name: String? = null, - var pubkey: String? = null, - var hasPgp: Boolean = false, - var client: String? = null, - var fingerprint: String? = null, - var lastUse: Long = 0, - var pgpKeyDetails: PgpKeyDetails? = null, - var hasNotUsablePubKey: Boolean = false -) : Parcelable { - - constructor(source: Parcel) : this( - source.readString()!!, - source.readString(), - source.readString(), - source.readInt() == 1, - source.readString(), - source.readString(), - source.readLong(), - source.readParcelable(PgpKeyDetails::class.java.classLoader), - source.readInt() == 1 - ) - - constructor(email: String, name: String?) : this(email) { - this.name = name - } - - override fun describeContents(): Int { - return 0 - } - - override fun writeToParcel(dest: Parcel, flags: Int) = - with(dest) { - writeString(email) - writeString(name) - writeString(pubkey) - writeInt((if (hasPgp) 1 else 0)) - writeString(client) - writeString(fingerprint) - writeLong(lastUse) - writeParcelable(pgpKeyDetails, flags) - writeInt((if (hasNotUsablePubKey) 1 else 0)) - } - - fun toRecipientEntity(): RecipientEntity { - return RecipientEntity( - email = email.lowercase(), - name = name, - lastUse = lastUse - ) - } - - fun toPubKey(): PublicKeyEntity { - return PublicKeyEntity( - recipient = email, - fingerprint = fingerprint!!, - publicKey = pubkey!!.toByteArray() - ) - } - - companion object { - @JvmField - val CREATOR: Parcelable.Creator = object : Parcelable.Creator { - override fun createFromParcel(source: Parcel): PgpContact = PgpContact(source) - override fun newArray(size: Int): Array = arrayOfNulls(size) - } - - fun determinePgpContacts(users: List): ArrayList { - val pgpContacts = ArrayList() - for (user in users) { - try { - val internetAddresses = InternetAddress.parse(user) - - for (internetAddress in internetAddresses) { - val email = internetAddress.address.lowercase() - val name = internetAddress.personal - - pgpContacts.add(PgpContact(email, name)) - } - } catch (e: AddressException) { - e.printStackTrace() - } - } - - return pgpContacts - } - } -} diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/model/PublicKeyInfo.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/model/PublicKeyInfo.kt index 01ad2aefe0..27b4feca9c 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/model/PublicKeyInfo.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/model/PublicKeyInfo.kt @@ -31,16 +31,4 @@ data class PublicKeyInfo constructor( email = keyOwner.lowercase() ) } - - fun toPgpContact(): PgpContact { - return PgpContact( - email = keyOwner, - name = null, - pubkey = publicKey, - hasPgp = true, - client = null, - fingerprint = fingerprint, - lastUse = 0 - ) - } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/security/model/PgpKeyDetails.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/security/model/PgpKeyDetails.kt index cd7086bd87..135809258b 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/security/model/PgpKeyDetails.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/security/model/PgpKeyDetails.kt @@ -10,11 +10,9 @@ import android.os.Parcelable import android.util.Patterns import com.flowcrypt.email.database.entity.AccountEntity import com.flowcrypt.email.database.entity.KeyEntity -import com.flowcrypt.email.model.PgpContact -import com.flowcrypt.email.util.exception.FlowCryptException +import com.flowcrypt.email.database.entity.PublicKeyEntity import com.google.gson.annotations.Expose import com.google.gson.annotations.SerializedName -import java.util.ArrayList import java.util.Locale import javax.mail.internet.AddressException import javax.mail.internet.InternetAddress @@ -42,11 +40,6 @@ data class PgpKeyDetails constructor( var tempPassphrase: CharArray? = null, var passphraseType: KeyEntity.PassphraseType? = null ) : Parcelable { - - val primaryPgpContact: PgpContact - get() = determinePrimaryPgpContact() - val pgpContacts: ArrayList - get() = PgpContact.determinePgpContacts(users) val fingerprint: String get() = ids.first().fingerprint val isPrivate: Boolean @@ -97,37 +90,8 @@ data class PgpKeyDetails constructor( writeParcelable(passphraseType, flags) } - private fun determinePrimaryPgpContact(): PgpContact { - val address = users.first() - val fingerprintFromKeyId = ids.first().fingerprint - var email: String? = null - var name: String? = null - try { - val internetAddresses = InternetAddress.parse(address) - email = internetAddresses.first().address - name = internetAddresses.first().personal - } catch (e: AddressException) { - e.printStackTrace() - val pattern = Patterns.EMAIL_ADDRESS - val matcher = pattern.matcher(users.first()) - if (matcher.find()) { - email = matcher.group() - name = email - } - } - - if (email == null) { - throw object : FlowCryptException("No user ids with mail address") {} - } - - return PgpContact( - email = email.toLowerCase(Locale.US), - name = name, - pubkey = publicKey, - hasPgp = true, - client = null, - fingerprint = fingerprintFromKeyId - ) + fun getUserIdsAsSingleString(): String { + return mimeAddresses.joinToString { it.address } } private fun parseMimeAddresses(): List { @@ -137,7 +101,12 @@ data class PgpKeyDetails constructor( try { results.addAll(listOf(*InternetAddress.parse(user))) } catch (e: AddressException) { - //do nothing + e.printStackTrace() + val pattern = Patterns.EMAIL_ADDRESS + val matcher = pattern.matcher(user) + if (matcher.find()) { + results.add(InternetAddress(matcher.group())) + } } } @@ -147,7 +116,7 @@ data class PgpKeyDetails constructor( fun toKeyEntity(accountEntity: AccountEntity): KeyEntity { return KeyEntity( fingerprint = fingerprint, - account = accountEntity.email.toLowerCase(Locale.US), + account = accountEntity.email.lowercase(Locale.US), accountType = accountEntity.accountType, source = PrivateKeySourceType.BACKUP.toString(), publicKey = publicKey.toByteArray(), @@ -159,6 +128,14 @@ data class PgpKeyDetails constructor( ) } + fun toPublicKeyEntity(recipient: String): PublicKeyEntity { + return PublicKeyEntity( + recipient = recipient, + fingerprint = fingerprint, + publicKey = publicKey.toByteArray() + ) + } + override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/service/EmailAndNameUpdaterService.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/service/EmailAndNameUpdaterService.kt index 592efe46d3..5c24b8aa04 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/service/EmailAndNameUpdaterService.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/service/EmailAndNameUpdaterService.kt @@ -29,7 +29,7 @@ import java.util.ArrayList * "save that person's name into the existing DB record" * * * else: - * "save that email, name pair into DB like so: new PgpContact(email, name);" + * "save that email, name pair into DB like so: new RecipientEntity(email, name);" * * * @author DenBond7 diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/service/PrepareOutgoingMessagesJobIntentService.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/service/PrepareOutgoingMessagesJobIntentService.kt index c45fd1bfb8..c68c2050ff 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/service/PrepareOutgoingMessagesJobIntentService.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/service/PrepareOutgoingMessagesJobIntentService.kt @@ -43,7 +43,6 @@ import java.io.File import java.io.IOException import java.io.InputStream import java.util.ArrayList -import java.util.Locale import java.util.UUID import javax.mail.Message @@ -79,7 +78,7 @@ class PrepareOutgoingMessagesJobIntentService : JobIntentService() { intent.getParcelableExtra(EXTRA_KEY_OUTGOING_MESSAGE_INFO) ?: return val accountEntity = - roomDatabase.accountDao().getAccount(outgoingMsgInfo.account.lowercase(Locale.US)) + roomDatabase.accountDao().getAccount(outgoingMsgInfo.account.lowercase()) ?: return val uid = outgoingMsgInfo.uid diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/ImportPgpContactActivity.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/ImportPgpContactActivity.kt index 5749dbe706..2714c9838b 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/ImportPgpContactActivity.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/ImportPgpContactActivity.kt @@ -35,14 +35,14 @@ import java.util.* /** * This [Activity] retrieves a public keys string from the different sources and sends it to - * [PreviewImportPgpContactActivity] + * [PreviewImportRecipientWithPubKeysActivity] * * @author Denis Bondarenko * Date: 04.05.2018 * Time: 17:07 * E-mail: DenBond7@gmail.com */ -class ImportPgpContactActivity : BaseImportKeyActivity() { +class ImportRecipientWithPubKeysActivity : BaseImportKeyActivity() { private val recipientsViewModel: RecipientsViewModel by viewModels() private var editTextEmailOrId: EditText? = null @@ -110,7 +110,7 @@ class ImportPgpContactActivity : BaseImportKeyActivity() { if (keyDetailsList.isNotEmpty()) { UIUtil.exchangeViewVisibility(true, layoutProgress, layoutContentView) startActivityForResult( - PreviewImportPgpContactActivity.newIntent( + PreviewImportRecipientWithPubKeysActivity.newIntent( this, keyImportModel!! .keyString ), REQUEST_CODE_RUN_PREVIEW_ACTIVITY @@ -125,7 +125,7 @@ class ImportPgpContactActivity : BaseImportKeyActivity() { override fun handleSelectedFile(uri: Uri) { UIUtil.exchangeViewVisibility(true, layoutProgress, layoutContentView) startActivityForResult( - PreviewImportPgpContactActivity.newIntent(this, uri), + PreviewImportRecipientWithPubKeysActivity.newIntent(this, uri), REQUEST_CODE_RUN_PREVIEW_ACTIVITY ) } @@ -147,7 +147,7 @@ class ImportPgpContactActivity : BaseImportKeyActivity() { private fun fetchPubKey() { val v = editTextEmailOrId ?: return - UIUtil.hideSoftInput(this@ImportPgpContactActivity, v) + UIUtil.hideSoftInput(this@ImportRecipientWithPubKeysActivity, v) if (v.text.isNullOrEmpty()) { Toast.makeText(this, R.string.please_type_key_id_or_email, Toast.LENGTH_SHORT).show() @@ -207,7 +207,7 @@ class ImportPgpContactActivity : BaseImportKeyActivity() { val pubkey = pubResponse.pubkey if (!pubkey.isNullOrEmpty()) { startActivityForResult( - PreviewImportPgpContactActivity.newIntent(this, pubkey), + PreviewImportRecipientWithPubKeysActivity.newIntent(this, pubkey), REQUEST_CODE_RUN_PREVIEW_ACTIVITY ) } else { @@ -226,7 +226,7 @@ class ImportPgpContactActivity : BaseImportKeyActivity() { accountEntity = accountEntity, title = context.getString(R.string.add_public_keys_of_your_contacts), throwErrorIfDuplicateFoundEnabled = false, - cls = ImportPgpContactActivity::class.java + cls = ImportRecipientWithPubKeysActivity::class.java ) } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/ImportPublicKeyActivity.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/ImportPublicKeyActivity.kt index fef8af9233..08b49ab809 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/ImportPublicKeyActivity.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/ImportPublicKeyActivity.kt @@ -12,9 +12,9 @@ import android.os.Bundle import androidx.activity.viewModels import com.flowcrypt.email.R import com.flowcrypt.email.database.entity.AccountEntity +import com.flowcrypt.email.database.entity.relation.RecipientWithPubKeys import com.flowcrypt.email.jetpack.viewmodel.RecipientsViewModel import com.flowcrypt.email.model.KeyImportDetails -import com.flowcrypt.email.model.PgpContact import com.flowcrypt.email.security.model.PgpKeyDetails import com.flowcrypt.email.ui.activity.base.BaseImportKeyActivity import com.flowcrypt.email.util.GeneralUtil @@ -30,7 +30,7 @@ import com.google.android.material.snackbar.Snackbar */ class ImportPublicKeyActivity : BaseImportKeyActivity() { - private var pgpContact: PgpContact? = null + private var recipientWithPubKeys: RecipientWithPubKeys? = null private val recipientsViewModel: RecipientsViewModel by viewModels() override val contentViewResourceId: Int @@ -42,7 +42,7 @@ class ImportPublicKeyActivity : BaseImportKeyActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (intent != null && intent.hasExtra(KEY_EXTRA_PGP_CONTACT)) { - this.pgpContact = intent.getParcelableExtra(KEY_EXTRA_PGP_CONTACT) + this.recipientWithPubKeys = intent.getParcelableExtra(KEY_EXTRA_PGP_CONTACT) } else { finish() } @@ -67,7 +67,7 @@ class ImportPublicKeyActivity : BaseImportKeyActivity() { return } - updateInformationAboutPgpContact(key) + updateInformationAboutRecipientWithPubKeys(key) setResult(Activity.RESULT_OK) finish() } else { @@ -78,11 +78,10 @@ class ImportPublicKeyActivity : BaseImportKeyActivity() { } } - private fun updateInformationAboutPgpContact(keyDetails: PgpKeyDetails) { - val pgpContactFromKey = keyDetails.primaryPgpContact - pgpContact?.pubkey = pgpContactFromKey.pubkey - pgpContact?.hasPgp = pgpContact?.pubkey?.isNotEmpty() == true - pgpContact?.let { recipientsViewModel.copyPubKeysToRecipient(it, pgpContactFromKey) } + private fun updateInformationAboutRecipientWithPubKeys(keyDetails: PgpKeyDetails) { + recipientWithPubKeys?.recipient?.let { + recipientsViewModel.copyPubKeysToRecipient(it, keyDetails) + } } companion object { @@ -95,13 +94,13 @@ class ImportPublicKeyActivity : BaseImportKeyActivity() { context: Context?, accountEntity: AccountEntity?, title: String, - pgpContact: PgpContact + recipientWithPubKeys: RecipientWithPubKeys ): Intent { val intent = newIntent( context = context, accountEntity = accountEntity, title = title, throwErrorIfDuplicateFoundEnabled = false, cls = ImportPublicKeyActivity::class.java ) - intent.putExtra(KEY_EXTRA_PGP_CONTACT, pgpContact) + intent.putExtra(KEY_EXTRA_PGP_CONTACT, recipientWithPubKeys) return intent } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/PreviewImportPgpContactActivity.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/PreviewImportPgpContactActivity.kt index 2ec7200d79..9a2c4b87b1 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/PreviewImportPgpContactActivity.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/PreviewImportPgpContactActivity.kt @@ -15,7 +15,7 @@ import android.view.MenuItem import android.view.View import com.flowcrypt.email.R import com.flowcrypt.email.ui.activity.base.BaseBackStackActivity -import com.flowcrypt.email.ui.activity.fragment.PreviewImportPgpContactFragment +import com.flowcrypt.email.ui.activity.fragment.PreviewImportRecipientWithPubKeysFragment import com.flowcrypt.email.ui.activity.settings.FeedbackActivity import com.flowcrypt.email.util.GeneralUtil @@ -27,7 +27,7 @@ import com.flowcrypt.email.util.GeneralUtil * Time: 18:01 * E-mail: DenBond7@gmail.com */ -class PreviewImportPgpContactActivity : BaseBackStackActivity() { +class PreviewImportRecipientWithPubKeysActivity : BaseBackStackActivity() { override val contentViewResourceId: Int get() = R.layout.activity_preview_import_pgp_contact @@ -49,10 +49,11 @@ class PreviewImportPgpContactActivity : BaseBackStackActivity() { val fragmentManager = supportFragmentManager var fragment = - fragmentManager.findFragmentById(R.id.layoutContent) as PreviewImportPgpContactFragment? + fragmentManager.findFragmentById(R.id.layoutContent) as PreviewImportRecipientWithPubKeysFragment? if (fragment == null) { - fragment = PreviewImportPgpContactFragment.newInstance(publicKeysString, publicKeysFileUri) + fragment = + PreviewImportRecipientWithPubKeysFragment.newInstance(publicKeysString, publicKeysFileUri) fragmentManager.beginTransaction().add(R.id.layoutContent, fragment).commit() } } @@ -77,22 +78,22 @@ class PreviewImportPgpContactActivity : BaseBackStackActivity() { val KEY_EXTRA_PUBLIC_KEY_STRING = GeneralUtil.generateUniqueExtraKey( "KEY_EXTRA_PUBLIC_KEY_STRING", - PreviewImportPgpContactActivity::class.java + PreviewImportRecipientWithPubKeysActivity::class.java ) val KEY_EXTRA_PUBLIC_KEYS_FILE_URI = GeneralUtil.generateUniqueExtraKey( "KEY_EXTRA_PUBLIC_KEYS_FILE_URI", - PreviewImportPgpContactActivity::class.java + PreviewImportRecipientWithPubKeysActivity::class.java ) fun newIntent(context: Context, publicKeysString: String?): Intent { - val intent = Intent(context, PreviewImportPgpContactActivity::class.java) + val intent = Intent(context, PreviewImportRecipientWithPubKeysActivity::class.java) intent.putExtra(KEY_EXTRA_PUBLIC_KEY_STRING, publicKeysString) return intent } fun newIntent(context: Context, publicKeysFileUri: Uri): Intent { - val intent = Intent(context, PreviewImportPgpContactActivity::class.java) + val intent = Intent(context, PreviewImportRecipientWithPubKeysActivity::class.java) intent.putExtra(KEY_EXTRA_PUBLIC_KEYS_FILE_URI, publicKeysFileUri) return intent } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/SelectContactsActivity.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/SelectContactsActivity.kt index 5ab0f4336a..08921a399f 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/SelectContactsActivity.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/SelectContactsActivity.kt @@ -27,7 +27,7 @@ import com.flowcrypt.email.extensions.decrementSafely import com.flowcrypt.email.extensions.incrementSafely import com.flowcrypt.email.jetpack.viewmodel.RecipientsViewModel import com.flowcrypt.email.ui.activity.base.BaseBackStackActivity -import com.flowcrypt.email.ui.adapter.ContactsRecyclerViewAdapter +import com.flowcrypt.email.ui.adapter.RecipientsRecyclerViewAdapter import com.flowcrypt.email.util.GeneralUtil import com.flowcrypt.email.util.UIUtil @@ -41,13 +41,13 @@ import com.flowcrypt.email.util.UIUtil * E-mail: DenBond7@gmail.com */ class SelectContactsActivity : BaseBackStackActivity(), - ContactsRecyclerViewAdapter.OnContactActionsListener, SearchView.OnQueryTextListener { + RecipientsRecyclerViewAdapter.OnContactActionsListener, SearchView.OnQueryTextListener { private var progressBar: View? = null private var recyclerViewContacts: RecyclerView? = null private var emptyView: View? = null - private val contactsRecyclerViewAdapter: ContactsRecyclerViewAdapter = - ContactsRecyclerViewAdapter(false) + private val recipientsRecyclerViewAdapter: RecipientsRecyclerViewAdapter = + RecipientsRecyclerViewAdapter(false) private var searchPattern: String? = null private val recipientsViewModel: RecipientsViewModel by viewModels() @@ -65,7 +65,7 @@ class SelectContactsActivity : BaseBackStackActivity(), override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - contactsRecyclerViewAdapter.onContactActionsListener = this + recipientsRecyclerViewAdapter.onContactActionsListener = this //todo-denbond7 need to fix this in the future. Not urgent //val isMultiply = intent.getBooleanExtra(KEY_EXTRA_IS_MULTIPLY, false) @@ -80,7 +80,7 @@ class SelectContactsActivity : BaseBackStackActivity(), drawable?.let { decoration.setDrawable(drawable) } recyclerViewContacts?.addItemDecoration(decoration) recyclerViewContacts?.layoutManager = manager - recyclerViewContacts?.adapter = contactsRecyclerViewAdapter + recyclerViewContacts?.adapter = recipientsRecyclerViewAdapter if (!TextUtils.isEmpty(title)) { supportActionBar?.title = title @@ -146,7 +146,7 @@ class SelectContactsActivity : BaseBackStackActivity(), if (it.data.isNullOrEmpty()) { UIUtil.exchangeViewVisibility(true, emptyView, recyclerViewContacts) } else { - contactsRecyclerViewAdapter.swap(it.data) + recipientsRecyclerViewAdapter.swap(it.data) UIUtil.exchangeViewVisibility(false, emptyView, recyclerViewContacts) } countingIdlingResourceForFilter.decrementSafely() diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/base/BaseSyncActivity.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/base/BaseSyncActivity.kt index ee0f1c158b..c6b3cec86d 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/base/BaseSyncActivity.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/base/BaseSyncActivity.kt @@ -9,7 +9,7 @@ import com.flowcrypt.email.jetpack.workmanager.sync.ArchiveMsgsWorker import com.flowcrypt.email.jetpack.workmanager.sync.DeleteMessagesPermanentlyWorker import com.flowcrypt.email.jetpack.workmanager.sync.DeleteMessagesWorker import com.flowcrypt.email.jetpack.workmanager.sync.EmptyTrashWorker -import com.flowcrypt.email.jetpack.workmanager.sync.LoadContactsWorker +import com.flowcrypt.email.jetpack.workmanager.sync.LoadRecipientsWorker import com.flowcrypt.email.jetpack.workmanager.sync.MovingToInboxWorker import com.flowcrypt.email.jetpack.workmanager.sync.UpdateLabelsWorker import com.flowcrypt.email.jetpack.workmanager.sync.UpdateMsgsSeenStateWorker @@ -35,7 +35,7 @@ abstract class BaseSyncActivity : BaseActivity() { * Load information about contacts. */ fun loadContactsIfNeeded() { - LoadContactsWorker.enqueue(this) + LoadRecipientsWorker.enqueue(this) } /** diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/ContactsListFragment.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/ContactsListFragment.kt index 3507d066d2..cf5fc0fbc0 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/ContactsListFragment.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/ContactsListFragment.kt @@ -20,9 +20,9 @@ import com.flowcrypt.email.api.retrofit.response.base.Result import com.flowcrypt.email.database.entity.RecipientEntity import com.flowcrypt.email.extensions.navController import com.flowcrypt.email.jetpack.viewmodel.RecipientsViewModel -import com.flowcrypt.email.ui.activity.ImportPgpContactActivity +import com.flowcrypt.email.ui.activity.ImportRecipientWithPubKeysActivity import com.flowcrypt.email.ui.activity.fragment.base.BaseFragment -import com.flowcrypt.email.ui.adapter.ContactsRecyclerViewAdapter +import com.flowcrypt.email.ui.adapter.RecipientsRecyclerViewAdapter import com.flowcrypt.email.util.UIUtil /** @@ -33,20 +33,21 @@ import com.flowcrypt.email.util.UIUtil * Time: 6:11 PM * E-mail: DenBond7@gmail.com */ -class ContactsListFragment : BaseFragment(), ContactsRecyclerViewAdapter.OnContactActionsListener { +class ContactsListFragment : BaseFragment(), + RecipientsRecyclerViewAdapter.OnContactActionsListener { private var progressBar: View? = null private var recyclerViewContacts: RecyclerView? = null private var emptyView: View? = null - private val contactsRecyclerViewAdapter: ContactsRecyclerViewAdapter = - ContactsRecyclerViewAdapter(true) + private val recipientsRecyclerViewAdapter: RecipientsRecyclerViewAdapter = + RecipientsRecyclerViewAdapter(true) private val recipientsViewModel: RecipientsViewModel by viewModels() override val contentResourceId: Int = R.layout.fragment_contacts_list override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - contactsRecyclerViewAdapter.onContactActionsListener = this + recipientsRecyclerViewAdapter.onContactActionsListener = this } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -97,12 +98,12 @@ class ContactsListFragment : BaseFragment(), ContactsRecyclerViewAdapter.OnConta drawable?.let { decoration.setDrawable(drawable) } recyclerViewContacts?.addItemDecoration(decoration) recyclerViewContacts?.layoutManager = manager - recyclerViewContacts?.adapter = contactsRecyclerViewAdapter + recyclerViewContacts?.adapter = recipientsRecyclerViewAdapter root.findViewById(R.id.floatActionButtonImportPublicKey)?.setOnClickListener { context?.let { startActivityForResult( - ImportPgpContactActivity.newIntent(it, account), + ImportRecipientWithPubKeysActivity.newIntent(it, account), REQUEST_CODE_START_IMPORT_PUB_KEY_ACTIVITY ) } @@ -121,7 +122,7 @@ class ContactsListFragment : BaseFragment(), ContactsRecyclerViewAdapter.OnConta if (it.data.isNullOrEmpty()) { UIUtil.exchangeViewVisibility(true, emptyView, recyclerViewContacts) } else { - contactsRecyclerViewAdapter.swap(it.data) + recipientsRecyclerViewAdapter.swap(it.data) UIUtil.exchangeViewVisibility(false, emptyView, recyclerViewContacts) } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/MessageDetailsFragment.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/MessageDetailsFragment.kt index 9a9d8571d3..485bee5a4e 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/MessageDetailsFragment.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/MessageDetailsFragment.kt @@ -72,7 +72,6 @@ import com.flowcrypt.email.jetpack.viewmodel.RecipientsViewModel import com.flowcrypt.email.jetpack.viewmodel.factory.MsgDetailsViewModelFactory import com.flowcrypt.email.model.MessageEncryptionType import com.flowcrypt.email.model.MessageType -import com.flowcrypt.email.model.PgpContact import com.flowcrypt.email.security.SecurityUtils import com.flowcrypt.email.security.pgp.PgpDecrypt import com.flowcrypt.email.service.attachment.AttachmentDownloadManagerService @@ -983,11 +982,11 @@ class MessageDetailsFragment : BaseFragment(), ProgressBehaviour, View.OnClickLi } val keyDetails = block.keyDetails - val pgpContact = keyDetails?.primaryPgpContact ?: PgpContact(email = "") + val userIds = keyDetails?.getUserIdsAsSingleString() - if (!TextUtils.isEmpty(pgpContact.email)) { + if (userIds?.isNotEmpty() == true) { val keyOwner = pubKeyView.findViewById(R.id.textViewKeyOwnerTemplate) - keyOwner.text = getString(R.string.template_message_part_public_key_owner, pgpContact.email) + keyOwner.text = getString(R.string.template_message_part_public_key_owner, userIds) } val fingerprint = pubKeyView.findViewById(R.id.textViewFingerprintTemplate) @@ -1000,14 +999,14 @@ class MessageDetailsFragment : BaseFragment(), ProgressBehaviour, View.OnClickLi textViewPgpPublicKey.text = clipLargeText(block.keyDetails?.publicKey ?: block.content) - val existingPgpContact = block.existingPgpContact + val existingRecipientWithPubKeys = block.existingRecipientWithPubKeys val button = pubKeyView.findViewById