mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-23 10:20:25 +01:00
Use strongly-typed ACIs and PNIs everywhere.
This commit is contained in:
@@ -93,7 +93,7 @@ sealed class CallLogRow {
|
||||
return FULL
|
||||
}
|
||||
|
||||
if (groupCallUpdateDetails.inCallUuidsList.contains(Recipient.self().requireServiceId().uuid().toString())) {
|
||||
if (groupCallUpdateDetails.inCallUuidsList.contains(Recipient.self().requireAci().rawUuid.toString())) {
|
||||
return LOCAL_USER_JOINED
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.logsubmit.SubmitDebugLogActivity
|
||||
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter
|
||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme
|
||||
import org.whispersystems.signalservice.api.push.PNI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI
|
||||
import java.util.Objects
|
||||
|
||||
private val TAG: String = Log.tag(ChangeNumberLockActivity::class.java)
|
||||
|
||||
@@ -34,8 +34,7 @@ import org.whispersystems.signalservice.api.SvrNoDataException
|
||||
import org.whispersystems.signalservice.api.account.ChangePhoneNumberRequest
|
||||
import org.whispersystems.signalservice.api.account.PreKeyUpload
|
||||
import org.whispersystems.signalservice.api.kbs.MasterKey
|
||||
import org.whispersystems.signalservice.api.push.PNI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI
|
||||
import org.whispersystems.signalservice.api.push.ServiceIdType
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.api.push.SignedPreKeyEntity
|
||||
@@ -243,7 +242,7 @@ class ChangeNumberRepository(
|
||||
throw AssertionError("No change number metadata")
|
||||
}
|
||||
|
||||
val originalPni = ServiceId.fromByteString(metadata.previousPni)
|
||||
val originalPni = PNI.parseOrThrow(metadata.previousPni)
|
||||
|
||||
if (originalPni == pni) {
|
||||
Log.i(TAG, "No change has occurred, PNI is unchanged: $pni")
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.thoughtcrime.securesms.registration.viewmodel.BaseRegistrationViewMod
|
||||
import org.thoughtcrime.securesms.registration.viewmodel.NumberViewState
|
||||
import org.thoughtcrime.securesms.registration.viewmodel.SvrAuthCredentialSet
|
||||
import org.thoughtcrime.securesms.util.DefaultValueLiveData
|
||||
import org.whispersystems.signalservice.api.push.PNI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI
|
||||
import org.whispersystems.signalservice.api.push.exceptions.IncorrectCodeException
|
||||
import org.whispersystems.signalservice.internal.ServiceResponse
|
||||
import java.util.Objects
|
||||
|
||||
@@ -8,7 +8,6 @@ package org.thoughtcrime.securesms.components.settings.app.internal.search
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
@@ -46,7 +45,7 @@ class InternalSearchViewModel : ViewModel() {
|
||||
InternalSearchResult(
|
||||
id = record.id,
|
||||
name = record.displayName(),
|
||||
aci = record.serviceId?.toString(),
|
||||
aci = record.aci?.toString(),
|
||||
pni = record.pni.toString(),
|
||||
groupId = record.groupId
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.UsernameUtil
|
||||
import org.whispersystems.signalservice.api.push.ACI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException
|
||||
import java.io.IOException
|
||||
|
||||
|
||||
@@ -165,8 +165,11 @@ class InternalConversationSettingsFragment : DSLSettingsFragment(
|
||||
.setTitle("Are you sure?")
|
||||
.setNegativeButton(android.R.string.cancel) { d, _ -> d.dismiss() }
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
if (recipient.hasServiceId()) {
|
||||
SignalDatabase.sessions.deleteAllFor(serviceId = SignalStore.account().requireAci(), addressName = recipient.requireServiceId().toString())
|
||||
if (recipient.hasAci()) {
|
||||
SignalDatabase.sessions.deleteAllFor(serviceId = SignalStore.account().requireAci(), addressName = recipient.requireAci().toString())
|
||||
}
|
||||
if (recipient.hasPni()) {
|
||||
SignalDatabase.sessions.deleteAllFor(serviceId = SignalStore.account().requireAci(), addressName = recipient.requirePni().toString())
|
||||
}
|
||||
}
|
||||
.show()
|
||||
@@ -182,14 +185,25 @@ class InternalConversationSettingsFragment : DSLSettingsFragment(
|
||||
.setTitle("Are you sure?")
|
||||
.setNegativeButton(android.R.string.cancel) { d, _ -> d.dismiss() }
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
SignalDatabase.threads.deleteConversation(SignalDatabase.threads.getThreadIdIfExistsFor(recipient.id))
|
||||
|
||||
if (recipient.hasServiceId()) {
|
||||
SignalDatabase.recipients.debugClearServiceIds(recipient.id)
|
||||
SignalDatabase.recipients.debugClearProfileData(recipient.id)
|
||||
SignalDatabase.sessions.deleteAllFor(serviceId = SignalStore.account().requireAci(), addressName = recipient.requireServiceId().toString())
|
||||
ApplicationDependencies.getProtocolStore().aci().identities().delete(recipient.requireServiceId().toString())
|
||||
ApplicationDependencies.getProtocolStore().pni().identities().delete(recipient.requireServiceId().toString())
|
||||
SignalDatabase.threads.deleteConversation(SignalDatabase.threads.getThreadIdIfExistsFor(recipient.id))
|
||||
}
|
||||
|
||||
if (recipient.hasAci()) {
|
||||
SignalDatabase.sessions.deleteAllFor(serviceId = SignalStore.account().requireAci(), addressName = recipient.requireAci().toString())
|
||||
SignalDatabase.sessions.deleteAllFor(serviceId = SignalStore.account().requirePni(), addressName = recipient.requireAci().toString())
|
||||
ApplicationDependencies.getProtocolStore().aci().identities().delete(recipient.requireAci().toString())
|
||||
}
|
||||
|
||||
if (recipient.hasPni()) {
|
||||
SignalDatabase.sessions.deleteAllFor(serviceId = SignalStore.account().requireAci(), addressName = recipient.requirePni().toString())
|
||||
SignalDatabase.sessions.deleteAllFor(serviceId = SignalStore.account().requirePni(), addressName = recipient.requirePni().toString())
|
||||
ApplicationDependencies.getProtocolStore().aci().identities().delete(recipient.requirePni().toString())
|
||||
}
|
||||
|
||||
startActivity(MainActivity.clearTop(requireContext()))
|
||||
}
|
||||
.show()
|
||||
@@ -237,7 +251,7 @@ class InternalConversationSettingsFragment : DSLSettingsFragment(
|
||||
SignalDatabase.recipients.debugClearE164AndPni(recipient.id)
|
||||
|
||||
val splitRecipientId: RecipientId = if (FeatureFlags.phoneNumberPrivacy()) {
|
||||
SignalDatabase.recipients.getAndPossiblyMergePnpVerified(recipient.pni.orElse(null), recipient.pni.orElse(null), recipient.requireE164())
|
||||
SignalDatabase.recipients.getAndPossiblyMergePnpVerified(null, recipient.pni.orElse(null), recipient.requireE164())
|
||||
} else {
|
||||
SignalDatabase.recipients.getAndPossiblyMerge(recipient.pni.orElse(null), recipient.requireE164())
|
||||
}
|
||||
@@ -281,7 +295,7 @@ class InternalConversationSettingsFragment : DSLSettingsFragment(
|
||||
|
||||
SignalDatabase.recipients.debugRemoveAci(recipient.id)
|
||||
|
||||
val aciRecipientId: RecipientId = SignalDatabase.recipients.getAndPossiblyMergePnpVerified(recipient.requireServiceId(), null, null)
|
||||
val aciRecipientId: RecipientId = SignalDatabase.recipients.getAndPossiblyMergePnpVerified(recipient.requireAci(), null, null)
|
||||
|
||||
recipient.profileKey?.let { profileKey ->
|
||||
SignalDatabase.recipients.setProfileKey(aciRecipientId, ProfileKey(profileKey))
|
||||
|
||||
@@ -16,7 +16,7 @@ import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
import org.whispersystems.signalservice.api.push.ACI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.api.push.exceptions.CdsiInvalidTokenException
|
||||
import org.whispersystems.signalservice.api.push.exceptions.CdsiResourceExhaustedException
|
||||
import org.whispersystems.signalservice.api.services.CdsiV2Service
|
||||
|
||||
@@ -4,7 +4,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -50,7 +50,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
|
||||
import org.thoughtcrime.securesms.verify.VerifyIdentityActivity;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
@@ -315,7 +315,7 @@ public final class ConversationUpdateItem extends FrameLayout
|
||||
liveBannedMembers = liveGroup.getBannedMembers();
|
||||
liveFullMembers = Transformations.map(liveGroup.getFullMembers(),
|
||||
members -> members.stream()
|
||||
.map(m -> m.getMember().requireServiceId().uuid())
|
||||
.map(m -> m.getMember().requireAci().getRawUuid())
|
||||
.collect(Collectors.toSet()));
|
||||
|
||||
liveIsSelfAdmin.observe(lifecycleOwner, updater);
|
||||
@@ -343,7 +343,7 @@ public final class ConversationUpdateItem extends FrameLayout
|
||||
|
||||
Set<UUID> bannedMembers = liveBannedMembers.getValue();
|
||||
if (bannedMembers != null) {
|
||||
return recipient.getServiceId().isPresent() && bannedMembers.contains(recipient.requireServiceId().uuid());
|
||||
return recipient.getServiceId().isPresent() && bannedMembers.contains(recipient.requireServiceId().getRawUuid());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -355,7 +355,7 @@ public final class ConversationUpdateItem extends FrameLayout
|
||||
|
||||
Set<UUID> members = liveFullMembers.getValue();
|
||||
if (members != null) {
|
||||
return recipient.getServiceId().isPresent() && members.contains(recipient.requireServiceId().uuid());
|
||||
return recipient.hasAci() && members.contains(recipient.requireAci().getRawUuid());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -446,12 +446,12 @@ public final class ConversationUpdateItem extends FrameLayout
|
||||
}
|
||||
});
|
||||
} else if (conversationMessage.getMessageRecord().isGroupCall()) {
|
||||
UpdateDescription updateDescription = MessageRecord.getGroupCallUpdateDescription(getContext(), conversationMessage.getMessageRecord().getBody(), true);
|
||||
Collection<ServiceId> sids = updateDescription.getMentioned();
|
||||
UpdateDescription updateDescription = MessageRecord.getGroupCallUpdateDescription(getContext(), conversationMessage.getMessageRecord().getBody(), true);
|
||||
Collection<ACI> acis = updateDescription.getMentioned();
|
||||
|
||||
int text = 0;
|
||||
if (Util.hasItems(sids)) {
|
||||
if (sids.contains(SignalStore.account().requireAci())) {
|
||||
if (Util.hasItems(acis)) {
|
||||
if (acis.contains(SignalStore.account().requireAci())) {
|
||||
text = R.string.ConversationUpdateItem_return_to_call;
|
||||
} else if (GroupCallUpdateDetailsUtil.parse(conversationMessage.getMessageRecord().getBody()).getIsCallFull()) {
|
||||
text = R.string.ConversationUpdateItem_call_is_full;
|
||||
|
||||
@@ -176,7 +176,7 @@ public final class SafetyNumberChangeRepository {
|
||||
Log.d(TAG, "Saving identity result: " + result);
|
||||
if (result == SignalIdentityKeyStore.SaveResult.NO_CHANGE) {
|
||||
Log.i(TAG, "Archiving sessions explicitly as they appear to be out of sync.");
|
||||
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSession(changedRecipient.getRecipient().getId(), SignalServiceAddress.DEFAULT_DEVICE_ID);
|
||||
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSessions(changedRecipient.getRecipient().getId(), SignalServiceAddress.DEFAULT_DEVICE_ID);
|
||||
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSiblingSessions(mismatchAddress);
|
||||
SignalDatabase.senderKeyShared().deleteAllFor(changedRecipient.getRecipient().getId());
|
||||
}
|
||||
|
||||
@@ -69,8 +69,8 @@ public class SignalBaseIdentityKeyStore {
|
||||
|
||||
public @NonNull SaveResult saveIdentity(SignalProtocolAddress address, IdentityKey identityKey, boolean nonBlockingApproval) {
|
||||
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
IdentityStoreRecord identityRecord = cache.get(address.getName());
|
||||
RecipientId recipientId = RecipientId.fromSidOrE164(address.getName());
|
||||
IdentityStoreRecord identityRecord = cache.get(address.getName());
|
||||
RecipientId recipientId = RecipientId.fromSidOrE164(address.getName());
|
||||
|
||||
if (identityRecord == null) {
|
||||
Log.i(TAG, "Saving new identity for " + address);
|
||||
|
||||
@@ -6,7 +6,6 @@ import androidx.annotation.Nullable;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.libsignal.protocol.NoSessionException;
|
||||
import org.signal.libsignal.protocol.SignalProtocolAddress;
|
||||
import org.signal.libsignal.protocol.message.CiphertextMessage;
|
||||
import org.signal.libsignal.protocol.state.SessionRecord;
|
||||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
|
||||
import org.thoughtcrime.securesms.database.SessionTable;
|
||||
@@ -126,13 +125,23 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void archiveSession(@NonNull ServiceId serviceId, int deviceId) {
|
||||
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
archiveSession(new SignalProtocolAddress(serviceId.toString(), deviceId));
|
||||
}
|
||||
}
|
||||
|
||||
public void archiveSession(@NonNull RecipientId recipientId, int deviceId) {
|
||||
public void archiveSessions(@NonNull RecipientId recipientId, int deviceId) {
|
||||
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
Recipient recipient = Recipient.resolved(recipientId);
|
||||
|
||||
if (recipient.hasServiceId()) {
|
||||
archiveSession(new SignalProtocolAddress(recipient.requireServiceId().toString(), deviceId));
|
||||
if (recipient.hasAci()) {
|
||||
archiveSession(new SignalProtocolAddress(recipient.requireAci().toString(), deviceId));
|
||||
}
|
||||
|
||||
if (recipient.hasPni()) {
|
||||
archiveSession(new SignalProtocolAddress(recipient.requirePni().toString(), deviceId));
|
||||
}
|
||||
|
||||
if (recipient.hasE164()) {
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.thoughtcrime.securesms.jobs.CallSyncEventJob
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.CallEvent
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.TimeUnit
|
||||
@@ -605,11 +605,11 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
||||
fun insertOrUpdateGroupCallFromRingState(
|
||||
ringId: Long,
|
||||
groupRecipientId: RecipientId,
|
||||
ringerUUID: UUID,
|
||||
ringerAci: ACI,
|
||||
dateReceived: Long,
|
||||
ringState: RingUpdate
|
||||
) {
|
||||
val ringerRecipient = Recipient.externalPush(ServiceId.from(ringerUUID))
|
||||
val ringerRecipient = Recipient.externalPush(ringerAci)
|
||||
handleGroupRingState(ringId, groupRecipientId, ringerRecipient.id, dateReceived, ringState)
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ import org.whispersystems.signalservice.api.groupsv2.GroupChangeReconstruct
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer
|
||||
import org.whispersystems.signalservice.api.push.DistributionId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil
|
||||
import java.io.Closeable
|
||||
import java.security.SecureRandom
|
||||
@@ -1215,7 +1216,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
|
||||
val serviceId = recipient.serviceId
|
||||
|
||||
return if (serviceId.isPresent) {
|
||||
DecryptedGroupUtil.findMemberByUuid(decryptedGroup.membersList, serviceId.get().uuid())
|
||||
DecryptedGroupUtil.findMemberByUuid(decryptedGroup.membersList, serviceId.get().rawUuid)
|
||||
.map { it.role == Member.Role.ADMINISTRATOR }
|
||||
.orElse(false)
|
||||
} else {
|
||||
@@ -1232,7 +1233,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
|
||||
return MemberLevel.NOT_A_MEMBER
|
||||
}
|
||||
|
||||
var memberLevel: Optional<MemberLevel> = DecryptedGroupUtil.findMemberByUuid(decryptedGroup.membersList, serviceId.get().uuid())
|
||||
var memberLevel: Optional<MemberLevel> = DecryptedGroupUtil.findMemberByUuid(decryptedGroup.membersList, serviceId.get().rawUuid)
|
||||
.map { member ->
|
||||
if (member.role == Member.Role.ADMINISTRATOR) {
|
||||
MemberLevel.ADMINISTRATOR
|
||||
@@ -1242,12 +1243,12 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
|
||||
}
|
||||
|
||||
if (memberLevel.isAbsent()) {
|
||||
memberLevel = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.pendingMembersList, serviceId.get().uuid())
|
||||
memberLevel = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.pendingMembersList, serviceId.get().rawUuid)
|
||||
.map { MemberLevel.PENDING_MEMBER }
|
||||
}
|
||||
|
||||
if (memberLevel.isAbsent()) {
|
||||
memberLevel = DecryptedGroupUtil.findRequestingByUuid(decryptedGroup.requestingMembersList, serviceId.get().uuid())
|
||||
memberLevel = DecryptedGroupUtil.findRequestingByUuid(decryptedGroup.requestingMembersList, serviceId.get().rawUuid)
|
||||
.map { _ -> MemberLevel.REQUESTING_MEMBER }
|
||||
}
|
||||
|
||||
@@ -1264,7 +1265,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
|
||||
|
||||
fun getMemberRecipientIds(memberSet: MemberSet): List<RecipientId> {
|
||||
val includeSelf = memberSet.includeSelf
|
||||
val selfUuid = SignalStore.account().requireAci().uuid()
|
||||
val selfAciUuid = SignalStore.account().requireAci().rawUuid
|
||||
val recipients: MutableList<RecipientId> = ArrayList(decryptedGroup.membersCount + decryptedGroup.pendingMembersCount)
|
||||
|
||||
var unknownMembers = 0
|
||||
@@ -1273,8 +1274,8 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
|
||||
for (uuid in DecryptedGroupUtil.toUuidList(decryptedGroup.membersList)) {
|
||||
if (UuidUtil.UNKNOWN_UUID == uuid) {
|
||||
unknownMembers++
|
||||
} else if (includeSelf || selfUuid != uuid) {
|
||||
recipients += RecipientId.from(ServiceId.from(uuid))
|
||||
} else if (includeSelf || selfAciUuid != uuid) {
|
||||
recipients += RecipientId.from(ACI.from(uuid))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1282,8 +1283,8 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
|
||||
for (uuid in DecryptedGroupUtil.pendingToUuidList(decryptedGroup.pendingMembersList)) {
|
||||
if (UuidUtil.UNKNOWN_UUID == uuid) {
|
||||
unknownPending++
|
||||
} else if (includeSelf || selfUuid != uuid) {
|
||||
recipients += RecipientId.from(ServiceId.from(uuid))
|
||||
} else if (includeSelf || selfAciUuid != uuid) {
|
||||
recipients += RecipientId.from(ACI.from(uuid))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1301,7 +1302,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
|
||||
.asSequence()
|
||||
.map { UuidUtil.fromByteStringOrNull(it.uuid) }
|
||||
.filterNotNull()
|
||||
.map { ServiceId.from(it) }
|
||||
.map { ACI.from(it) }
|
||||
.sortedBy { it.toString() }
|
||||
.toList()
|
||||
}
|
||||
@@ -1376,8 +1377,8 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
|
||||
private fun gv2GroupActive(decryptedGroup: DecryptedGroup): Boolean {
|
||||
val aci = SignalStore.account().requireAci()
|
||||
|
||||
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.membersList, aci.uuid()).isPresent ||
|
||||
DecryptedGroupUtil.findPendingByUuid(decryptedGroup.pendingMembersList, aci.uuid()).isPresent
|
||||
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.membersList, aci.rawUuid).isPresent ||
|
||||
DecryptedGroupUtil.findPendingByUuid(decryptedGroup.pendingMembersList, aci.rawUuid).isPresent
|
||||
}
|
||||
|
||||
private fun List<UUID>.toRecipientIds(): MutableList<RecipientId> {
|
||||
@@ -1405,7 +1406,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
|
||||
Log.w(TAG, "Saw an unknown UUID when mapping to RecipientIds!")
|
||||
null
|
||||
} else {
|
||||
val id = RecipientId.from(ServiceId.from(uuid))
|
||||
val id = RecipientId.from(ACI.from(uuid))
|
||||
val remapped = RemappedRecords.getInstance().getRecipient(id)
|
||||
if (remapped.isPresent) {
|
||||
Log.w(TAG, "Saw that $id remapped to $remapped. Using the mapping.")
|
||||
|
||||
@@ -70,6 +70,14 @@ class IdentityTable internal constructor(context: Context?, databaseHelper: Sign
|
||||
"""
|
||||
}
|
||||
|
||||
fun getIdentityStoreRecord(serviceId: ServiceId?): IdentityStoreRecord? {
|
||||
return if (serviceId != null) {
|
||||
getIdentityStoreRecord(serviceId.toString())
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun getIdentityStoreRecord(addressName: String): IdentityStoreRecord? {
|
||||
readableDatabase
|
||||
.select()
|
||||
|
||||
@@ -96,7 +96,7 @@ public final class MentionUtil {
|
||||
BodyRangeList.Builder builder = BodyRangeList.newBuilder();
|
||||
|
||||
for (Mention mention : mentions) {
|
||||
String uuid = Recipient.resolved(mention.getRecipientId()).requireServiceId().toString();
|
||||
String uuid = Recipient.resolved(mention.getRecipientId()).requireAci().toString();
|
||||
builder.addRanges(BodyRangeList.BodyRange.newBuilder()
|
||||
.setMentionUuid(uuid)
|
||||
.setStart(mention.getStart())
|
||||
|
||||
@@ -142,6 +142,7 @@ import org.thoughtcrime.securesms.util.Util
|
||||
import org.thoughtcrime.securesms.util.isStory
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.ReadMessage
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage
|
||||
import java.io.Closeable
|
||||
import java.io.IOException
|
||||
@@ -845,7 +846,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
val threadId = threads.getOrCreateThreadIdFor(recipient)
|
||||
val messageId: MessageId = writableDatabase.withinTransaction { db ->
|
||||
val self = Recipient.self()
|
||||
val markRead = joinedUuids.contains(self.requireServiceId().uuid()) || self.id == sender
|
||||
val markRead = joinedUuids.contains(self.requireServiceId().rawUuid) || self.id == sender
|
||||
val updateDetails: ByteArray = GroupCallUpdateDetails.newBuilder()
|
||||
.setEraId(eraId)
|
||||
.setStartedCallUuid(Recipient.resolved(sender).requireServiceId().toString())
|
||||
@@ -919,7 +920,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
}
|
||||
|
||||
val updateDetail = GroupCallUpdateDetailsUtil.parse(message.body)
|
||||
val containsSelf = joinedUuids.contains(SignalStore.account().requireAci().uuid())
|
||||
val containsSelf = joinedUuids.contains(SignalStore.account().requireAci().rawUuid)
|
||||
val sameEraId = updateDetail.eraId == eraId && !Util.isEmpty(eraId)
|
||||
val inCallUuids = if (sameEraId) joinedUuids.map { it.toString() } else emptyList()
|
||||
val contentValues = contentValuesOf(
|
||||
@@ -954,7 +955,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
MmsReader(cursor).use { reader ->
|
||||
val record = reader.getNext() ?: return@withinTransaction false
|
||||
val groupCallUpdateDetails = GroupCallUpdateDetailsUtil.parse(record.body)
|
||||
val containsSelf = peekJoinedUuids.contains(SignalStore.account().requireAci().uuid())
|
||||
val containsSelf = peekJoinedUuids.contains(SignalStore.account().requireAci().rawUuid)
|
||||
val sameEraId = groupCallUpdateDetails.eraId == peekGroupCallEraId && !Util.isEmpty(peekGroupCallEraId)
|
||||
|
||||
val inCallUuids = if (sameEraId) {
|
||||
@@ -3088,9 +3089,10 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
val members: MutableSet<RecipientId> = mutableSetOf()
|
||||
|
||||
if (message.isGroupUpdate && message.isV2Group) {
|
||||
// TODO [greyson][ServiceId] pending members could be ACI's or PNI's
|
||||
members += message.requireGroupV2Properties().allActivePendingAndRemovedMembers
|
||||
.distinct()
|
||||
.map { uuid -> RecipientId.from(ServiceId.from(uuid)) }
|
||||
.map { uuid -> RecipientId.from(ACI.from(uuid)) }
|
||||
.toList()
|
||||
|
||||
members -= Recipient.self().id
|
||||
|
||||
@@ -3,8 +3,9 @@ package org.thoughtcrime.securesms.database
|
||||
import app.cash.exhaustive.Exhaustive
|
||||
import org.thoughtcrime.securesms.database.model.RecipientRecord
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.whispersystems.signalservice.api.push.ACI
|
||||
import org.whispersystems.signalservice.api.push.PNI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI
|
||||
|
||||
/**
|
||||
* Encapsulates data around processing a tuple of user data into a user entry in [RecipientTable].
|
||||
@@ -15,18 +16,20 @@ data class PnpDataSet(
|
||||
val pni: PNI?,
|
||||
val aci: ACI?,
|
||||
val byE164: RecipientId?,
|
||||
val byPniSid: RecipientId?,
|
||||
val byPniOnly: RecipientId?,
|
||||
val byAciSid: RecipientId?,
|
||||
val byPni: RecipientId?,
|
||||
val byAci: RecipientId?,
|
||||
val e164Record: RecipientRecord? = null,
|
||||
val pniSidRecord: RecipientRecord? = null,
|
||||
val aciSidRecord: RecipientRecord? = null
|
||||
val pniRecord: RecipientRecord? = null,
|
||||
val aciRecord: RecipientRecord? = null
|
||||
) {
|
||||
|
||||
/**
|
||||
* @return The common id if all non-null ids are equal, or null if all are null or at least one non-null pair doesn't match.
|
||||
*/
|
||||
val commonId: RecipientId? = findCommonId(listOf(byE164, byPniSid, byPniOnly, byAciSid))
|
||||
val commonId: RecipientId? = findCommonId(listOf(byE164, byPni, byAci))
|
||||
|
||||
/** The ID that would be used to contact this user. */
|
||||
val serviceId: ServiceId? = aci ?: pni
|
||||
|
||||
fun MutableSet<RecipientRecord>.replace(recipientId: RecipientId, update: (RecipientRecord) -> RecipientRecord) {
|
||||
val toUpdate = this.first { it.id == recipientId }
|
||||
@@ -43,7 +46,7 @@ data class PnpDataSet(
|
||||
return this
|
||||
}
|
||||
|
||||
val records: MutableSet<RecipientRecord> = listOfNotNull(e164Record, pniSidRecord, aciSidRecord).toMutableSet()
|
||||
val records: MutableSet<RecipientRecord> = listOfNotNull(e164Record, pniRecord, aciRecord).toMutableSet()
|
||||
|
||||
for (operation in operations) {
|
||||
@Exhaustive
|
||||
@@ -55,16 +58,12 @@ data class PnpDataSet(
|
||||
records.replace(operation.recipientId) { record ->
|
||||
record.copy(
|
||||
pni = null,
|
||||
serviceId = if (record.sidIsPni()) {
|
||||
null
|
||||
} else {
|
||||
record.serviceId
|
||||
}
|
||||
aci = record.aci
|
||||
)
|
||||
}
|
||||
}
|
||||
is PnpOperation.SetAci -> {
|
||||
records.replace(operation.recipientId) { it.copy(serviceId = operation.aci) }
|
||||
records.replace(operation.recipientId) { it.copy(aci = operation.aci) }
|
||||
}
|
||||
is PnpOperation.SetE164 -> {
|
||||
records.replace(operation.recipientId) { it.copy(e164 = operation.e164) }
|
||||
@@ -72,12 +71,7 @@ data class PnpDataSet(
|
||||
is PnpOperation.SetPni -> {
|
||||
records.replace(operation.recipientId) { record ->
|
||||
record.copy(
|
||||
pni = operation.pni,
|
||||
serviceId = if (record.sidIsPni()) {
|
||||
operation.pni
|
||||
} else {
|
||||
record.serviceId ?: operation.pni
|
||||
}
|
||||
pni = operation.pni
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -89,7 +83,7 @@ data class PnpDataSet(
|
||||
primary.copy(
|
||||
e164 = primary.e164 ?: secondary.e164,
|
||||
pni = primary.pni ?: secondary.pni,
|
||||
serviceId = primary.serviceId ?: secondary.serviceId
|
||||
aci = primary.aci ?: secondary.aci
|
||||
)
|
||||
}
|
||||
|
||||
@@ -101,20 +95,16 @@ data class PnpDataSet(
|
||||
}
|
||||
|
||||
val newE164Record = if (e164 != null) records.firstOrNull { it.e164 == e164 } else null
|
||||
val newPniSidRecord = if (pni != null) records.firstOrNull { it.serviceId == pni } else null
|
||||
val newAciSidRecord = if (aci != null) records.firstOrNull { it.serviceId == aci } else null
|
||||
val newPniRecord = if (pni != null) records.firstOrNull { it.pni == pni } else null
|
||||
val newAciRecord = if (aci != null) records.firstOrNull { it.aci == aci } else null
|
||||
|
||||
return PnpDataSet(
|
||||
e164 = e164,
|
||||
pni = pni,
|
||||
aci = aci,
|
||||
return this.copy(
|
||||
byE164 = newE164Record?.id,
|
||||
byPniSid = newPniSidRecord?.id,
|
||||
byPniOnly = byPniOnly,
|
||||
byAciSid = newAciSidRecord?.id,
|
||||
byPni = newPniRecord?.id,
|
||||
byAci = newAciRecord?.id,
|
||||
e164Record = newE164Record,
|
||||
pniSidRecord = newPniSidRecord,
|
||||
aciSidRecord = newAciSidRecord
|
||||
pniRecord = newPniRecord,
|
||||
aciRecord = newAciRecord
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -116,12 +116,20 @@ class SenderKeySharedTable internal constructor(context: Context?, databaseHelpe
|
||||
fun deleteAllFor(recipientId: RecipientId) {
|
||||
val recipient = Recipient.resolved(recipientId)
|
||||
if (recipient.hasServiceId()) {
|
||||
writableDatabase
|
||||
.delete(TABLE_NAME)
|
||||
.where("$ADDRESS = ?", recipient.requireServiceId().toString())
|
||||
.run()
|
||||
if (recipient.hasAci()) {
|
||||
writableDatabase
|
||||
.delete(TABLE_NAME)
|
||||
.where("$ADDRESS = ?", recipient.requireAci().toString())
|
||||
.run()
|
||||
}
|
||||
if (recipient.hasPni()) {
|
||||
writableDatabase
|
||||
.delete(TABLE_NAME)
|
||||
.where("$ADDRESS = ?", recipient.requirePni().toString())
|
||||
.run()
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "Recipient doesn't have a UUID! $recipientId")
|
||||
Log.w(TAG, "Recipient doesn't have a ServiceId! $recipientId")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,6 @@ import org.thoughtcrime.securesms.util.JsonUtils.SaneJSONObject
|
||||
import org.thoughtcrime.securesms.util.LRUCache
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.isScheduled
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.api.storage.SignalAccountRecord
|
||||
import org.whispersystems.signalservice.api.storage.SignalAccountRecord.PinnedConversation
|
||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord
|
||||
@@ -1700,7 +1699,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
if (threadRecipient.isPushV2Group) {
|
||||
val inviteAddState = record.gv2AddInviteState
|
||||
if (inviteAddState != null) {
|
||||
val from = RecipientId.from(ServiceId.from(inviteAddState.addedOrInvitedBy))
|
||||
val from = RecipientId.from(inviteAddState.addedOrInvitedBy)
|
||||
return if (inviteAddState.isInvited) {
|
||||
Log.i(TAG, "GV2 invite message request from $from")
|
||||
Extra.forGroupV2invite(from, authorId)
|
||||
|
||||
@@ -55,6 +55,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V196_BackCallLinksW
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V197_DropAvatarColorFromCallLinks
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V198_AddMacDigestColumn
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V199_AddThreadActiveColumn
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V200_ResetPniColumn
|
||||
|
||||
/**
|
||||
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
|
||||
@@ -63,7 +64,7 @@ object SignalDatabaseMigrations {
|
||||
|
||||
val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass)
|
||||
|
||||
const val DATABASE_VERSION = 199
|
||||
const val DATABASE_VERSION = 200
|
||||
|
||||
@JvmStatic
|
||||
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
@@ -270,6 +271,10 @@ object SignalDatabaseMigrations {
|
||||
if (oldVersion < 199) {
|
||||
V199_AddThreadActiveColumn.migrate(context, db, oldVersion, newVersion)
|
||||
}
|
||||
|
||||
if (oldVersion < 200) {
|
||||
V200_ResetPniColumn.migrate(context, db, oldVersion, newVersion)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@@ -47,8 +47,8 @@ import org.thoughtcrime.securesms.util.FileUtils
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil
|
||||
import org.thoughtcrime.securesms.util.Triple
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.whispersystems.signalservice.api.push.ACI
|
||||
import org.whispersystems.signalservice.api.push.DistributionId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import java.io.File
|
||||
import java.util.LinkedList
|
||||
import java.util.Locale
|
||||
|
||||
@@ -16,7 +16,7 @@ import org.signal.core.util.requireString
|
||||
import org.thoughtcrime.securesms.database.KeyValueDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.whispersystems.signalservice.api.push.ACI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
|
||||
/**
|
||||
* This is a combination of the edit message and message recipient migrations (would have been V185 and v186), but as they
|
||||
|
||||
@@ -16,7 +16,7 @@ import org.signal.core.util.requireString
|
||||
import org.thoughtcrime.securesms.database.KeyValueDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.whispersystems.signalservice.api.push.ACI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
|
||||
/**
|
||||
* This is a fix for a bad situation that could happen during [V185_MessageRecipientsAndEditMessageMigration].
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.database.helpers.migration
|
||||
|
||||
import android.app.Application
|
||||
import net.zetetic.database.sqlcipher.SQLiteDatabase
|
||||
|
||||
/**
|
||||
* This updates the PNI column to have the proper serialized format.
|
||||
*/
|
||||
@Suppress("ClassName")
|
||||
object V200_ResetPniColumn : SignalDatabaseMigration {
|
||||
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
db.execSQL("UPDATE recipient SET pni = 'PNI:' || pni WHERE pni NOT NULL")
|
||||
db.execSQL("ALTER TABLE recipient RENAME COLUMN uuid to aci")
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -31,7 +31,7 @@ public class GroupCallUpdateMessageFactory implements UpdateDescription.Spannabl
|
||||
private final ACI selfAci;
|
||||
|
||||
public GroupCallUpdateMessageFactory(@NonNull Context context,
|
||||
@NonNull List<ServiceId> joinedMembers,
|
||||
@NonNull List<ACI> joinedMembers,
|
||||
boolean withTime,
|
||||
@NonNull GroupCallUpdateDetails groupCallUpdateDetails)
|
||||
{
|
||||
|
||||
@@ -176,7 +176,7 @@ class GroupRecord(
|
||||
if (isV2Group) {
|
||||
val serviceId = recipient.serviceId
|
||||
if (serviceId.isPresent) {
|
||||
return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().decryptedGroup.pendingMembersList, serviceId.get().uuid())
|
||||
return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().decryptedGroup.pendingMembersList, serviceId.get().rawUuid)
|
||||
.isPresent
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.ExpirationUtil;
|
||||
import org.thoughtcrime.securesms.util.SpanUtil;
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIds;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
@@ -72,9 +72,9 @@ final class GroupsV2UpdateMessageProducer {
|
||||
* When the revision of the group is 0, the change is very noisy and only the editor is useful.
|
||||
*/
|
||||
UpdateDescription describeNewGroup(@NonNull DecryptedGroup group, @NonNull DecryptedGroupChange decryptedGroupChange) {
|
||||
Optional<DecryptedPendingMember> selfPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfIds.getAci().uuid());
|
||||
Optional<DecryptedPendingMember> selfPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfIds.getAci().getRawUuid());
|
||||
if (!selfPending.isPresent() && selfIds.getPni() != null) {
|
||||
selfPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfIds.getPni().uuid());
|
||||
selfPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfIds.getPni().getRawUuid());
|
||||
}
|
||||
|
||||
if (selfPending.isPresent()) {
|
||||
@@ -90,8 +90,8 @@ final class GroupsV2UpdateMessageProducer {
|
||||
}
|
||||
}
|
||||
|
||||
if (DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfIds.getAci().uuid()).isPresent() ||
|
||||
(selfIds.getPni() != null && DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfIds.getPni().uuid()).isPresent()))
|
||||
if (DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfIds.getAci().getRawUuid()).isPresent() ||
|
||||
(selfIds.getPni() != null && DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfIds.getPni().getRawUuid()).isPresent()))
|
||||
{
|
||||
return updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16);
|
||||
} else {
|
||||
@@ -820,11 +820,11 @@ final class GroupsV2UpdateMessageProducer {
|
||||
@NonNull ByteString uuid1Bytes,
|
||||
@DrawableRes int iconResource)
|
||||
{
|
||||
ServiceId serviceId = ServiceId.fromByteStringOrUnknown(uuid1Bytes);
|
||||
RecipientId recipientId = RecipientId.from(serviceId);
|
||||
ACI aci = ACI.parseOrUnknown(uuid1Bytes);
|
||||
RecipientId recipientId = RecipientId.from(aci);
|
||||
|
||||
return UpdateDescription.mentioning(
|
||||
Collections.singletonList(serviceId),
|
||||
Collections.singletonList(aci),
|
||||
() -> {
|
||||
List<RecipientId> recipientIdList = Collections.singletonList(recipientId);
|
||||
String templateString = context.getString(stringRes, makePlaceholders(recipientIdList, null));
|
||||
@@ -839,14 +839,14 @@ final class GroupsV2UpdateMessageProducer {
|
||||
@NonNull ByteString uuid2Bytes,
|
||||
@DrawableRes int iconResource)
|
||||
{
|
||||
ServiceId sid1 = ServiceId.fromByteStringOrUnknown(uuid1Bytes);
|
||||
ServiceId sid2 = ServiceId.fromByteStringOrUnknown(uuid2Bytes);
|
||||
ACI aci1 = ACI.parseOrUnknown(uuid1Bytes);
|
||||
ACI aci2 = ACI.parseOrUnknown(uuid2Bytes);
|
||||
|
||||
RecipientId recipientId1 = RecipientId.from(sid1);
|
||||
RecipientId recipientId2 = RecipientId.from(sid2);
|
||||
RecipientId recipientId1 = RecipientId.from(aci1);
|
||||
RecipientId recipientId2 = RecipientId.from(aci2);
|
||||
|
||||
return UpdateDescription.mentioning(
|
||||
Arrays.asList(sid1, sid2),
|
||||
Arrays.asList(aci1, aci2),
|
||||
() -> {
|
||||
List<RecipientId> recipientIdList = Arrays.asList(recipientId1, recipientId2);
|
||||
String templateString = context.getString(stringRes, makePlaceholders(recipientIdList, null));
|
||||
@@ -862,11 +862,11 @@ final class GroupsV2UpdateMessageProducer {
|
||||
@NonNull Object formatArg,
|
||||
@DrawableRes int iconResource)
|
||||
{
|
||||
ServiceId serviceId = ServiceId.fromByteStringOrUnknown(uuid1Bytes);
|
||||
RecipientId recipientId = RecipientId.from(serviceId);
|
||||
ACI aci = ACI.parseOrUnknown(uuid1Bytes);
|
||||
RecipientId recipientId = RecipientId.from(aci);
|
||||
|
||||
return UpdateDescription.mentioning(
|
||||
Collections.singletonList(serviceId),
|
||||
Collections.singletonList(aci),
|
||||
() -> {
|
||||
List<RecipientId> recipientIdList = Collections.singletonList(recipientId);
|
||||
String templateString = context.getString(stringRes, makePlaceholders(recipientIdList, Collections.singletonList(formatArg)));
|
||||
@@ -883,11 +883,11 @@ final class GroupsV2UpdateMessageProducer {
|
||||
@NonNull Object formatArg,
|
||||
@DrawableRes int iconResource)
|
||||
{
|
||||
ServiceId serviceId = ServiceId.fromByteStringOrUnknown(uuid1Bytes);
|
||||
RecipientId recipientId = RecipientId.from(serviceId);
|
||||
ACI aci = ACI.parseOrUnknown(uuid1Bytes);
|
||||
RecipientId recipientId = RecipientId.from(aci);
|
||||
|
||||
return UpdateDescription.mentioning(
|
||||
Collections.singletonList(serviceId),
|
||||
Collections.singletonList(aci),
|
||||
() -> {
|
||||
List<RecipientId> recipientIdList = Collections.singletonList(recipientId);
|
||||
String templateString = context.getResources().getQuantityString(stringRes, quantity, makePlaceholders(recipientIdList, Collections.singletonList(formatArg)));
|
||||
|
||||
@@ -64,6 +64,7 @@ import org.thoughtcrime.securesms.util.ExpirationUtil;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
@@ -307,7 +308,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
|
||||
private static boolean selfCreatedGroup(@NonNull DecryptedGroupChange change) {
|
||||
return change.getRevision() == 0 &&
|
||||
change.getEditor().equals(UuidUtil.toByteString(SignalStore.account().requireAci().uuid()));
|
||||
change.getEditor().equals(UuidUtil.toByteString(SignalStore.account().requireAci().getRawUuid()));
|
||||
}
|
||||
|
||||
public static @NonNull UpdateDescription getGv2ChangeDescription(@NonNull Context context, @NonNull String body, @Nullable Consumer<RecipientId> recipientClickHandler) {
|
||||
@@ -345,13 +346,13 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
}
|
||||
|
||||
DecryptedGroup groupState = decryptedGroupV2Context.getGroupState();
|
||||
boolean invited = DecryptedGroupUtil.findPendingByUuid(groupState.getPendingMembersList(), SignalStore.account().requireAci().uuid()).isPresent();
|
||||
boolean invited = DecryptedGroupUtil.findPendingByUuid(groupState.getPendingMembersList(), SignalStore.account().requireAci().getRawUuid()).isPresent();
|
||||
|
||||
if (decryptedGroupV2Context.hasChange()) {
|
||||
UUID changeEditor = UuidUtil.fromByteStringOrNull(decryptedGroupV2Context.getChange().getEditor());
|
||||
|
||||
if (changeEditor != null) {
|
||||
return new InviteAddState(invited, changeEditor);
|
||||
return new InviteAddState(invited, ACI.from(changeEditor));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,7 +368,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
@NonNull Function<Recipient, String> stringGenerator,
|
||||
@DrawableRes int iconResource)
|
||||
{
|
||||
return UpdateDescription.mentioning(Collections.singletonList(recipient.getServiceId().orElse(ServiceId.UNKNOWN)),
|
||||
return UpdateDescription.mentioning(Collections.singletonList(recipient.getAci().orElse(ACI.UNKNOWN)),
|
||||
() -> new SpannableString(stringGenerator.apply(recipient.resolve())),
|
||||
iconResource);
|
||||
}
|
||||
@@ -435,10 +436,10 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
public static @NonNull UpdateDescription getGroupCallUpdateDescription(@NonNull Context context, @NonNull String body, boolean withTime) {
|
||||
GroupCallUpdateDetails groupCallUpdateDetails = GroupCallUpdateDetailsUtil.parse(body);
|
||||
|
||||
List<ServiceId> joinedMembers = Stream.of(groupCallUpdateDetails.getInCallUuidsList())
|
||||
List<ACI> joinedMembers = Stream.of(groupCallUpdateDetails.getInCallUuidsList())
|
||||
.map(UuidUtil::parseOrNull)
|
||||
.withoutNulls()
|
||||
.map(ServiceId::from)
|
||||
.map(ACI::from)
|
||||
.toList();
|
||||
|
||||
UpdateDescription.SpannableFactory stringFactory = new GroupCallUpdateMessageFactory(context, joinedMembers, withTime, groupCallUpdateDetails);
|
||||
@@ -467,7 +468,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isGroupV2JoinRequest(UuidUtil.toByteString(serviceId.uuid()));
|
||||
return isGroupV2JoinRequest(UuidUtil.toByteString(serviceId.getRawUuid()));
|
||||
}
|
||||
|
||||
public boolean isGroupV2JoinRequest(@NonNull ByteString uuid) {
|
||||
@@ -489,7 +490,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
DecryptedGroupChange change = decryptedGroupV2Context.getChange();
|
||||
return change.getNewRequestingMembersCount() > 0 &&
|
||||
change.getDeleteRequestingMembersCount() > 0 &&
|
||||
(serviceId == null || change.getEditor().equals(UuidUtil.toByteString(serviceId.uuid())));
|
||||
(serviceId == null || change.getEditor().equals(UuidUtil.toByteString(serviceId.getRawUuid())));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -748,14 +749,14 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
public static final class InviteAddState {
|
||||
|
||||
private final boolean invited;
|
||||
private final UUID addedOrInvitedBy;
|
||||
private final ACI addedOrInvitedBy;
|
||||
|
||||
public InviteAddState(boolean invited, @NonNull UUID addedOrInvitedBy) {
|
||||
public InviteAddState(boolean invited, @NonNull ACI addedOrInvitedBy) {
|
||||
this.invited = invited;
|
||||
this.addedOrInvitedBy = addedOrInvitedBy;
|
||||
}
|
||||
|
||||
public @NonNull UUID getAddedOrInvitedBy() {
|
||||
public @NonNull ACI getAddedOrInvitedBy() {
|
||||
return addedOrInvitedBy;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,9 @@ import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId
|
||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper
|
||||
import org.whispersystems.signalservice.api.push.PNI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI
|
||||
import java.util.Optional
|
||||
|
||||
/**
|
||||
@@ -28,7 +29,7 @@ import java.util.Optional
|
||||
*/
|
||||
data class RecipientRecord(
|
||||
val id: RecipientId,
|
||||
val serviceId: ServiceId?,
|
||||
val aci: ACI?,
|
||||
val pni: PNI?,
|
||||
val username: String?,
|
||||
val e164: String?,
|
||||
@@ -89,21 +90,23 @@ data class RecipientRecord(
|
||||
}
|
||||
|
||||
fun e164Only(): Boolean {
|
||||
return this.e164 != null && this.serviceId == null
|
||||
return this.e164 != null && this.aci == null
|
||||
}
|
||||
|
||||
fun sidOnly(sid: ServiceId): Boolean {
|
||||
return this.e164 == null && this.serviceId == sid && (this.pni == null || this.pni == sid)
|
||||
fun pniOnly(): Boolean {
|
||||
return this.e164 == null && this.aci == null && this.pni != null
|
||||
}
|
||||
|
||||
fun sidIsPni(): Boolean {
|
||||
return this.serviceId != null && this.pni != null && this.serviceId == this.pni
|
||||
fun aciOnly(): Boolean {
|
||||
return this.e164 == null && this.pni == null && this.aci != null
|
||||
}
|
||||
|
||||
fun pniAndAci(): Boolean {
|
||||
return this.serviceId != null && this.pni != null && this.serviceId != this.pni
|
||||
return this.aci != null && this.pni != null
|
||||
}
|
||||
|
||||
val serviceId: ServiceId? = this.aci ?: this.pni
|
||||
|
||||
/**
|
||||
* A bundle of data that's only necessary when syncing to storage service, not for a
|
||||
* [Recipient].
|
||||
|
||||
@@ -11,6 +11,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -18,6 +19,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Contains a list of people mentioned in an update message and a function to create the update message.
|
||||
@@ -28,14 +30,14 @@ public final class UpdateDescription {
|
||||
Spannable create();
|
||||
}
|
||||
|
||||
private final Collection<ServiceId> mentioned;
|
||||
private final SpannableFactory stringFactory;
|
||||
private final Spannable staticString;
|
||||
private final int lightIconResource;
|
||||
private final int lightTint;
|
||||
private final int darkTint;
|
||||
private final Collection<ACI> mentioned;
|
||||
private final SpannableFactory stringFactory;
|
||||
private final Spannable staticString;
|
||||
private final int lightIconResource;
|
||||
private final int lightTint;
|
||||
private final int darkTint;
|
||||
|
||||
private UpdateDescription(@NonNull Collection<ServiceId> mentioned,
|
||||
private UpdateDescription(@NonNull Collection<ACI> mentioned,
|
||||
@Nullable SpannableFactory stringFactory,
|
||||
@Nullable Spannable staticString,
|
||||
@DrawableRes int iconResource,
|
||||
@@ -60,11 +62,11 @@ public final class UpdateDescription {
|
||||
* @param mentioned UUIDs of recipients that are mentioned in the string.
|
||||
* @param stringFactory The background method for generating the string.
|
||||
*/
|
||||
public static UpdateDescription mentioning(@NonNull Collection<ServiceId> mentioned,
|
||||
public static UpdateDescription mentioning(@NonNull Collection<ACI> mentioned,
|
||||
@NonNull SpannableFactory stringFactory,
|
||||
@DrawableRes int iconResource)
|
||||
{
|
||||
return new UpdateDescription(ServiceId.filterKnown(mentioned),
|
||||
return new UpdateDescription(mentioned.stream().filter(ACI::isValid).collect(Collectors.toList()),
|
||||
stringFactory,
|
||||
null,
|
||||
iconResource,
|
||||
@@ -125,7 +127,7 @@ public final class UpdateDescription {
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
public @NonNull Collection<ServiceId> getMentioned() {
|
||||
public @NonNull Collection<ACI> getMentioned() {
|
||||
return mentioned;
|
||||
}
|
||||
|
||||
@@ -156,7 +158,7 @@ public final class UpdateDescription {
|
||||
);
|
||||
}
|
||||
|
||||
Set<ServiceId> allMentioned = new HashSet<>();
|
||||
Set<ACI> allMentioned = new HashSet<>();
|
||||
|
||||
for (UpdateDescription updateDescription : updateDescriptions) {
|
||||
allMentioned.addAll(updateDescription.getMentioned());
|
||||
|
||||
@@ -85,8 +85,8 @@ import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.SignalWebSocket;
|
||||
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.push.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.services.CallLinksService;
|
||||
import org.whispersystems.signalservice.api.services.DonationsService;
|
||||
import org.whispersystems.signalservice.api.services.ProfileService;
|
||||
|
||||
@@ -319,13 +319,13 @@ public final class GroupManager {
|
||||
GroupTable.V2GroupProperties groupProperties = SignalDatabase.groups().requireGroup(groupId).requireV2GroupProperties();
|
||||
Recipient recipient = Recipient.resolved(recipientId);
|
||||
|
||||
if (groupProperties.getBannedMembers().contains(recipient.requireServiceId().uuid())) {
|
||||
if (groupProperties.getBannedMembers().contains(recipient.requireServiceId().getRawUuid())) {
|
||||
Log.i(TAG, "Attempt to ban already banned recipient: " + recipientId);
|
||||
return;
|
||||
}
|
||||
|
||||
try (GroupManagerV2.GroupEditor editor = new GroupManagerV2(context).edit(groupId.requireV2())) {
|
||||
editor.ban(recipient.requireServiceId().uuid());
|
||||
editor.ban(recipient.requireServiceId().getRawUuid());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ public final class GroupManager {
|
||||
throws GroupChangeBusyException, IOException, GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException
|
||||
{
|
||||
try (GroupManagerV2.GroupEditor editor = new GroupManagerV2(context).edit(groupId.requireV2())) {
|
||||
editor.unban(Collections.singleton(Recipient.resolved(recipientId).requireServiceId().uuid()));
|
||||
editor.unban(Collections.singleton(Recipient.resolved(recipientId).requireServiceId().getRawUuid()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,8 +64,8 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||
import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException;
|
||||
import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.push.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIds;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
|
||||
@@ -176,7 +176,7 @@ final class GroupManagerV2 {
|
||||
|
||||
Map<UUID, UuidCiphertext> uuidCipherTexts = new HashMap<>();
|
||||
for (Recipient recipient : recipients) {
|
||||
uuidCipherTexts.put(recipient.requireServiceId().uuid(), clientZkGroupCipher.encryptUuid(recipient.requireServiceId().uuid()));
|
||||
uuidCipherTexts.put(recipient.requireServiceId().getRawUuid(), clientZkGroupCipher.encryptUuid(recipient.requireServiceId().getRawUuid()));
|
||||
}
|
||||
|
||||
return uuidCipherTexts;
|
||||
@@ -231,7 +231,7 @@ final class GroupManagerV2 {
|
||||
return latest;
|
||||
}
|
||||
|
||||
Optional<DecryptedMember> selfInFullMemberList = DecryptedGroupUtil.findMemberByUuid(latest.getMembersList(), selfAci.uuid());
|
||||
Optional<DecryptedMember> selfInFullMemberList = DecryptedGroupUtil.findMemberByUuid(latest.getMembersList(), selfAci.getRawUuid());
|
||||
|
||||
if (!selfInFullMemberList.isPresent()) {
|
||||
return latest;
|
||||
@@ -356,7 +356,7 @@ final class GroupManagerV2 {
|
||||
groupCandidates = GroupCandidate.withoutExpiringProfileKeyCredentials(groupCandidates);
|
||||
}
|
||||
|
||||
return commitChangeWithConflictResolution(selfAci, groupOperations.createModifyGroupMembershipChange(groupCandidates, bannedMembers, selfAci.uuid()));
|
||||
return commitChangeWithConflictResolution(selfAci, groupOperations.createModifyGroupMembershipChange(groupCandidates, bannedMembers, selfAci.getRawUuid()));
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
@@ -431,7 +431,7 @@ final class GroupManagerV2 {
|
||||
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
|
||||
{
|
||||
Set<UUID> uuids = Stream.of(recipientIds)
|
||||
.map(r -> Recipient.resolved(r).requireServiceId().uuid())
|
||||
.map(r -> Recipient.resolved(r).requireServiceId().getRawUuid())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
return commitChangeWithConflictResolution(selfAci, groupOperations.createApproveGroupJoinRequest(uuids));
|
||||
@@ -442,7 +442,7 @@ final class GroupManagerV2 {
|
||||
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
|
||||
{
|
||||
Set<UUID> uuids = Stream.of(recipientIds)
|
||||
.map(r -> Recipient.resolved(r).requireServiceId().uuid())
|
||||
.map(r -> Recipient.resolved(r).requireServiceId().getRawUuid())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
return commitChangeWithConflictResolution(selfAci, groupOperations.createRefuseGroupJoinRequest(uuids, true, v2GroupProperties.getDecryptedGroup().getBannedMembersList()));
|
||||
@@ -454,7 +454,7 @@ final class GroupManagerV2 {
|
||||
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
|
||||
{
|
||||
Recipient recipient = Recipient.resolved(recipientId);
|
||||
return commitChangeWithConflictResolution(selfAci, groupOperations.createChangeMemberRole(recipient.requireServiceId().uuid(), admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT));
|
||||
return commitChangeWithConflictResolution(selfAci, groupOperations.createChangeMemberRole(recipient.requireServiceId().getRawUuid(), admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT));
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
@@ -463,9 +463,9 @@ final class GroupManagerV2 {
|
||||
{
|
||||
GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
|
||||
DecryptedGroup decryptedGroup = groupRecord.requireV2GroupProperties().getDecryptedGroup();
|
||||
Optional<DecryptedMember> selfMember = DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), selfAci.uuid());
|
||||
Optional<DecryptedPendingMember> aciPendingMember = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), selfAci.uuid());
|
||||
Optional<DecryptedPendingMember> pniPendingMember = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), selfPni.uuid());
|
||||
Optional<DecryptedMember> selfMember = DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), selfAci.getRawUuid());
|
||||
Optional<DecryptedPendingMember> aciPendingMember = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), selfAci.getRawUuid());
|
||||
Optional<DecryptedPendingMember> pniPendingMember = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), selfPni.getRawUuid());
|
||||
Optional<DecryptedPendingMember> selfPendingMember = Optional.empty();
|
||||
ServiceId serviceId = selfAci;
|
||||
|
||||
@@ -494,7 +494,7 @@ final class GroupManagerV2 {
|
||||
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
|
||||
{
|
||||
return commitChangeWithConflictResolution(selfAci,
|
||||
groupOperations.createRemoveMembersChange(Collections.singleton(serviceId.uuid()),
|
||||
groupOperations.createRemoveMembersChange(Collections.singleton(serviceId.getRawUuid()),
|
||||
ban,
|
||||
ban ? v2GroupProperties.getDecryptedGroup().getBannedMembersList()
|
||||
: Collections.emptyList()),
|
||||
@@ -506,9 +506,9 @@ final class GroupManagerV2 {
|
||||
@NonNull GroupManager.GroupActionResult addMemberAdminsAndLeaveGroup(Collection<RecipientId> newAdmins)
|
||||
throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException
|
||||
{
|
||||
List<UUID> newAdminRecipients = Stream.of(newAdmins).map(id -> Recipient.resolved(id).requireServiceId().uuid()).toList();
|
||||
List<UUID> newAdminRecipients = Stream.of(newAdmins).map(id -> Recipient.resolved(id).requireServiceId().getRawUuid()).toList();
|
||||
|
||||
return commitChangeWithConflictResolution(selfAci, groupOperations.createLeaveAndPromoteMembersToAdmin(selfAci.uuid(),
|
||||
return commitChangeWithConflictResolution(selfAci, groupOperations.createLeaveAndPromoteMembersToAdmin(selfAci.getRawUuid(),
|
||||
newAdminRecipients));
|
||||
}
|
||||
|
||||
@@ -518,7 +518,7 @@ final class GroupManagerV2 {
|
||||
{
|
||||
ProfileKey profileKey = ProfileKeyUtil.getSelfProfileKey();
|
||||
DecryptedGroup group = groupDatabase.requireGroup(groupId).requireV2GroupProperties().getDecryptedGroup();
|
||||
Optional<DecryptedMember> selfInGroup = DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfAci.uuid());
|
||||
Optional<DecryptedMember> selfInGroup = DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfAci.getRawUuid());
|
||||
|
||||
if (!selfInGroup.isPresent()) {
|
||||
Log.w(TAG, "Self not in group " + groupId);
|
||||
@@ -548,15 +548,15 @@ final class GroupManagerV2 {
|
||||
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
|
||||
{
|
||||
DecryptedGroup group = groupDatabase.requireGroup(groupId).requireV2GroupProperties().getDecryptedGroup();
|
||||
Optional<DecryptedMember> selfInGroup = DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfAci.uuid());
|
||||
Optional<DecryptedMember> selfInGroup = DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfAci.getRawUuid());
|
||||
|
||||
if (selfInGroup.isPresent()) {
|
||||
Log.w(TAG, "Self already in group");
|
||||
return null;
|
||||
}
|
||||
|
||||
Optional<DecryptedPendingMember> aciInPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfAci.uuid());
|
||||
Optional<DecryptedPendingMember> pniInPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfPni.uuid());
|
||||
Optional<DecryptedPendingMember> aciInPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfAci.getRawUuid());
|
||||
Optional<DecryptedPendingMember> pniInPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfPni.getRawUuid());
|
||||
|
||||
GroupCandidate groupCandidate = groupCandidateHelper.recipientIdToCandidate(Recipient.self().getId());
|
||||
|
||||
@@ -650,7 +650,7 @@ final class GroupManagerV2 {
|
||||
throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException
|
||||
{
|
||||
boolean refetchedAddMemberCredentials = false;
|
||||
change.setSourceUuid(UuidUtil.toByteString(authServiceId.uuid()));
|
||||
change.setSourceUuid(UuidUtil.toByteString(authServiceId.getRawUuid()));
|
||||
|
||||
for (int attempt = 0; attempt < 5; attempt++) {
|
||||
try {
|
||||
@@ -704,7 +704,7 @@ final class GroupManagerV2 {
|
||||
GroupChange.Actions changeActions = change.build();
|
||||
|
||||
return GroupChangeUtil.resolveConflict(groupUpdateResult.getLatestServer(),
|
||||
groupOperations.decryptChange(changeActions, authServiceId.uuid()),
|
||||
groupOperations.decryptChange(changeActions, authServiceId.getRawUuid()),
|
||||
changeActions);
|
||||
} catch (VerificationFailedException | InvalidGroupStateException ex) {
|
||||
throw new GroupChangeFailedException(ex);
|
||||
@@ -1203,7 +1203,7 @@ final class GroupManagerV2 {
|
||||
void cancelJoinRequest()
|
||||
throws GroupChangeFailedException, IOException
|
||||
{
|
||||
Set<UUID> uuids = Collections.singleton(selfAci.uuid());
|
||||
Set<UUID> uuids = Collections.singleton(selfAci.getRawUuid());
|
||||
|
||||
GroupChange signedGroupChange;
|
||||
try {
|
||||
@@ -1331,8 +1331,9 @@ final class GroupManagerV2 {
|
||||
}
|
||||
|
||||
private static @NonNull List<RecipientId> getPendingMemberRecipientIds(@NonNull List<DecryptedPendingMember> newPendingMembersList) {
|
||||
// TODO [greyson][ServiceId] Pending members can be ACI's or PNI's
|
||||
return Stream.of(DecryptedGroupUtil.pendingToUuidList(newPendingMembersList))
|
||||
.map(uuid -> RecipientId.from(ServiceId.from(uuid)))
|
||||
.map(uuid -> RecipientId.from(ACI.from(uuid)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
||||
@@ -80,12 +80,12 @@ public final class GroupProtoUtil {
|
||||
|
||||
@WorkerThread
|
||||
public static Recipient pendingMemberToRecipient(@NonNull Context context, @NonNull DecryptedPendingMember pendingMember) {
|
||||
return uuidByteStringToRecipient(context, pendingMember.getUuid());
|
||||
return pendingMemberServiceIdToRecipient(context, pendingMember.getUuid());
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public static Recipient uuidByteStringToRecipient(@NonNull Context context, @NonNull ByteString uuidByteString) {
|
||||
ServiceId serviceId = ServiceId.fromByteString(uuidByteString);
|
||||
public static Recipient pendingMemberServiceIdToRecipient(@NonNull Context context, @NonNull ByteString uuidByteString) {
|
||||
ServiceId serviceId = ServiceId.parseOrThrow(uuidByteString);
|
||||
|
||||
if (serviceId.isUnknown()) {
|
||||
return Recipient.UNKNOWN;
|
||||
@@ -96,7 +96,7 @@ public final class GroupProtoUtil {
|
||||
|
||||
@WorkerThread
|
||||
public static @NonNull RecipientId uuidByteStringToRecipientId(@NonNull ByteString uuidByteString) {
|
||||
ServiceId serviceId = ServiceId.fromByteString(uuidByteString);
|
||||
ServiceId serviceId = ServiceId.parseOrThrow(uuidByteString);
|
||||
|
||||
if (serviceId.isUnknown()) {
|
||||
return RecipientId.UNKNOWN;
|
||||
|
||||
@@ -4,7 +4,6 @@ import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.libsignal.zkgroup.GenericServerPublicParams;
|
||||
import org.signal.libsignal.zkgroup.GenericServerSecretParams;
|
||||
import org.signal.libsignal.zkgroup.VerificationFailedException;
|
||||
import org.signal.libsignal.zkgroup.auth.AuthCredentialWithPniResponse;
|
||||
import org.signal.libsignal.zkgroup.calllinks.CallLinkAuthCredential;
|
||||
@@ -12,9 +11,6 @@ import org.signal.libsignal.zkgroup.calllinks.CallLinkAuthCredentialPresentation
|
||||
import org.signal.libsignal.zkgroup.calllinks.CallLinkAuthCredentialResponse;
|
||||
import org.signal.libsignal.zkgroup.calllinks.CallLinkSecretParams;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2AuthorizationString;
|
||||
@@ -130,13 +126,13 @@ public class GroupsV2Authorization {
|
||||
}
|
||||
|
||||
CallLinkAuthCredential credential = authCredentialResponse.receive(
|
||||
Recipient.self().requireServiceId().uuid(),
|
||||
Recipient.self().requireServiceId().getRawUuid(),
|
||||
Instant.ofEpochSecond(todaySeconds),
|
||||
genericServerPublicParams
|
||||
);
|
||||
|
||||
return credential.present(
|
||||
Recipient.self().requireServiceId().uuid(),
|
||||
Recipient.self().requireServiceId().getRawUuid(),
|
||||
Instant.ofEpochSecond(todaySeconds),
|
||||
genericServerPublicParams,
|
||||
callLinkSecretParams
|
||||
|
||||
@@ -111,7 +111,7 @@ public final class LiveGroup {
|
||||
|
||||
return Stream.of(requestingMembersList)
|
||||
.map(requestingMember -> {
|
||||
Recipient recipient = Recipient.externalPush(ServiceId.fromByteString(requestingMember.getUuid()));
|
||||
Recipient recipient = Recipient.externalPush(ServiceId.parseOrThrow(requestingMember.getUuid()));
|
||||
return new GroupMemberEntry.RequestingMember(recipient, selfAdmin);
|
||||
})
|
||||
.toList();
|
||||
|
||||
@@ -77,7 +77,7 @@ final class PendingMemberInvitesRepository {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Recipient inviter = GroupProtoUtil.uuidByteStringToRecipient(context, inviterUuid);
|
||||
Recipient inviter = GroupProtoUtil.pendingMemberServiceIdToRecipient(context, inviterUuid);
|
||||
ArrayList<UuidCiphertext> uuidCipherTexts = new ArrayList<>(invitedMembers.size());
|
||||
|
||||
for (DecryptedPendingMember pendingMember : invitedMembers) {
|
||||
|
||||
@@ -51,7 +51,7 @@ public class GroupCandidateHelper {
|
||||
}
|
||||
|
||||
Optional<ExpiringProfileKeyCredential> expiringProfileKeyCredential = Optional.ofNullable(recipient.getExpiringProfileKeyCredential());
|
||||
GroupCandidate candidate = new GroupCandidate(serviceId.uuid(), expiringProfileKeyCredential);
|
||||
GroupCandidate candidate = new GroupCandidate(serviceId.getRawUuid(), expiringProfileKeyCredential);
|
||||
|
||||
if (!candidate.hasValidProfileKeyCredential()) {
|
||||
recipientTable.clearProfileKeyCredential(recipient.getId());
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedMember;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
@@ -97,11 +98,11 @@ public final class ProfileKeySet {
|
||||
}
|
||||
|
||||
if (memberUuid.equals(changeSource)) {
|
||||
authoritativeProfileKeys.put(ServiceId.from(memberUuid), profileKey);
|
||||
profileKeys.remove(ServiceId.from(memberUuid));
|
||||
authoritativeProfileKeys.put(ACI.from(memberUuid), profileKey);
|
||||
profileKeys.remove(ACI.from(memberUuid));
|
||||
} else {
|
||||
if (!authoritativeProfileKeys.containsKey(ServiceId.from(memberUuid))) {
|
||||
profileKeys.put(ServiceId.from(memberUuid), profileKey);
|
||||
if (!authoritativeProfileKeys.containsKey(ACI.from(memberUuid))) {
|
||||
profileKeys.put(ACI.from(memberUuid), profileKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
|
||||
import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException;
|
||||
import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException;
|
||||
import org.whispersystems.signalservice.api.groupsv2.PartialDecryptedGroup;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIds;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.internal.push.exceptions.GroupNotFoundException;
|
||||
@@ -171,13 +171,13 @@ public class GroupsV2StateProcessor {
|
||||
}
|
||||
|
||||
private StateProcessorForGroup(@NonNull ServiceIds serviceIds,
|
||||
@NonNull Context context,
|
||||
@NonNull GroupTable groupDatabase,
|
||||
@NonNull GroupsV2Api groupsV2Api,
|
||||
@NonNull GroupsV2Authorization groupsV2Authorization,
|
||||
@NonNull GroupMasterKey groupMasterKey,
|
||||
@NonNull GroupSecretParams groupSecretParams,
|
||||
@NonNull RecipientTable recipientTable)
|
||||
@NonNull Context context,
|
||||
@NonNull GroupTable groupDatabase,
|
||||
@NonNull GroupsV2Api groupsV2Api,
|
||||
@NonNull GroupsV2Authorization groupsV2Authorization,
|
||||
@NonNull GroupMasterKey groupMasterKey,
|
||||
@NonNull GroupSecretParams groupSecretParams,
|
||||
@NonNull RecipientTable recipientTable)
|
||||
{
|
||||
this.serviceIds = serviceIds;
|
||||
this.context = context;
|
||||
@@ -425,23 +425,23 @@ public class GroupsV2StateProcessor {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
if (localState != null && localState.getRevision() >= latestServerGroup.getRevision() && GroupProtoUtil.isMember(serviceIds.getAci().uuid(), localState.getMembersList())) {
|
||||
if (localState != null && localState.getRevision() >= latestServerGroup.getRevision() && GroupProtoUtil.isMember(serviceIds.getAci().getRawUuid(), localState.getMembersList())) {
|
||||
info("Local state is at or later than server");
|
||||
return new GroupUpdateResult(GroupState.GROUP_CONSISTENT_OR_AHEAD, null);
|
||||
}
|
||||
|
||||
if (latestRevisionOnly || !GroupProtoUtil.isMember(serviceIds.getAci().uuid(), latestServerGroup.getMembersList())) {
|
||||
if (latestRevisionOnly || !GroupProtoUtil.isMember(serviceIds.getAci().getRawUuid(), latestServerGroup.getMembersList())) {
|
||||
info("Latest revision or not a member, use latest only");
|
||||
inputGroupState = new GlobalGroupState(localState, Collections.singletonList(new ServerGroupLogEntry(latestServerGroup.getFullyDecryptedGroup(), null)));
|
||||
} else {
|
||||
int revisionWeWereAdded = GroupProtoUtil.findRevisionWeWereAdded(latestServerGroup, serviceIds.getAci().uuid());
|
||||
int revisionWeWereAdded = GroupProtoUtil.findRevisionWeWereAdded(latestServerGroup, serviceIds.getAci().getRawUuid());
|
||||
int logsNeededFrom = localState != null ? Math.max(localState.getRevision(), revisionWeWereAdded) : revisionWeWereAdded;
|
||||
|
||||
boolean includeFirstState = forceIncludeFirst ||
|
||||
localState == null ||
|
||||
localState.getRevision() < 0 ||
|
||||
localState.getRevision() == revisionWeWereAdded ||
|
||||
!GroupProtoUtil.isMember(serviceIds.getAci().uuid(), localState.getMembersList()) ||
|
||||
!GroupProtoUtil.isMember(serviceIds.getAci().getRawUuid(), localState.getMembersList()) ||
|
||||
(revision == LATEST && localState.getRevision() + 1 < latestServerGroup.getRevision());
|
||||
|
||||
info("Requesting from server currentRevision: " + (localState != null ? localState.getRevision() : "null") +
|
||||
@@ -556,7 +556,7 @@ public class GroupsV2StateProcessor {
|
||||
}
|
||||
|
||||
Recipient groupRecipient = Recipient.externalGroupExact(groupId);
|
||||
UUID selfUuid = serviceIds.getAci().uuid();
|
||||
UUID selfUuid = serviceIds.getAci().getRawUuid();
|
||||
|
||||
DecryptedGroup decryptedGroup = groupDatabase.requireGroup(groupId)
|
||||
.requireV2GroupProperties()
|
||||
@@ -668,17 +668,17 @@ public class GroupsV2StateProcessor {
|
||||
@VisibleForTesting
|
||||
static class ProfileAndMessageHelper {
|
||||
|
||||
private final Context context;
|
||||
private final ServiceId serviceId;
|
||||
private final Context context;
|
||||
private final ACI aci;
|
||||
private final GroupId.V2 groupId;
|
||||
private final RecipientTable recipientTable;
|
||||
|
||||
@VisibleForTesting
|
||||
GroupMasterKey masterKey;
|
||||
|
||||
ProfileAndMessageHelper(@NonNull Context context, @NonNull ServiceId serviceId, @NonNull GroupMasterKey masterKey, @NonNull GroupId.V2 groupId, @NonNull RecipientTable recipientTable) {
|
||||
ProfileAndMessageHelper(@NonNull Context context, @NonNull ACI aci, @NonNull GroupMasterKey masterKey, @NonNull GroupId.V2 groupId, @NonNull RecipientTable recipientTable) {
|
||||
this.context = context;
|
||||
this.serviceId = serviceId;
|
||||
this.aci = aci;
|
||||
this.masterKey = masterKey;
|
||||
this.groupId = groupId;
|
||||
this.recipientTable = recipientTable;
|
||||
@@ -686,15 +686,15 @@ public class GroupsV2StateProcessor {
|
||||
|
||||
void determineProfileSharing(@NonNull GlobalGroupState inputGroupState, @NonNull DecryptedGroup newLocalState) {
|
||||
if (inputGroupState.getLocalState() != null) {
|
||||
boolean wasAMemberAlready = DecryptedGroupUtil.findMemberByUuid(inputGroupState.getLocalState().getMembersList(), serviceId.uuid()).isPresent();
|
||||
boolean wasAMemberAlready = DecryptedGroupUtil.findMemberByUuid(inputGroupState.getLocalState().getMembersList(), aci.getRawUuid()).isPresent();
|
||||
|
||||
if (wasAMemberAlready) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Optional<DecryptedMember> selfAsMemberOptional = DecryptedGroupUtil.findMemberByUuid(newLocalState.getMembersList(), serviceId.uuid());
|
||||
Optional<DecryptedPendingMember> selfAsPendingOptional = DecryptedGroupUtil.findPendingByUuid(newLocalState.getPendingMembersList(), serviceId.uuid());
|
||||
Optional<DecryptedMember> selfAsMemberOptional = DecryptedGroupUtil.findMemberByUuid(newLocalState.getMembersList(), aci.getRawUuid());
|
||||
Optional<DecryptedPendingMember> selfAsPendingOptional = DecryptedGroupUtil.findPendingByUuid(newLocalState.getPendingMembersList(), aci.getRawUuid());
|
||||
|
||||
if (selfAsMemberOptional.isPresent()) {
|
||||
DecryptedMember selfAsMember = selfAsMemberOptional.get();
|
||||
@@ -705,7 +705,7 @@ public class GroupsV2StateProcessor {
|
||||
.filter(c -> c != null && c.getRevision() == revisionJoinedAt)
|
||||
.findFirst()
|
||||
.map(c -> Optional.ofNullable(UuidUtil.fromByteStringOrNull(c.getEditor()))
|
||||
.map(uuid -> Recipient.externalPush(ServiceId.from(uuid))))
|
||||
.map(uuid -> Recipient.externalPush(ACI.from(uuid))))
|
||||
.orElse(Optional.empty());
|
||||
|
||||
if (addedByOptional.isPresent()) {
|
||||
@@ -713,7 +713,7 @@ public class GroupsV2StateProcessor {
|
||||
|
||||
Log.i(TAG, String.format("Added as a full member of %s by %s", groupId, addedBy.getId()));
|
||||
|
||||
if (addedBy.isBlocked() && (inputGroupState.getLocalState() == null || !DecryptedGroupUtil.isRequesting(inputGroupState.getLocalState(), serviceId.uuid()))) {
|
||||
if (addedBy.isBlocked() && (inputGroupState.getLocalState() == null || !DecryptedGroupUtil.isRequesting(inputGroupState.getLocalState(), aci.getRawUuid()))) {
|
||||
Log.i(TAG, "Added by a blocked user. Leaving group.");
|
||||
ApplicationDependencies.getJobManager().add(new LeaveGroupV2Job(groupId));
|
||||
//noinspection UnnecessaryReturnStatement
|
||||
@@ -730,7 +730,7 @@ public class GroupsV2StateProcessor {
|
||||
}
|
||||
} else if (selfAsPendingOptional.isPresent()) {
|
||||
Optional<Recipient> addedBy = selfAsPendingOptional.flatMap(adder -> Optional.ofNullable(UuidUtil.fromByteStringOrNull(adder.getAddedByUuid()))
|
||||
.map(uuid -> Recipient.externalPush(ServiceId.from(uuid))));
|
||||
.map(uuid -> Recipient.externalPush(ACI.from(uuid))));
|
||||
|
||||
if (addedBy.isPresent() && addedBy.get().isBlocked()) {
|
||||
Log.i(TAG, String.format("Added to group %s by a blocked user %s. Leaving group.", groupId, addedBy.get().getId()));
|
||||
@@ -795,9 +795,9 @@ public class GroupsV2StateProcessor {
|
||||
}
|
||||
|
||||
void storeMessage(@NonNull DecryptedGroupV2Context decryptedGroupV2Context, long timestamp) {
|
||||
Optional<ServiceId> editor = getEditor(decryptedGroupV2Context).map(ServiceId::from);
|
||||
Optional<ACI> editor = getEditor(decryptedGroupV2Context).map(ACI::from);
|
||||
|
||||
boolean outgoing = !editor.isPresent() || serviceId.equals(editor.get());
|
||||
boolean outgoing = !editor.isPresent() || aci.equals(editor.get());
|
||||
|
||||
if (outgoing) {
|
||||
try {
|
||||
@@ -835,7 +835,7 @@ public class GroupsV2StateProcessor {
|
||||
if (changeEditor.isPresent()) {
|
||||
return changeEditor;
|
||||
} else {
|
||||
Optional<DecryptedPendingMember> pendingByUuid = DecryptedGroupUtil.findPendingByUuid(decryptedGroupV2Context.getGroupState().getPendingMembersList(), serviceId.uuid());
|
||||
Optional<DecryptedPendingMember> pendingByUuid = DecryptedGroupUtil.findPendingByUuid(decryptedGroupV2Context.getGroupState().getPendingMembersList(), aci.getRawUuid());
|
||||
if (pendingByUuid.isPresent()) {
|
||||
return Optional.ofNullable(UuidUtil.fromByteStringOrNull(pendingByUuid.get().getAddedByUuid()));
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ public class AutomaticSessionResetJob extends BaseJob {
|
||||
|
||||
@Override
|
||||
protected void onRun() throws Exception {
|
||||
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSession(recipientId, deviceId);
|
||||
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSessions(recipientId, deviceId);
|
||||
SignalDatabase.senderKeyShared().deleteAllFor(recipientId);
|
||||
insertLocalMessage();
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ public final class GroupV2UpdateSelfProfileKeyJob extends BaseJob {
|
||||
continue;
|
||||
}
|
||||
|
||||
ByteString selfUuidBytes = UuidUtil.toByteString(Recipient.self().requireServiceId().uuid());
|
||||
ByteString selfUuidBytes = UuidUtil.toByteString(Recipient.self().requireAci().getRawUuid());
|
||||
DecryptedMember selfMember = group.get().requireV2GroupProperties().getDecryptedGroup().getMembersList()
|
||||
.stream()
|
||||
.filter(m -> m.getUuid().equals(selfUuidBytes))
|
||||
|
||||
@@ -74,7 +74,7 @@ class MultiDeviceStorySendSyncJob private constructor(parameters: Parameters, pr
|
||||
|
||||
private fun buildSentTranscript(recipientsSet: Set<SignalServiceStoryMessageRecipient>): SentTranscriptMessage {
|
||||
return SentTranscriptMessage(
|
||||
Optional.of(SignalServiceAddress(Recipient.self().requireServiceId())),
|
||||
Optional.of(SignalServiceAddress(Recipient.self().requireAci())),
|
||||
sentTimestamp,
|
||||
Optional.empty(),
|
||||
0,
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
|
||||
@@ -77,8 +77,8 @@ public final class PushGroupSilentUpdateSendJob extends BaseJob {
|
||||
|
||||
Set<RecipientId> recipients = Stream.concat(Stream.of(memberUuids), Stream.of(pendingUuids))
|
||||
.filter(uuid -> !UuidUtil.UNKNOWN_UUID.equals(uuid))
|
||||
.filter(uuid -> !SignalStore.account().requireAci().uuid().equals(uuid))
|
||||
.map(uuid -> Recipient.externalPush(ServiceId.from(uuid)))
|
||||
.filter(uuid -> !SignalStore.account().requireAci().getRawUuid().equals(uuid))
|
||||
.map(uuid -> Recipient.externalPush(ACI.from(uuid)))
|
||||
.filter(recipient -> recipient.getRegistered() != RecipientTable.RegisteredState.NOT_REGISTERED)
|
||||
.map(Recipient::getId)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
@@ -67,6 +67,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemo
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServicePreview;
|
||||
import org.whispersystems.signalservice.api.messages.shared.SharedContact;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException;
|
||||
@@ -325,7 +326,7 @@ public abstract class PushSendJob extends SendJob {
|
||||
protected Optional<SignalServiceDataMessage.Quote> getQuoteFor(OutgoingMessage message) throws IOException {
|
||||
if (message.getOutgoingQuote() == null) return Optional.empty();
|
||||
if (message.isMessageEdit()) {
|
||||
return Optional.of(new SignalServiceDataMessage.Quote(0, ServiceId.UNKNOWN, "", null, null, SignalServiceDataMessage.Quote.Type.NORMAL, null));
|
||||
return Optional.of(new SignalServiceDataMessage.Quote(0, ACI.UNKNOWN, "", null, null, SignalServiceDataMessage.Quote.Type.NORMAL, null));
|
||||
}
|
||||
|
||||
long quoteId = message.getOutgoingQuote().getId();
|
||||
@@ -383,7 +384,7 @@ public abstract class PushSendJob extends SendJob {
|
||||
if (quoteAuthorRecipient.isMaybeRegistered()) {
|
||||
return Optional.of(new SignalServiceDataMessage.Quote(quoteId, RecipientUtil.getOrFetchServiceId(context, quoteAuthorRecipient), quoteBody, quoteAttachments, quoteMentions, quoteType.getDataMessageType(), bodyRanges));
|
||||
} else if (quoteAuthorRecipient.hasServiceId()) {
|
||||
return Optional.of(new SignalServiceDataMessage.Quote(quoteId, quoteAuthorRecipient.requireServiceId(), quoteBody, quoteAttachments, quoteMentions, quoteType.getDataMessageType(), bodyRanges));
|
||||
return Optional.of(new SignalServiceDataMessage.Quote(quoteId, quoteAuthorRecipient.requireAci(), quoteBody, quoteAttachments, quoteMentions, quoteType.getDataMessageType(), bodyRanges));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
@@ -451,7 +452,7 @@ public abstract class PushSendJob extends SendJob {
|
||||
|
||||
List<SignalServiceDataMessage.Mention> getMentionsFor(@NonNull List<Mention> mentions) {
|
||||
return Stream.of(mentions)
|
||||
.map(m -> new SignalServiceDataMessage.Mention(Recipient.resolved(m.getRecipientId()).requireServiceId(), m.getStart(), m.getLength()))
|
||||
.map(m -> new SignalServiceDataMessage.Mention(Recipient.resolved(m.getRecipientId()).requireAci(), m.getStart(), m.getLength()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ import org.thoughtcrime.securesms.service.KeyCachingService
|
||||
import org.thoughtcrime.securesms.util.Base64
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.whispersystems.signalservice.api.push.ACI
|
||||
import org.whispersystems.signalservice.api.push.PNI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI
|
||||
import org.whispersystems.signalservice.api.push.ServiceIds
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import java.security.SecureRandom
|
||||
@@ -85,6 +85,12 @@ internal class AccountValues internal constructor(store: KeyValueStore) : Signal
|
||||
if (!store.containsKey(KEY_ACI_IDENTITY_PUBLIC_KEY)) {
|
||||
migrateFromSharedPrefsV2(ApplicationDependencies.getApplication())
|
||||
}
|
||||
|
||||
store.getString(KEY_PNI, null)?.let { pni ->
|
||||
if (!pni.startsWith("PNI:")) {
|
||||
store.beginWrite().putString(KEY_PNI, "PNI:$pni").commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onFirstEverAppLaunch() = Unit
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.VersionTracker;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
|
||||
@@ -42,7 +42,7 @@ object CallMessageProcessor {
|
||||
handleCallHangupMessage(envelope, metadata, hangup, senderRecipient.id, callMessage.hasLegacyHangup())
|
||||
}
|
||||
callMessage.hasBusy() -> handleCallBusyMessage(envelope, metadata, callMessage.busy, senderRecipient.id)
|
||||
callMessage.hasOpaque() -> handleCallOpaqueMessage(envelope, metadata, callMessage.opaque, senderRecipient.requireServiceId(), serverDeliveredTimestamp)
|
||||
callMessage.hasOpaque() -> handleCallOpaqueMessage(envelope, metadata, callMessage.opaque, senderRecipient.requireAci(), serverDeliveredTimestamp)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ object CallMessageProcessor {
|
||||
ApplicationDependencies.getSignalCallManager()
|
||||
.receivedOpaqueMessage(
|
||||
OpaqueMessageMetadata(
|
||||
senderServiceId.uuid(),
|
||||
senderServiceId.rawUuid,
|
||||
opaque.data.toByteArray(),
|
||||
metadata.sourceDeviceId,
|
||||
messageAgeSeconds
|
||||
|
||||
@@ -95,6 +95,7 @@ import org.thoughtcrime.securesms.util.isStory
|
||||
import org.whispersystems.signalservice.api.crypto.EnvelopeMetadata
|
||||
import org.whispersystems.signalservice.api.payments.Money
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.api.util.OptionalUtil.asOptional
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.BodyRange
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.Content
|
||||
@@ -992,10 +993,10 @@ object DataMessageProcessor {
|
||||
return mentionBodyRanges
|
||||
.filter { it.hasMentionAci() }
|
||||
.mapNotNull {
|
||||
val serviceId = ServiceId.parseOrNull(it.mentionAci)
|
||||
val aci = ACI.parseOrNull(it.mentionAci)
|
||||
|
||||
if (serviceId != null && !serviceId.isUnknown) {
|
||||
val id = Recipient.externalPush(serviceId).id
|
||||
if (aci != null && !aci.isUnknown) {
|
||||
val id = Recipient.externalPush(aci).id
|
||||
Mention(id, it.start, it.length)
|
||||
} else {
|
||||
null
|
||||
|
||||
@@ -537,7 +537,7 @@ public class MessageContentProcessor {
|
||||
Optional<GroupRecord> groupRecord = groupDatabase.getGroup(groupId);
|
||||
|
||||
if (groupRecord.isPresent() && !groupRecord.get().getMembers().contains(senderRecipient.getId())) {
|
||||
log(String.valueOf(content.getTimestamp()), "Ignoring GV2 message from member not in group " + groupId + ". Sender: " + senderRecipient.getId() + " | " + senderRecipient.requireServiceId());
|
||||
log(String.valueOf(content.getTimestamp()), "Ignoring GV2 message from member not in group " + groupId + ". Sender: " + senderRecipient.getId() + " | " + senderRecipient.requireAci());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -739,7 +739,7 @@ public class MessageContentProcessor {
|
||||
}
|
||||
|
||||
ApplicationDependencies.getSignalCallManager()
|
||||
.receivedOpaqueMessage(new WebRtcData.OpaqueMessageMetadata(senderRecipient.requireServiceId().uuid(),
|
||||
.receivedOpaqueMessage(new WebRtcData.OpaqueMessageMetadata(senderRecipient.requireAci().getRawUuid(),
|
||||
message.getOpaque(),
|
||||
content.getSenderDevice(),
|
||||
messageAgeSeconds));
|
||||
@@ -843,7 +843,7 @@ public class MessageContentProcessor {
|
||||
log(content.getTimestamp(), "Unknown group message.");
|
||||
|
||||
warn(content.getTimestamp(), "Received a GV2 message for a group we have no knowledge of -- attempting to fix this state.");
|
||||
ServiceId authServiceId = ServiceId.parseOrNull(content.getDestinationUuid());
|
||||
ServiceId authServiceId = ServiceId.parseOrNull(content.getDestinationServiceId());
|
||||
if (authServiceId == null) {
|
||||
warn(content.getTimestamp(), "Group message missing destination uuid, defaulting to ACI");
|
||||
authServiceId = SignalStore.account().requireAci();
|
||||
@@ -1290,7 +1290,7 @@ public class MessageContentProcessor {
|
||||
return;
|
||||
}
|
||||
|
||||
ServiceId serviceId = ServiceId.fromByteString(callEvent.getConversationId());
|
||||
ServiceId serviceId = ServiceId.parseOrThrow(callEvent.getConversationId());
|
||||
RecipientId recipientId = RecipientId.from(serviceId);
|
||||
|
||||
log(envelopeTimestamp, "Synchronize call event call: " + callId);
|
||||
@@ -3061,7 +3061,7 @@ public class MessageContentProcessor {
|
||||
ratchetKeyMatches(requester, content.getSenderDevice(), decryptionErrorMessage.getRatchetKey().get()))
|
||||
{
|
||||
warn(content.getTimestamp(), "[RetryReceipt-I] Ratchet key matches. Archiving the session.");
|
||||
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSession(requester.getId(), content.getSenderDevice());
|
||||
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSession(requester.requireServiceId(), content.getSenderDevice());
|
||||
archivedSession = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -569,7 +569,7 @@ open class MessageContentProcessorV2(private val context: Context) {
|
||||
ratchetKeyMatches(requester, metadata.sourceDeviceId, decryptionErrorMessage.ratchetKey.get())
|
||||
) {
|
||||
warn(envelope.timestamp, "[RetryReceipt-I] Ratchet key matches. Archiving the session.")
|
||||
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSession(requester.id, metadata.sourceDeviceId)
|
||||
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSession(requester.requireServiceId(), metadata.sourceDeviceId)
|
||||
archivedSession = true
|
||||
}
|
||||
|
||||
@@ -604,7 +604,7 @@ open class MessageContentProcessorV2(private val context: Context) {
|
||||
}
|
||||
|
||||
private fun ratchetKeyMatches(recipient: Recipient, deviceId: Int, ratchetKey: ECPublicKey): Boolean {
|
||||
val address = recipient.resolve().requireServiceId().toProtocolAddress(deviceId)
|
||||
val address = recipient.resolve().requireAci().toProtocolAddress(deviceId)
|
||||
val session = ApplicationDependencies.getProtocolStore().aci().loadSession(address)
|
||||
return session.currentRatchetKeyMatches(ratchetKey)
|
||||
}
|
||||
|
||||
@@ -55,8 +55,9 @@ import org.whispersystems.signalservice.api.crypto.SignalGroupSessionBuilder
|
||||
import org.whispersystems.signalservice.api.crypto.SignalServiceCipher
|
||||
import org.whispersystems.signalservice.api.crypto.SignalServiceCipherResult
|
||||
import org.whispersystems.signalservice.api.messages.EnvelopeContentValidator
|
||||
import org.whispersystems.signalservice.api.push.PNI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.Content
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.Envelope
|
||||
@@ -158,13 +159,17 @@ object MessageDecryptor {
|
||||
}
|
||||
|
||||
if (FeatureFlags.phoneNumberPrivacy() && cipherResult.content.hasPniSignatureMessage()) {
|
||||
handlePniSignatureMessage(
|
||||
envelope,
|
||||
cipherResult.metadata.sourceServiceId,
|
||||
cipherResult.metadata.sourceE164,
|
||||
cipherResult.metadata.sourceDeviceId,
|
||||
cipherResult.content.pniSignatureMessage
|
||||
)
|
||||
if (cipherResult.metadata.sourceServiceId is ACI) {
|
||||
handlePniSignatureMessage(
|
||||
envelope,
|
||||
cipherResult.metadata.sourceServiceId as ACI,
|
||||
cipherResult.metadata.sourceE164,
|
||||
cipherResult.metadata.sourceDeviceId,
|
||||
cipherResult.content.pniSignatureMessage
|
||||
)
|
||||
} else {
|
||||
Log.w(TAG, "${logPrefix(envelope)} Ignoring PNI signature because the sourceServiceId isn't an ACI!")
|
||||
}
|
||||
} else if (cipherResult.content.hasPniSignatureMessage()) {
|
||||
Log.w(TAG, "${logPrefix(envelope)} Ignoring PNI signature because the feature flag is disabled!")
|
||||
}
|
||||
@@ -295,37 +300,37 @@ object MessageDecryptor {
|
||||
SignalGroupSessionBuilder(ReentrantSessionLock.INSTANCE, GroupSessionBuilder(senderKeyStore)).process(sender, message)
|
||||
}
|
||||
|
||||
private fun handlePniSignatureMessage(envelope: Envelope, serviceId: ServiceId, e164: String?, deviceId: Int, pniSignatureMessage: PniSignatureMessage) {
|
||||
Log.i(TAG, "${logPrefix(envelope, serviceId)} Processing PniSignatureMessage")
|
||||
private fun handlePniSignatureMessage(envelope: Envelope, aci: ACI, e164: String?, deviceId: Int, pniSignatureMessage: PniSignatureMessage) {
|
||||
Log.i(TAG, "${logPrefix(envelope, aci)} Processing PniSignatureMessage")
|
||||
|
||||
val pni: PNI = PNI.parseOrThrow(pniSignatureMessage.pni.toByteArray())
|
||||
|
||||
if (SignalDatabase.recipients.isAssociated(serviceId, pni)) {
|
||||
Log.i(TAG, "${logPrefix(envelope, serviceId)}[handlePniSignatureMessage] ACI ($serviceId) and PNI ($pni) are already associated.")
|
||||
if (SignalDatabase.recipients.isAssociated(aci, pni)) {
|
||||
Log.i(TAG, "${logPrefix(envelope, aci)}[handlePniSignatureMessage] ACI ($aci) and PNI ($pni) are already associated.")
|
||||
return
|
||||
}
|
||||
|
||||
val identityStore = ApplicationDependencies.getProtocolStore().aci().identities()
|
||||
val aciAddress = SignalProtocolAddress(serviceId.toString(), deviceId)
|
||||
val aciAddress = SignalProtocolAddress(aci.toString(), deviceId)
|
||||
val pniAddress = SignalProtocolAddress(pni.toString(), deviceId)
|
||||
val aciIdentity = identityStore.getIdentity(aciAddress)
|
||||
val pniIdentity = identityStore.getIdentity(pniAddress)
|
||||
|
||||
if (aciIdentity == null) {
|
||||
Log.w(TAG, "${logPrefix(envelope, serviceId)}[validatePniSignature] No identity found for ACI address $aciAddress")
|
||||
Log.w(TAG, "${logPrefix(envelope, aci)}[validatePniSignature] No identity found for ACI address $aciAddress")
|
||||
return
|
||||
}
|
||||
|
||||
if (pniIdentity == null) {
|
||||
Log.w(TAG, "${logPrefix(envelope, serviceId)}[validatePniSignature] No identity found for PNI address $pniAddress")
|
||||
Log.w(TAG, "${logPrefix(envelope, aci)}[validatePniSignature] No identity found for PNI address $pniAddress")
|
||||
return
|
||||
}
|
||||
|
||||
if (pniIdentity.verifyAlternateIdentity(aciIdentity, pniSignatureMessage.signature.toByteArray())) {
|
||||
Log.i(TAG, "${logPrefix(envelope, serviceId)}[validatePniSignature] PNI signature is valid. Associating ACI ($serviceId) with PNI ($pni)")
|
||||
SignalDatabase.recipients.getAndPossiblyMergePnpVerified(serviceId, pni, e164)
|
||||
Log.i(TAG, "${logPrefix(envelope, aci)}[validatePniSignature] PNI signature is valid. Associating ACI ($aci) with PNI ($pni)")
|
||||
SignalDatabase.recipients.getAndPossiblyMergePnpVerified(aci, pni, e164)
|
||||
} else {
|
||||
Log.w(TAG, "${logPrefix(envelope, serviceId)}[validatePniSignature] Invalid PNI signature! Cannot associate ACI ($serviceId) with PNI ($pni)")
|
||||
Log.w(TAG, "${logPrefix(envelope, aci)}[validatePniSignature] Invalid PNI signature! Cannot associate ACI ($aci) with PNI ($pni)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ import org.whispersystems.signalservice.api.crypto.EnvelopeMetadata
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer
|
||||
import org.whispersystems.signalservice.api.push.DistributionId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.api.storage.StorageKey
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos
|
||||
@@ -1227,8 +1228,8 @@ object SyncMessageProcessor {
|
||||
return
|
||||
}
|
||||
|
||||
val serviceId = ServiceId.fromByteString(callEvent.conversationId)
|
||||
val recipientId = RecipientId.from(serviceId)
|
||||
val aci = ACI.parseOrThrow(callEvent.conversationId)
|
||||
val recipientId = RecipientId.from(aci)
|
||||
|
||||
log(envelopeTimestamp, "Synchronize call event call: $callId")
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.account.PreKeyUpload;
|
||||
import org.whispersystems.signalservice.api.push.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.whispersystems.signalservice.api.push.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -191,7 +191,7 @@ public final class MessageGroupContext {
|
||||
List<RecipientId> members = new ArrayList<>(decryptedGroupV2Context.getGroupState().getMembersCount());
|
||||
|
||||
for (DecryptedMember member : decryptedGroupV2Context.getGroupState().getMembersList()) {
|
||||
RecipientId recipient = RecipientId.from(ServiceId.fromByteString(member.getUuid()));
|
||||
RecipientId recipient = RecipientId.from(ServiceId.parseOrThrow(member.getUuid()));
|
||||
if (!Recipient.self().getId().equals(recipient)) {
|
||||
members.add(recipient);
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.push.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
|
||||
public class AccountManagerFactory {
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.signal.core.util.CursorUtil;
|
||||
import org.thoughtcrime.securesms.util.LRUCache;
|
||||
import org.signal.core.util.Stopwatch;
|
||||
import org.thoughtcrime.securesms.util.concurrent.FilteredExecutor;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -160,7 +160,7 @@ public final class LiveRecipientCache {
|
||||
}
|
||||
|
||||
if (localAci != null) {
|
||||
selfId = recipientTable.getByServiceId(localAci).orElse(null);
|
||||
selfId = recipientTable.getByAci(localAci).orElse(null);
|
||||
}
|
||||
|
||||
if (selfId == null && localE164 != null) {
|
||||
|
||||
@@ -49,7 +49,8 @@ import org.thoughtcrime.securesms.util.AvatarUtil;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
|
||||
import org.whispersystems.signalservice.api.push.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.util.OptionalUtil;
|
||||
@@ -86,7 +87,7 @@ public class Recipient {
|
||||
|
||||
private final RecipientId id;
|
||||
private final boolean resolving;
|
||||
private final ServiceId serviceId;
|
||||
private final ACI aci;
|
||||
private final PNI pni;
|
||||
private final String username;
|
||||
private final String e164;
|
||||
@@ -219,8 +220,8 @@ public class Recipient {
|
||||
* Create a recipient with a full (ACI, PNI, E164) tuple. It is assumed that the association between the PNI and serviceId is trusted.
|
||||
* That means it must be from either storage service or a PNI verification message.
|
||||
*/
|
||||
public static @NonNull Recipient trustedPush(@NonNull ServiceId serviceId, @Nullable PNI pni, @Nullable String e164) {
|
||||
if (ServiceId.UNKNOWN.equals(serviceId)) {
|
||||
public static @NonNull Recipient trustedPush(@NonNull ACI aci, @Nullable PNI pni, @Nullable String e164) {
|
||||
if (ACI.UNKNOWN.equals(aci) || PNI.UNKNOWN.equals(pni)) {
|
||||
throw new AssertionError("Unknown serviceId!");
|
||||
}
|
||||
|
||||
@@ -229,9 +230,9 @@ public class Recipient {
|
||||
RecipientId recipientId;
|
||||
|
||||
if (FeatureFlags.phoneNumberPrivacy()) {
|
||||
recipientId = db.getAndPossiblyMergePnpVerified(serviceId, pni, e164);
|
||||
recipientId = db.getAndPossiblyMergePnpVerified(aci, pni, e164);
|
||||
} else {
|
||||
recipientId = db.getAndPossiblyMerge(serviceId, e164);
|
||||
recipientId = db.getAndPossiblyMerge(aci, e164);
|
||||
}
|
||||
|
||||
Recipient resolved = resolved(recipientId);
|
||||
@@ -242,7 +243,7 @@ public class Recipient {
|
||||
|
||||
if (!resolved.isRegistered()) {
|
||||
Log.w(TAG, "External push was locally marked unregistered. Marking as registered.");
|
||||
db.markRegistered(recipientId, serviceId);
|
||||
db.markRegistered(recipientId, aci);
|
||||
}
|
||||
|
||||
return resolved;
|
||||
@@ -259,7 +260,7 @@ public class Recipient {
|
||||
*/
|
||||
@WorkerThread
|
||||
static @NonNull Recipient externalPush(@Nullable ServiceId serviceId, @Nullable String e164) {
|
||||
if (ServiceId.UNKNOWN.equals(serviceId)) {
|
||||
if (ACI.UNKNOWN.equals(serviceId) || PNI.UNKNOWN.equals(serviceId)) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@@ -375,7 +376,7 @@ public class Recipient {
|
||||
Recipient(@NonNull RecipientId id) {
|
||||
this.id = id;
|
||||
this.resolving = true;
|
||||
this.serviceId = null;
|
||||
this.aci = null;
|
||||
this.pni = null;
|
||||
this.username = null;
|
||||
this.e164 = null;
|
||||
@@ -433,7 +434,7 @@ public class Recipient {
|
||||
public Recipient(@NonNull RecipientId id, @NonNull RecipientDetails details, boolean resolved) {
|
||||
this.id = id;
|
||||
this.resolving = !resolved;
|
||||
this.serviceId = details.serviceId;
|
||||
this.aci = details.aci;
|
||||
this.pni = details.pni;
|
||||
this.username = details.username;
|
||||
this.e164 = details.e164;
|
||||
@@ -661,7 +662,11 @@ public class Recipient {
|
||||
}
|
||||
|
||||
public @NonNull Optional<ServiceId> getServiceId() {
|
||||
return Optional.ofNullable(serviceId);
|
||||
return OptionalUtil.or(Optional.ofNullable(aci), Optional.ofNullable(pni));
|
||||
}
|
||||
|
||||
public @NonNull Optional<ACI> getAci() {
|
||||
return Optional.ofNullable(aci);
|
||||
}
|
||||
|
||||
public @NonNull Optional<PNI> getPni() {
|
||||
@@ -750,6 +755,14 @@ public class Recipient {
|
||||
return getServiceId().isPresent();
|
||||
}
|
||||
|
||||
public boolean hasAci() {
|
||||
return getAci().isPresent();
|
||||
}
|
||||
|
||||
public boolean hasPni() {
|
||||
return getPni().isPresent();
|
||||
}
|
||||
|
||||
public boolean isServiceIdOnly() {
|
||||
return hasServiceId() && !hasSmsAddress();
|
||||
}
|
||||
@@ -786,7 +799,22 @@ public class Recipient {
|
||||
* The {@link ServiceId} of the user if available, otherwise throw.
|
||||
*/
|
||||
public @NonNull ServiceId requireServiceId() {
|
||||
ServiceId resolved = resolving ? resolve().serviceId : serviceId;
|
||||
Recipient resolved = resolving ? resolve() : this;
|
||||
|
||||
if (resolved.aci != null) {
|
||||
return resolved.aci;
|
||||
} else if (resolved.pni != null) {
|
||||
return resolved.pni;
|
||||
} else {
|
||||
throw new MissingAddressError(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link ACI} of the user if available, otherwise throw.
|
||||
*/
|
||||
public @NonNull ACI requireAci() {
|
||||
ACI resolved = resolving ? resolve().aci : aci;
|
||||
|
||||
if (resolved == null) {
|
||||
throw new MissingAddressError(id);
|
||||
@@ -1326,7 +1354,7 @@ public class Recipient {
|
||||
profileSharing == other.profileSharing &&
|
||||
isHidden == other.isHidden &&
|
||||
forceSmsSelection == other.forceSmsSelection &&
|
||||
Objects.equals(serviceId, other.serviceId) &&
|
||||
Objects.equals(aci, other.aci) &&
|
||||
Objects.equals(username, other.username) &&
|
||||
Objects.equals(e164, other.e164) &&
|
||||
Objects.equals(email, other.email) &&
|
||||
|
||||
@@ -26,8 +26,8 @@ import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
|
||||
import org.whispersystems.signalservice.api.push.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
@@ -36,7 +36,7 @@ import java.util.Optional;
|
||||
|
||||
public class RecipientDetails {
|
||||
|
||||
final ServiceId serviceId;
|
||||
final ACI aci;
|
||||
final PNI pni;
|
||||
final String username;
|
||||
final String e164;
|
||||
@@ -108,7 +108,7 @@ public class RecipientDetails {
|
||||
this.systemContactPhoto = Util.uri(record.getSystemContactPhotoUri());
|
||||
this.customLabel = record.getSystemPhoneLabel();
|
||||
this.contactUri = Util.uri(record.getSystemContactUri());
|
||||
this.serviceId = record.getServiceId();
|
||||
this.aci = record.getAci();
|
||||
this.pni = record.getPni();
|
||||
this.username = record.getUsername();
|
||||
this.e164 = record.getE164();
|
||||
@@ -165,7 +165,7 @@ public class RecipientDetails {
|
||||
this.systemContactPhoto = null;
|
||||
this.customLabel = null;
|
||||
this.contactUri = null;
|
||||
this.serviceId = null;
|
||||
this.aci = null;
|
||||
this.pni = null;
|
||||
this.username = null;
|
||||
this.e164 = null;
|
||||
@@ -220,7 +220,7 @@ public class RecipientDetails {
|
||||
public static @NonNull RecipientDetails forIndividual(@NonNull Context context, @NonNull RecipientRecord settings) {
|
||||
boolean systemContact = !settings.getSystemProfileName().isEmpty();
|
||||
boolean isSelf = (settings.getE164() != null && settings.getE164().equals(SignalStore.account().getE164())) ||
|
||||
(settings.getServiceId() != null && settings.getServiceId().equals(SignalStore.account().getAci()));
|
||||
(settings.getAci() != null && settings.getAci().equals(SignalStore.account().getAci()));
|
||||
boolean isReleaseChannel = settings.getId().equals(SignalStore.releaseChannelValues().getReleaseChannelRecipientId());
|
||||
|
||||
RegisteredState registeredState = settings.getRegistered();
|
||||
|
||||
@@ -38,8 +38,8 @@ import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.account.PreKeyCollection;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.push.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.util.Preconditions;
|
||||
@@ -129,7 +129,7 @@ public final class RegistrationRepository {
|
||||
Preconditions.checkNotNull(response.getPniPreKeyCollection(), "Missing PNI prekey collection!");
|
||||
|
||||
ACI aci = ACI.parseOrThrow(response.getVerifyAccountResponse().getUuid());
|
||||
PNI pni = PNI.parseOrThrow(response.getVerifyAccountResponse().getPni());
|
||||
PNI pni = PNI.parseUnPrefixedOrThrow(response.getVerifyAccountResponse().getPni());
|
||||
boolean hasPin = response.getVerifyAccountResponse().isStorageCapable();
|
||||
|
||||
SignalStore.account().setAci(aci);
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceStateBuilder
|
||||
import org.webrtc.PeerConnection;
|
||||
import org.webrtc.VideoTrack;
|
||||
import org.whispersystems.signalservice.api.messages.calls.OfferMessage;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -91,7 +92,7 @@ public class GroupActionProcessor extends DeviceAwareActionProcessor {
|
||||
seen.add(Recipient.self());
|
||||
|
||||
for (GroupCall.RemoteDeviceState device : remoteDeviceStates) {
|
||||
Recipient recipient = Recipient.externalPush(ServiceId.from(device.getUserId()));
|
||||
Recipient recipient = Recipient.externalPush(ACI.from(device.getUserId()));
|
||||
CallParticipantId callParticipantId = new CallParticipantId(device.getDemuxId(), recipient.getId());
|
||||
CallParticipant callParticipant = participants.get(callParticipantId);
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ package org.thoughtcrime.securesms.service.webrtc
|
||||
import org.signal.ringrtc.CallManager
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import java.util.UUID
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
|
||||
data class GroupCallRingCheckInfo(
|
||||
val recipientId: RecipientId,
|
||||
val groupId: GroupId.V2,
|
||||
val ringId: Long,
|
||||
val ringerUuid: UUID,
|
||||
val ringerAci: ACI,
|
||||
val ringUpdate: CallManager.RingUpdate
|
||||
)
|
||||
|
||||
@@ -158,8 +158,8 @@ public class GroupConnectedActionProcessor extends GroupActionProcessor {
|
||||
webRtcInteractor.sendGroupCallMessage(currentState.getCallInfoState().getCallRecipient(), eraId, remoteUserRangTheCall, true);
|
||||
|
||||
List<UUID> members = new ArrayList<>(peekInfo.getJoinedMembers());
|
||||
if (!members.contains(SignalStore.account().requireAci().uuid())) {
|
||||
members.add(SignalStore.account().requireAci().uuid());
|
||||
if (!members.contains(SignalStore.account().requireAci().getRawUuid())) {
|
||||
members.add(SignalStore.account().requireAci().getRawUuid());
|
||||
}
|
||||
webRtcInteractor.updateGroupCallUpdateMessage(currentState.getCallInfoState().getCallRecipient().getId(), eraId, members, WebRtcUtil.isCallFull(peekInfo));
|
||||
|
||||
@@ -184,7 +184,7 @@ public class GroupConnectedActionProcessor extends GroupActionProcessor {
|
||||
String eraId = WebRtcUtil.getGroupCallEraId(groupCall);
|
||||
webRtcInteractor.sendGroupCallMessage(currentState.getCallInfoState().getCallRecipient(), eraId, false, false);
|
||||
|
||||
List<UUID> members = Stream.of(currentState.getCallInfoState().getRemoteCallParticipants()).map(p -> p.getRecipient().requireServiceId().uuid()).toList();
|
||||
List<UUID> members = Stream.of(currentState.getCallInfoState().getRemoteCallParticipants()).map(p -> p.getRecipient().requireServiceId().getRawUuid()).toList();
|
||||
webRtcInteractor.updateGroupCallUpdateMessage(currentState.getCallInfoState().getCallRecipient().getId(), eraId, members, false);
|
||||
|
||||
currentState = currentState.builder()
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState;
|
||||
import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceStateBuilder;
|
||||
import org.thoughtcrime.securesms.util.NetworkUtil;
|
||||
import org.whispersystems.signalservice.api.messages.calls.OfferMessage;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.util.List;
|
||||
@@ -120,7 +121,7 @@ public class GroupPreJoinActionProcessor extends GroupActionProcessor {
|
||||
}
|
||||
|
||||
List<Recipient> callParticipants = Stream.of(peekInfo.getJoinedMembers())
|
||||
.map(uuid -> Recipient.externalPush(ServiceId.from(uuid)))
|
||||
.map(uuid -> Recipient.externalPush(ACI.from(uuid)))
|
||||
.toList();
|
||||
|
||||
WebRtcServiceStateBuilder.CallInfoStateBuilder builder = currentState.builder()
|
||||
|
||||
@@ -17,8 +17,7 @@ import org.thoughtcrime.securesms.ringrtc.RemotePeer;
|
||||
import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.whispersystems.signalservice.api.messages.calls.OfferMessage;
|
||||
|
||||
import java.util.UUID;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
|
||||
/**
|
||||
* Action handler for when the system is at rest. Mainly responsible
|
||||
@@ -97,7 +96,7 @@ public class IdleActionProcessor extends WebRtcActionProcessor {
|
||||
@NonNull RemotePeer remotePeerGroup,
|
||||
@NonNull GroupId.V2 groupId,
|
||||
long ringId,
|
||||
@NonNull UUID sender,
|
||||
@NonNull ACI sender,
|
||||
@NonNull CallManager.RingUpdate ringUpdate)
|
||||
{
|
||||
Log.i(TAG, "handleGroupCallRingUpdate(): recipient: " + remotePeerGroup.getId() + " ring: " + ringId + " update: " + ringUpdate);
|
||||
@@ -154,11 +153,11 @@ public class IdleActionProcessor extends WebRtcActionProcessor {
|
||||
|
||||
if (peekInfo.getDeviceCount() == 0) {
|
||||
Log.i(TAG, "No one in the group call, mark as expired and do not ring");
|
||||
SignalDatabase.calls().insertOrUpdateGroupCallFromRingState(info.getRingId(), info.getRecipientId(), info.getRingerUuid(), System.currentTimeMillis(), CallManager.RingUpdate.EXPIRED_REQUEST);
|
||||
SignalDatabase.calls().insertOrUpdateGroupCallFromRingState(info.getRingId(), info.getRecipientId(), info.getRingerAci(), System.currentTimeMillis(), CallManager.RingUpdate.EXPIRED_REQUEST);
|
||||
return currentState;
|
||||
} else if (peekInfo.getJoinedMembers().contains(Recipient.self().requireServiceId().uuid())) {
|
||||
} else if (peekInfo.getJoinedMembers().contains(Recipient.self().requireServiceId().getRawUuid())) {
|
||||
Log.i(TAG, "We are already in the call, mark accepted on another device and do not ring");
|
||||
SignalDatabase.calls().insertOrUpdateGroupCallFromRingState(info.getRingId(), info.getRecipientId(), info.getRingerUuid(), System.currentTimeMillis(), CallManager.RingUpdate.ACCEPTED_ON_ANOTHER_DEVICE);
|
||||
SignalDatabase.calls().insertOrUpdateGroupCallFromRingState(info.getRingId(), info.getRecipientId(), info.getRingerAci(), System.currentTimeMillis(), CallManager.RingUpdate.ACCEPTED_ON_ANOTHER_DEVICE);
|
||||
return currentState;
|
||||
}
|
||||
|
||||
@@ -166,6 +165,6 @@ public class IdleActionProcessor extends WebRtcActionProcessor {
|
||||
.actionProcessor(new IncomingGroupCallActionProcessor(webRtcInteractor))
|
||||
.build();
|
||||
|
||||
return currentState.getActionProcessor().handleGroupCallRingUpdate(currentState, new RemotePeer(info.getRecipientId()), info.getGroupId(), info.getRingId(), info.getRingerUuid(), info.getRingUpdate());
|
||||
return currentState.getActionProcessor().handleGroupCallRingUpdate(currentState, new RemotePeer(info.getRecipientId()), info.getGroupId(), info.getRingId(), info.getRingerAci(), info.getRingUpdate());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.thoughtcrime.securesms.ringrtc.RemotePeer;
|
||||
import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState;
|
||||
import org.thoughtcrime.securesms.util.NetworkUtil;
|
||||
import org.thoughtcrime.securesms.webrtc.locks.LockManager;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -49,7 +50,7 @@ public final class IncomingGroupCallActionProcessor extends DeviceAwareActionPro
|
||||
@NonNull RemotePeer remotePeerGroup,
|
||||
@NonNull GroupId.V2 groupId,
|
||||
long ringId,
|
||||
@NonNull UUID sender,
|
||||
@NonNull ACI sender,
|
||||
@NonNull CallManager.RingUpdate ringUpdate)
|
||||
{
|
||||
Log.i(TAG, "handleGroupCallRingUpdate(): recipient: " + remotePeerGroup.getId() + " ring: " + Long.toHexString(ringId) + " update: " + ringUpdate);
|
||||
@@ -108,7 +109,7 @@ public final class IncomingGroupCallActionProcessor extends DeviceAwareActionPro
|
||||
|
||||
Log.i(TAG, "Requesting new ring: " + Long.toHexString(ringId));
|
||||
|
||||
Recipient ringerRecipient = Recipient.externalPush(ServiceId.from(sender));
|
||||
Recipient ringerRecipient = Recipient.externalPush(sender);
|
||||
SignalDatabase.calls().insertOrUpdateGroupCallFromRingState(
|
||||
ringId,
|
||||
remotePeerGroup.getId(),
|
||||
|
||||
@@ -80,7 +80,7 @@ import org.whispersystems.signalservice.api.messages.calls.OpaqueMessage;
|
||||
import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage;
|
||||
import org.whispersystems.signalservice.api.messages.calls.TurnServerInfo;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage;
|
||||
|
||||
@@ -191,7 +191,7 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
|
||||
serviceExecutor.execute(() -> {
|
||||
if (needsToSetSelfUuid) {
|
||||
try {
|
||||
callManager.setSelfUuid(SignalStore.account().requireAci().uuid());
|
||||
callManager.setSelfUuid(SignalStore.account().requireAci().getRawUuid());
|
||||
needsToSetSelfUuid = false;
|
||||
} catch (CallException e) {
|
||||
Log.w(TAG, "Unable to set self UUID on CallManager", e);
|
||||
@@ -724,14 +724,14 @@ private void processStateless(@NonNull Function1<WebRtcEphemeralState, WebRtcEph
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendCallMessage(@NonNull UUID uuid, @NonNull byte[] bytes, @NonNull CallManager.CallMessageUrgency urgency) {
|
||||
public void onSendCallMessage(@NonNull UUID aciUuid, @NonNull byte[] bytes, @NonNull CallManager.CallMessageUrgency urgency) {
|
||||
Log.i(TAG, "onSendCallMessage():");
|
||||
|
||||
OpaqueMessage opaqueMessage = new OpaqueMessage(bytes, getUrgencyFromCallUrgency(urgency));
|
||||
SignalServiceCallMessage callMessage = SignalServiceCallMessage.forOpaque(opaqueMessage, true, null);
|
||||
|
||||
networkExecutor.execute(() -> {
|
||||
Recipient recipient = Recipient.resolved(RecipientId.from(ServiceId.from(uuid)));
|
||||
Recipient recipient = Recipient.resolved(RecipientId.from(ACI.from(aciUuid)));
|
||||
if (recipient.isBlocked()) {
|
||||
return;
|
||||
}
|
||||
@@ -826,16 +826,17 @@ private void processStateless(@NonNull Function1<WebRtcEphemeralState, WebRtcEph
|
||||
@Override
|
||||
public void onGroupCallRingUpdate(@NonNull byte[] groupIdBytes, long ringId, @NonNull UUID sender, @NonNull CallManager.RingUpdate ringUpdate) {
|
||||
try {
|
||||
ACI senderAci = ACI.from(sender);
|
||||
GroupId.V2 groupId = GroupId.v2(new GroupIdentifier(groupIdBytes));
|
||||
GroupRecord group = SignalDatabase.groups().getGroup(groupId).orElse(null);
|
||||
Recipient senderRecipient = Recipient.externalPush(ServiceId.from(sender));
|
||||
Recipient senderRecipient = Recipient.externalPush(senderAci);
|
||||
|
||||
if (group != null &&
|
||||
group.isActive() &&
|
||||
!Recipient.resolved(group.getRecipientId()).isBlocked() &&
|
||||
(!group.isAnnouncementGroup() || group.isAdmin(senderRecipient)))
|
||||
{
|
||||
process((s, p) -> p.handleGroupCallRingUpdate(s, new RemotePeer(group.getRecipientId()), groupId, ringId, sender, ringUpdate));
|
||||
process((s, p) -> p.handleGroupCallRingUpdate(s, new RemotePeer(group.getRecipientId()), groupId, ringId, senderAci, ringUpdate));
|
||||
} else {
|
||||
Log.w(TAG, "Unable to ring unknown/inactive/blocked group.");
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ import org.whispersystems.signalservice.api.messages.calls.HangupMessage;
|
||||
import org.whispersystems.signalservice.api.messages.calls.IceUpdateMessage;
|
||||
import org.whispersystems.signalservice.api.messages.calls.OfferMessage;
|
||||
import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -789,7 +790,7 @@ public abstract class WebRtcActionProcessor {
|
||||
@NonNull RemotePeer remotePeerGroup,
|
||||
@NonNull GroupId.V2 groupId,
|
||||
long ringId,
|
||||
@NonNull UUID sender,
|
||||
@NonNull ACI sender,
|
||||
@NonNull RingUpdate ringUpdate)
|
||||
{
|
||||
Log.i(tag, "handleGroupCallRingUpdate(): recipient: " + remotePeerGroup.getId() + " ring: " + ringId + " update: " + ringUpdate);
|
||||
|
||||
@@ -45,7 +45,7 @@ class SignalCallLinkManager(
|
||||
linkRootKey: ByteArray,
|
||||
roomId: ByteArray
|
||||
): CreateCallLinkCredentialPresentation {
|
||||
val userUuid = Recipient.self().requireServiceId().uuid()
|
||||
val userUuid = Recipient.self().requireAci().rawUuid
|
||||
val requestContext = CreateCallLinkCredentialRequestContext.forRoom(roomId)
|
||||
val request = requestContext.request
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.push.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
|
||||
import org.whispersystems.signalservice.api.util.OptionalUtil;
|
||||
@@ -26,7 +26,6 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -81,9 +80,9 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||
continue;
|
||||
}
|
||||
|
||||
if (remoteRecord.getUnregisteredTimestamp() > 0 && remoteRecord.getServiceId() != null && !remoteRecord.getPni().isPresent() && !remoteRecord.getNumber().isPresent()) {
|
||||
if (remoteRecord.getUnregisteredTimestamp() > 0 && remoteRecord.getAci() != null && !remoteRecord.getPni().isPresent() && !remoteRecord.getNumber().isPresent()) {
|
||||
unregisteredAciOnly.add(remoteRecord);
|
||||
} else if (remoteRecord.getServiceId() != null && remoteRecord.getServiceId().equals(remoteRecord.getPni().orElse(null))) {
|
||||
} else if (remoteRecord.getAci() != null && remoteRecord.getAci().equals(remoteRecord.getPni().orElse(null))) {
|
||||
pniE164Only.add(remoteRecord);
|
||||
}
|
||||
}
|
||||
@@ -128,22 +127,19 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||
*/
|
||||
@Override
|
||||
boolean isInvalid(@NonNull SignalContactRecord remote) {
|
||||
if (remote.getServiceId() == null) {
|
||||
if (remote.getAci() == null) {
|
||||
Log.w(TAG, "No address on the ContentRecord -- marking as invalid.");
|
||||
return true;
|
||||
} else if (remote.getServiceId().isUnknown()) {
|
||||
} else if (remote.getAci().isUnknown()) {
|
||||
Log.w(TAG, "Found a ContactRecord without a UUID -- marking as invalid.");
|
||||
return true;
|
||||
} else if (remote.getServiceId().equals(selfAci) ||
|
||||
remote.getServiceId().equals(selfPni) ||
|
||||
} else if (remote.getAci().equals(selfAci) ||
|
||||
remote.getAci().equals(selfPni) ||
|
||||
(selfPni != null && selfPni.equals(remote.getPni().orElse(null))) ||
|
||||
(selfE164 != null && remote.getNumber().isPresent() && remote.getNumber().get().equals(selfE164)))
|
||||
{
|
||||
Log.w(TAG, "Found a ContactRecord for ourselves -- marking as invalid.");
|
||||
return true;
|
||||
} else if (!FeatureFlags.phoneNumberPrivacy() && remote.getServiceId().equals(remote.getPni().orElse(null))) {
|
||||
Log.w(TAG, "Found a PNI-only ContactRecord when PNP is disabled -- marking as invalid.");
|
||||
return true;
|
||||
} else if (remote.getNumber().isPresent() && !isValidE164(remote.getNumber().get())) {
|
||||
Log.w(TAG, "Found a record with an invalid E164. Marking as invalid.");
|
||||
return true;
|
||||
@@ -158,17 +154,13 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||
remote = remote.withoutPni();
|
||||
}
|
||||
|
||||
Optional<RecipientId> found = recipientTable.getByServiceId(remote.getServiceId());
|
||||
Optional<RecipientId> found = recipientTable.getByAci(remote.getAci());
|
||||
|
||||
if (!found.isPresent() && remote.getNumber().isPresent()) {
|
||||
if (found.isEmpty() && remote.getNumber().isPresent()) {
|
||||
found = recipientTable.getByE164(remote.getNumber().get());
|
||||
}
|
||||
|
||||
if (!found.isPresent() && remote.getPni().isPresent()) {
|
||||
found = recipientTable.getByServiceId(remote.getPni().get());
|
||||
}
|
||||
|
||||
if (!found.isPresent() && remote.getPni().isPresent()) {
|
||||
if (found.isEmpty() && remote.getPni().isPresent()) {
|
||||
found = recipientTable.getByPni(remote.getPni().get());
|
||||
}
|
||||
|
||||
@@ -219,8 +211,8 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||
}
|
||||
|
||||
if (identityKey != null && remote.getIdentityKey().isPresent() && !Arrays.equals(identityKey, remote.getIdentityKey().get())) {
|
||||
Log.w(TAG, "The local and remote identity keys do not match for " + local.getServiceId() + ". Enqueueing a profile fetch.");
|
||||
RetrieveProfileJob.enqueue(Recipient.trustedPush(local.getServiceId(), local.getPni().orElse(null), local.getNumber().orElse(null)).getId());
|
||||
Log.w(TAG, "The local and remote identity keys do not match for " + local.getAci() + ". Enqueueing a profile fetch.");
|
||||
RetrieveProfileJob.enqueue(Recipient.trustedPush(local.getAci(), local.getPni().orElse(null), local.getNumber().orElse(null)).getId());
|
||||
}
|
||||
|
||||
PNI pni;
|
||||
@@ -259,7 +251,7 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||
}
|
||||
|
||||
byte[] unknownFields = remote.serializeUnknownFields();
|
||||
ServiceId serviceId = local.getServiceId() == ServiceId.UNKNOWN ? remote.getServiceId() : local.getServiceId();
|
||||
ACI aci = local.getAci() == ACI.UNKNOWN ? remote.getAci() : local.getAci();
|
||||
byte[] profileKey = OptionalUtil.or(remote.getProfileKey(), local.getProfileKey()).orElse(null);
|
||||
String username = OptionalUtil.or(remote.getUsername(), local.getUsername()).orElse("");
|
||||
boolean blocked = remote.isBlocked();
|
||||
@@ -273,15 +265,15 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||
String systemGivenName = SignalStore.account().isPrimaryDevice() ? local.getSystemGivenName().orElse("") : remote.getSystemGivenName().orElse("");
|
||||
String systemFamilyName = SignalStore.account().isPrimaryDevice() ? local.getSystemFamilyName().orElse("") : remote.getSystemFamilyName().orElse("");
|
||||
String systemNickname = remote.getSystemNickname().orElse("");
|
||||
boolean matchesRemote = doParamsMatch(remote, unknownFields, serviceId, pni, e164, profileGivenName, profileFamilyName, systemGivenName, systemFamilyName, systemNickname, profileKey, username, identityState, identityKey, blocked, profileSharing, archived, forcedUnread, muteUntil, hideStory, unregisteredTimestamp, hidden);
|
||||
boolean matchesLocal = doParamsMatch(local, unknownFields, serviceId, pni, e164, profileGivenName, profileFamilyName, systemGivenName, systemFamilyName, systemNickname, profileKey, username, identityState, identityKey, blocked, profileSharing, archived, forcedUnread, muteUntil, hideStory, unregisteredTimestamp, hidden);
|
||||
boolean matchesRemote = doParamsMatch(remote, unknownFields, aci, pni, e164, profileGivenName, profileFamilyName, systemGivenName, systemFamilyName, systemNickname, profileKey, username, identityState, identityKey, blocked, profileSharing, archived, forcedUnread, muteUntil, hideStory, unregisteredTimestamp, hidden);
|
||||
boolean matchesLocal = doParamsMatch(local, unknownFields, aci, pni, e164, profileGivenName, profileFamilyName, systemGivenName, systemFamilyName, systemNickname, profileKey, username, identityState, identityKey, blocked, profileSharing, archived, forcedUnread, muteUntil, hideStory, unregisteredTimestamp, hidden);
|
||||
|
||||
if (matchesRemote) {
|
||||
return remote;
|
||||
} else if (matchesLocal) {
|
||||
return local;
|
||||
} else {
|
||||
return new SignalContactRecord.Builder(keyGenerator.generate(), serviceId, unknownFields)
|
||||
return new SignalContactRecord.Builder(keyGenerator.generate(), aci, unknownFields)
|
||||
.setE164(e164)
|
||||
.setPni(pni)
|
||||
.setProfileGivenName(profileGivenName)
|
||||
@@ -317,7 +309,7 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||
|
||||
@Override
|
||||
public int compare(@NonNull SignalContactRecord lhs, @NonNull SignalContactRecord rhs) {
|
||||
if (Objects.equals(lhs.getServiceId(), rhs.getServiceId()) ||
|
||||
if (Objects.equals(lhs.getAci(), rhs.getAci()) ||
|
||||
(lhs.getNumber().isPresent() && Objects.equals(lhs.getNumber(), rhs.getNumber())) ||
|
||||
(lhs.getPni().isPresent() && Objects.equals(lhs.getPni(), rhs.getPni())))
|
||||
{
|
||||
@@ -355,7 +347,7 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||
boolean hidden)
|
||||
{
|
||||
return Arrays.equals(contact.serializeUnknownFields(), unknownFields) &&
|
||||
Objects.equals(contact.getServiceId(), serviceId) &&
|
||||
Objects.equals(contact.getAci(), serviceId) &&
|
||||
Objects.equals(contact.getPni().orElse(null), pni) &&
|
||||
Objects.equals(contact.getNumber().orElse(null), e164) &&
|
||||
Objects.equals(contact.getProfileGivenName().orElse(""), profileGivenName) &&
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.subscription.Subscriber;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
|
||||
@@ -93,7 +94,7 @@ public final class StorageSyncModels {
|
||||
|
||||
private static @NonNull SignalAccountRecord.PinnedConversation localToRemotePinnedConversation(@NonNull RecipientRecord settings) {
|
||||
switch (settings.getGroupType()) {
|
||||
case NONE : return SignalAccountRecord.PinnedConversation.forContact(new SignalServiceAddress(settings.getServiceId(), settings.getE164()));
|
||||
case NONE : return SignalAccountRecord.PinnedConversation.forContact(new SignalServiceAddress(settings.getAci(), settings.getE164()));
|
||||
case SIGNAL_V1: return SignalAccountRecord.PinnedConversation.forGroupV1(settings.getGroupId().requireV1().getDecodedId());
|
||||
case SIGNAL_V2: return SignalAccountRecord.PinnedConversation.forGroupV2(settings.getSyncExtras().getGroupMasterKey().serialize());
|
||||
default : throw new AssertionError("Unexpected group type!");
|
||||
@@ -101,14 +102,14 @@ public final class StorageSyncModels {
|
||||
}
|
||||
|
||||
private static @NonNull SignalContactRecord localToRemoteContact(@NonNull RecipientRecord recipient, byte[] rawStorageId) {
|
||||
if (recipient.getServiceId() == null && recipient.getE164() == null) {
|
||||
if (recipient.getAci() == null && recipient.getE164() == null) {
|
||||
throw new AssertionError("Must have either a UUID or a phone number!");
|
||||
}
|
||||
|
||||
ServiceId serviceId = recipient.getServiceId() != null ? recipient.getServiceId() : ServiceId.UNKNOWN;
|
||||
ACI aci = recipient.getAci() != null ? recipient.getAci() : ACI.UNKNOWN;
|
||||
boolean hideStory = recipient.getExtras() != null && recipient.getExtras().hideStory();
|
||||
|
||||
return new SignalContactRecord.Builder(rawStorageId, serviceId, recipient.getSyncExtras().getStorageProto())
|
||||
return new SignalContactRecord.Builder(rawStorageId, aci, recipient.getSyncExtras().getStorageProto())
|
||||
.setE164(recipient.getE164())
|
||||
.setPni(recipient.getPni())
|
||||
.setProfileKey(recipient.getProfileKey())
|
||||
|
||||
@@ -164,7 +164,7 @@ public final class StorageSyncValidations {
|
||||
if (insert.getContact().isPresent()) {
|
||||
SignalContactRecord contact = insert.getContact().get();
|
||||
|
||||
if (self.requireServiceId().equals(contact.getServiceId()) ||
|
||||
if (self.requireAci().equals(contact.getAci()) ||
|
||||
self.requirePni().equals(contact.getPni().orElse(null)) ||
|
||||
self.requireE164().equals(contact.getNumber().orElse("")))
|
||||
{
|
||||
|
||||
@@ -8,15 +8,11 @@ import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.mms.PushMediaConstraints;
|
||||
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Provide access to locale specific values within feature flags following the locale CSV-Colon format.
|
||||
@@ -85,7 +81,7 @@ public final class LocaleFeatureFlags {
|
||||
}
|
||||
|
||||
long countEnabled = getCountryValue(countryCodeValues, self.getE164().orElse(""), 0);
|
||||
long currentUserBucket = BucketingUtil.bucket(flag, self.requireServiceId().uuid(), 1_000_000);
|
||||
long currentUserBucket = BucketingUtil.bucket(flag, self.requireAci().getRawUuid(), 1_000_000);
|
||||
|
||||
return countEnabled > currentUserBucket;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.util.Base64UrlSafe;
|
||||
|
||||
|
||||
@@ -63,9 +63,9 @@ class VerifySafetyNumberViewModel(
|
||||
e164Fingerprint = SafetyNumberFingerprint(version, localIdentifier, localIdentity, remoteIdentifier, remoteIdentity, generator.createFor(version, localIdentifier, localIdentity, remoteIdentifier, remoteIdentity))
|
||||
}
|
||||
|
||||
if (resolved.serviceId.isPresent) {
|
||||
if (resolved.aci.isPresent) {
|
||||
val localIdentifier = SignalStore.account().requireAci().toByteArray()
|
||||
val remoteIdentifier = resolved.requireServiceId().toByteArray()
|
||||
val remoteIdentifier = resolved.requireAci().toByteArray()
|
||||
val version = 2
|
||||
aciFingerprint = SafetyNumberFingerprint(version, localIdentifier, localIdentity, remoteIdentifier, remoteIdentity, generator.createFor(version, localIdentifier, localIdentity, remoteIdentifier, remoteIdentity))
|
||||
}
|
||||
@@ -97,13 +97,13 @@ class VerifySafetyNumberViewModel(
|
||||
val context: Context = ApplicationDependencies.getApplication()
|
||||
|
||||
SignalExecutors.BOUNDED.execute {
|
||||
ReentrantSessionLock.INSTANCE.acquire().use { unused ->
|
||||
ReentrantSessionLock.INSTANCE.acquire().use { _ ->
|
||||
if (verified) {
|
||||
Log.i(TAG, "Saving identity: $recipientId")
|
||||
ApplicationDependencies.getProtocolStore().aci().identities()
|
||||
.saveIdentityWithoutSideEffects(
|
||||
recipientId,
|
||||
recipient.resolve().requireServiceId(),
|
||||
recipient.resolve().requireAci(),
|
||||
remoteIdentity,
|
||||
IdentityTable.VerifiedStatus.VERIFIED,
|
||||
false,
|
||||
|
||||
Reference in New Issue
Block a user