kopia lustrzana https://github.com/ryukoposting/Signal-Android
Ensure identity records are good before trying to send media.
rodzic
5b91c927b6
commit
b0458f10a3
|
@ -1,16 +1,11 @@
|
|||
package org.thoughtcrime.securesms.conversation.mutiselect.forward
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.util.Consumer
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
|
||||
import org.thoughtcrime.securesms.contacts.paged.RecipientSearchKey
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||
import org.thoughtcrime.securesms.database.identity.IdentityRecordList
|
||||
import org.thoughtcrime.securesms.database.model.IdentityRecord
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.sharing.MultiShareArgs
|
||||
|
@ -20,25 +15,12 @@ import org.whispersystems.libsignal.util.guava.Optional
|
|||
|
||||
class MultiselectForwardRepository(context: Context) {
|
||||
|
||||
private val context = context.applicationContext
|
||||
|
||||
class MultiselectForwardResultHandlers(
|
||||
val onAllMessageSentSuccessfully: () -> Unit,
|
||||
val onSomeMessagesFailed: () -> Unit,
|
||||
val onAllMessagesFailed: () -> Unit
|
||||
)
|
||||
|
||||
fun checkForBadIdentityRecords(contactSearchKeys: Set<ContactSearchKey>, consumer: Consumer<List<IdentityRecord>>) {
|
||||
SignalExecutors.BOUNDED.execute {
|
||||
val recipients: List<Recipient> = contactSearchKeys
|
||||
.filterIsInstance<RecipientSearchKey>()
|
||||
.map { Recipient.resolved(it.recipientId) }
|
||||
val identityRecordList: IdentityRecordList = ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecords(recipients)
|
||||
|
||||
consumer.accept(identityRecordList.untrustedRecords)
|
||||
}
|
||||
}
|
||||
|
||||
fun canSelectRecipient(recipientId: Optional<RecipientId>): Single<Boolean> {
|
||||
if (!recipientId.isPresent) {
|
||||
return Single.just(true)
|
||||
|
|
|
@ -4,7 +4,9 @@ import androidx.lifecycle.LiveData
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
|
||||
import org.thoughtcrime.securesms.contacts.paged.RecipientSearchKey
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.mediasend.v2.UntrustedRecords
|
||||
import org.thoughtcrime.securesms.sharing.MultiShareArgs
|
||||
import org.thoughtcrime.securesms.util.livedata.Store
|
||||
|
||||
|
@ -23,7 +25,7 @@ class MultiselectForwardViewModel(
|
|||
store.update { it.copy(stage = MultiselectForwardState.Stage.FirstConfirmation) }
|
||||
} else {
|
||||
store.update { it.copy(stage = MultiselectForwardState.Stage.LoadingIdentities) }
|
||||
repository.checkForBadIdentityRecords(selectedContacts) { identityRecords ->
|
||||
UntrustedRecords.checkForBadIdentityRecords(selectedContacts.filterIsInstance(RecipientSearchKey::class.java).toSet()) { identityRecords ->
|
||||
if (identityRecords.isEmpty()) {
|
||||
performSend(additionalMessage, selectedContacts)
|
||||
} else {
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.components.emoji.EmojiEventListener
|
|||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchConfiguration
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchState
|
||||
import org.thoughtcrime.securesms.conversation.mutiselect.forward.SearchConfigurationProvider
|
||||
import org.thoughtcrime.securesms.conversation.ui.error.SafetyNumberChangeDialog
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardPageFragment
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.search.EmojiSearchFragment
|
||||
import org.thoughtcrime.securesms.mediasend.Media
|
||||
|
@ -146,13 +147,18 @@ class MediaSelectionActivity :
|
|||
}
|
||||
|
||||
override fun onSendError(error: Throwable) {
|
||||
setResult(RESULT_CANCELED)
|
||||
if (error is UntrustedRecords.UntrustedRecordsException) {
|
||||
Log.w(TAG, "Send failed due to untrusted identities.")
|
||||
SafetyNumberChangeDialog.show(supportFragmentManager, error.untrustedRecords)
|
||||
} else {
|
||||
setResult(RESULT_CANCELED)
|
||||
|
||||
// TODO [alex] - Toast
|
||||
Log.w(TAG, "Failed to send message.", error)
|
||||
// TODO [alex] - Toast
|
||||
Log.w(TAG, "Failed to send message.", error)
|
||||
|
||||
finish()
|
||||
overridePendingTransition(R.anim.stationary, R.anim.camera_slide_to_bottom)
|
||||
finish()
|
||||
overridePendingTransition(R.anim.stationary, R.anim.camera_slide_to_bottom)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNoMediaSelected() {
|
||||
|
|
|
@ -280,17 +280,19 @@ class MediaSelectionViewModel(
|
|||
fun send(
|
||||
selectedContacts: List<RecipientSearchKey> = emptyList()
|
||||
): Maybe<MediaSendActivityResult> {
|
||||
return repository.send(
|
||||
store.state.selectedMedia,
|
||||
store.state.editorStateMap,
|
||||
store.state.quality,
|
||||
store.state.message,
|
||||
store.state.transportOption.isSms,
|
||||
isViewOnceEnabled(),
|
||||
destination.getRecipientSearchKey(),
|
||||
if (selectedContacts.isNotEmpty()) selectedContacts else destination.getRecipientSearchKeyList(),
|
||||
MentionAnnotation.getMentionsFromAnnotations(store.state.message),
|
||||
store.state.transportOption
|
||||
return UntrustedRecords.checkForBadIdentityRecords(selectedContacts.toSet()).andThen(
|
||||
repository.send(
|
||||
store.state.selectedMedia,
|
||||
store.state.editorStateMap,
|
||||
store.state.quality,
|
||||
store.state.message,
|
||||
store.state.transportOption.isSms,
|
||||
isViewOnceEnabled(),
|
||||
destination.getRecipientSearchKey(),
|
||||
selectedContacts.ifEmpty { destination.getRecipientSearchKeyList() },
|
||||
MentionAnnotation.getMentionsFromAnnotations(store.state.message),
|
||||
store.state.transportOption
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package org.thoughtcrime.securesms.mediasend.v2
|
||||
|
||||
import androidx.core.util.Consumer
|
||||
import io.reactivex.rxjava3.core.Completable
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.thoughtcrime.securesms.contacts.paged.RecipientSearchKey
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.IdentityRecord
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
object UntrustedRecords {
|
||||
|
||||
fun checkForBadIdentityRecords(contactSearchKeys: Set<RecipientSearchKey>): Completable {
|
||||
return Completable.fromAction {
|
||||
val untrustedRecords: List<IdentityRecord> = checkForBadIdentityRecordsSync(contactSearchKeys)
|
||||
if (untrustedRecords.isNotEmpty()) {
|
||||
throw UntrustedRecordsException(untrustedRecords)
|
||||
}
|
||||
}.subscribeOn(Schedulers.io())
|
||||
}
|
||||
|
||||
fun checkForBadIdentityRecords(contactSearchKeys: Set<RecipientSearchKey>, consumer: Consumer<List<IdentityRecord>>) {
|
||||
SignalExecutors.BOUNDED.execute {
|
||||
consumer.accept(checkForBadIdentityRecordsSync(contactSearchKeys))
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkForBadIdentityRecordsSync(contactSearchKeys: Set<RecipientSearchKey>): List<IdentityRecord> {
|
||||
val recipients: List<Recipient> = contactSearchKeys
|
||||
.map { Recipient.resolved(it.recipientId) }
|
||||
.map { recipient ->
|
||||
when {
|
||||
recipient.isGroup -> recipient.participants
|
||||
recipient.isDistributionList -> Recipient.resolvedList(SignalDatabase.distributionLists.getMembers(recipient.distributionListId.get()))
|
||||
else -> listOf(recipient)
|
||||
}
|
||||
}
|
||||
.flatten()
|
||||
|
||||
return ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecords(recipients).untrustedRecords
|
||||
}
|
||||
|
||||
class UntrustedRecordsException(val untrustedRecords: List<IdentityRecord>) : Throwable()
|
||||
}
|
|
@ -2,19 +2,17 @@ package org.thoughtcrime.securesms.mediasend.v2.text.send
|
|||
|
||||
import android.content.Context
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.signal.core.util.ThreadUtil
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
|
||||
import org.thoughtcrime.securesms.contacts.paged.RecipientSearchKey
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||
import org.thoughtcrime.securesms.database.identity.IdentityRecordList
|
||||
import org.thoughtcrime.securesms.database.model.StoryType
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.StoryTextPost
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.fonts.TextFont
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview
|
||||
import org.thoughtcrime.securesms.mediasend.v2.UntrustedRecords
|
||||
import org.thoughtcrime.securesms.mediasend.v2.text.TextStoryPostCreationState
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage
|
||||
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage
|
||||
|
@ -35,28 +33,23 @@ class TextStoryPostSendRepository(context: Context) {
|
|||
}
|
||||
|
||||
fun send(contactSearchKey: Set<ContactSearchKey>, textStoryPostCreationState: TextStoryPostCreationState, linkPreview: LinkPreview?): Single<TextStoryPostSendResult> {
|
||||
return checkForBadIdentityRecords(contactSearchKey).flatMap { result ->
|
||||
if (result is TextStoryPostSendResult.Success) {
|
||||
performSend(contactSearchKey, textStoryPostCreationState, linkPreview)
|
||||
} else {
|
||||
Single.just(result)
|
||||
return UntrustedRecords
|
||||
.checkForBadIdentityRecords(contactSearchKey.filterIsInstance(RecipientSearchKey::class.java).toSet())
|
||||
.toSingleDefault<TextStoryPostSendResult>(TextStoryPostSendResult.Success)
|
||||
.onErrorReturn {
|
||||
if (it is UntrustedRecords.UntrustedRecordsException) {
|
||||
TextStoryPostSendResult.UntrustedRecordsError(it.untrustedRecords)
|
||||
} else {
|
||||
TextStoryPostSendResult.Failure
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkForBadIdentityRecords(contactSearchKeys: Set<ContactSearchKey>): Single<TextStoryPostSendResult> {
|
||||
return Single.fromCallable {
|
||||
val recipients: List<Recipient> = contactSearchKeys
|
||||
.filterIsInstance<RecipientSearchKey>()
|
||||
.map { Recipient.resolved(it.recipientId) }
|
||||
val identityRecordList: IdentityRecordList = ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecords(recipients)
|
||||
|
||||
if (identityRecordList.untrustedRecords.isNotEmpty()) {
|
||||
TextStoryPostSendResult.UntrustedRecordsError(identityRecordList.untrustedRecords)
|
||||
} else {
|
||||
TextStoryPostSendResult.Success
|
||||
.flatMap { result ->
|
||||
if (result is TextStoryPostSendResult.Success) {
|
||||
performSend(contactSearchKey, textStoryPostCreationState, linkPreview)
|
||||
} else {
|
||||
Single.just(result)
|
||||
}
|
||||
}
|
||||
}.subscribeOn(Schedulers.io())
|
||||
}
|
||||
|
||||
private fun performSend(contactSearchKey: Set<ContactSearchKey>, textStoryPostCreationState: TextStoryPostCreationState, linkPreview: LinkPreview?): Single<TextStoryPostSendResult> {
|
||||
|
|
|
@ -4,5 +4,6 @@ import org.thoughtcrime.securesms.database.model.IdentityRecord
|
|||
|
||||
sealed class TextStoryPostSendResult {
|
||||
object Success : TextStoryPostSendResult()
|
||||
object Failure : TextStoryPostSendResult()
|
||||
data class UntrustedRecordsError(val untrustedRecords: List<IdentityRecord>) : TextStoryPostSendResult()
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue