mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-27 04:04:43 +01:00
Strongly type UUIDs as ACIs.
This commit is contained in:
@@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor;
|
||||
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
import org.thoughtcrime.securesms.groups.GroupAccessControl;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
@@ -804,10 +805,10 @@ private static final String[] GROUP_PROJECTION = {
|
||||
}
|
||||
|
||||
private static boolean gv2GroupActive(@NonNull DecryptedGroup decryptedGroup) {
|
||||
UUID uuid = Recipient.self().getUuid().get();
|
||||
ACI aci = Recipient.self().requireAci();
|
||||
|
||||
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), uuid).isPresent() ||
|
||||
DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), uuid).isPresent();
|
||||
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), aci.uuid()).isPresent() ||
|
||||
DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), aci.uuid()).isPresent();
|
||||
}
|
||||
|
||||
private List<RecipientId> getCurrentMembers(@NonNull GroupId groupId) {
|
||||
@@ -868,7 +869,7 @@ private static final String[] GROUP_PROJECTION = {
|
||||
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
|
||||
Log.w(TAG, "Seen unknown UUID in members list");
|
||||
} else {
|
||||
groupMembers.add(RecipientId.from(uuid, null));
|
||||
groupMembers.add(RecipientId.from(ACI.from(uuid), null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1186,9 +1187,9 @@ private static final String[] GROUP_PROJECTION = {
|
||||
*/
|
||||
public boolean isPendingMember(@NonNull Recipient recipient) {
|
||||
if (isV2Group()) {
|
||||
Optional<UUID> uuid = recipient.getUuid();
|
||||
if (uuid.isPresent()) {
|
||||
return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().getDecryptedGroup().getPendingMembersList(), uuid.get())
|
||||
Optional<ACI> aci = recipient.getAci();
|
||||
if (aci.isPresent()) {
|
||||
return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().getDecryptedGroup().getPendingMembersList(), aci.get().uuid())
|
||||
.isPresent();
|
||||
}
|
||||
}
|
||||
@@ -1229,13 +1230,13 @@ private static final String[] GROUP_PROJECTION = {
|
||||
}
|
||||
|
||||
public boolean isAdmin(@NonNull Recipient recipient) {
|
||||
Optional<UUID> uuid = recipient.getUuid();
|
||||
Optional<ACI> aci = recipient.getAci();
|
||||
|
||||
if (!uuid.isPresent()) {
|
||||
if (!aci.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return DecryptedGroupUtil.findMemberByUuid(getDecryptedGroup().getMembersList(), uuid.get())
|
||||
return DecryptedGroupUtil.findMemberByUuid(getDecryptedGroup().getMembersList(), aci.get().uuid())
|
||||
.transform(t -> t.getRole() == Member.Role.ADMINISTRATOR)
|
||||
.or(false);
|
||||
}
|
||||
@@ -1245,21 +1246,21 @@ private static final String[] GROUP_PROJECTION = {
|
||||
}
|
||||
|
||||
public MemberLevel memberLevel(@NonNull Recipient recipient) {
|
||||
Optional<UUID> uuid = recipient.getUuid();
|
||||
Optional<ACI> aci = recipient.getAci();
|
||||
|
||||
if (!uuid.isPresent()) {
|
||||
if (!aci.isPresent()) {
|
||||
return MemberLevel.NOT_A_MEMBER;
|
||||
}
|
||||
|
||||
DecryptedGroup decryptedGroup = getDecryptedGroup();
|
||||
|
||||
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), uuid.get())
|
||||
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), aci.get().uuid())
|
||||
.transform(member -> member.getRole() == Member.Role.ADMINISTRATOR
|
||||
? MemberLevel.ADMINISTRATOR
|
||||
: MemberLevel.FULL_MEMBER)
|
||||
.or(() -> DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), uuid.get())
|
||||
.or(() -> DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), aci.get().uuid())
|
||||
.transform(m -> MemberLevel.PENDING_MEMBER)
|
||||
.or(() -> DecryptedGroupUtil.findRequestingByUuid(decryptedGroup.getRequestingMembersList(), uuid.get())
|
||||
.or(() -> DecryptedGroupUtil.findRequestingByUuid(decryptedGroup.getRequestingMembersList(), aci.get().uuid())
|
||||
.transform(m -> MemberLevel.REQUESTING_MEMBER)
|
||||
.or(MemberLevel.NOT_A_MEMBER)));
|
||||
}
|
||||
@@ -1271,7 +1272,7 @@ private static final String[] GROUP_PROJECTION = {
|
||||
public List<RecipientId> getMemberRecipientIds(@NonNull MemberSet memberSet) {
|
||||
boolean includeSelf = memberSet.includeSelf;
|
||||
DecryptedGroup groupV2 = getDecryptedGroup();
|
||||
UUID selfUuid = Recipient.self().getUuid().get();
|
||||
UUID selfUuid = Recipient.self().requireAci().uuid();
|
||||
List<RecipientId> recipients = new ArrayList<>(groupV2.getMembersCount() + groupV2.getPendingMembersCount());
|
||||
int unknownMembers = 0;
|
||||
int unknownPending = 0;
|
||||
@@ -1280,7 +1281,7 @@ private static final String[] GROUP_PROJECTION = {
|
||||
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
|
||||
unknownMembers++;
|
||||
} else if (includeSelf || !selfUuid.equals(uuid)) {
|
||||
recipients.add(RecipientId.from(uuid, null));
|
||||
recipients.add(RecipientId.from(ACI.from(uuid), null));
|
||||
}
|
||||
}
|
||||
if (memberSet.includePending) {
|
||||
@@ -1288,7 +1289,7 @@ private static final String[] GROUP_PROJECTION = {
|
||||
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
|
||||
unknownPending++;
|
||||
} else if (includeSelf || !selfUuid.equals(uuid)) {
|
||||
recipients.add(RecipientId.from(uuid, null));
|
||||
recipients.add(RecipientId.from(ACI.from(uuid), null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -105,7 +106,7 @@ public final class MentionUtil {
|
||||
BodyRangeList.Builder builder = BodyRangeList.newBuilder();
|
||||
|
||||
for (Mention mention : mentions) {
|
||||
String uuid = Recipient.resolved(mention.getRecipientId()).requireUuid().toString();
|
||||
String uuid = Recipient.resolved(mention.getRecipientId()).requireAci().toString();
|
||||
builder.addRanges(BodyRangeList.BodyRange.newBuilder()
|
||||
.setMentionUuid(uuid)
|
||||
.setStart(mention.getStart())
|
||||
@@ -121,7 +122,7 @@ public final class MentionUtil {
|
||||
return Stream.of(BodyRangeList.parseFrom(data).getRangesList())
|
||||
.filter(bodyRange -> bodyRange.getAssociatedValueCase() == BodyRangeList.BodyRange.AssociatedValueCase.MENTIONUUID)
|
||||
.map(mention -> {
|
||||
RecipientId id = Recipient.externalPush(context, UuidUtil.parseOrThrow(mention.getMentionUuid()), null, false).getId();
|
||||
RecipientId id = Recipient.externalPush(context, ACI.parseOrThrow(mention.getMentionUuid()), null, false).getId();
|
||||
return new Mention(id, mention.getStart(), mention.getLength());
|
||||
})
|
||||
.toList();
|
||||
|
||||
@@ -81,6 +81,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.util.Pair;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
@@ -1559,7 +1560,7 @@ public class MmsDatabase extends MessageDatabase {
|
||||
MessageGroupContext.GroupV2Properties groupV2Properties = outgoingGroupUpdateMessage.requireGroupV2Properties();
|
||||
members.addAll(Stream.of(groupV2Properties.getAllActivePendingAndRemovedMembers())
|
||||
.distinct()
|
||||
.map(uuid -> RecipientId.from(uuid, null))
|
||||
.map(uuid -> RecipientId.from(ACI.from(uuid), null))
|
||||
.toList());
|
||||
members.remove(Recipient.self().getId());
|
||||
} else {
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
|
||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.thoughtcrime.securesms.database.model.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BadgeList;
|
||||
@@ -80,7 +81,6 @@ import org.whispersystems.signalservice.api.storage.SignalContactRecord;
|
||||
import org.whispersystems.signalservice.api.storage.SignalGroupV1Record;
|
||||
import org.whispersystems.signalservice.api.storage.SignalGroupV2Record;
|
||||
import org.whispersystems.signalservice.api.storage.StorageId;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
@@ -107,7 +107,7 @@ public class RecipientDatabase extends Database {
|
||||
|
||||
static final String TABLE_NAME = "recipient";
|
||||
public static final String ID = "_id";
|
||||
private static final String UUID = "uuid";
|
||||
private static final String ACI_COLUMN = "uuid";
|
||||
private static final String USERNAME = "username";
|
||||
public static final String PHONE = "phone";
|
||||
public static final String EMAIL = "email";
|
||||
@@ -178,7 +178,7 @@ public class RecipientDatabase extends Database {
|
||||
}
|
||||
|
||||
private static final String[] RECIPIENT_PROJECTION = new String[] {
|
||||
ID, UUID, USERNAME, PHONE, EMAIL, GROUP_ID, GROUP_TYPE,
|
||||
ID, ACI_COLUMN, USERNAME, PHONE, EMAIL, GROUP_ID, GROUP_TYPE,
|
||||
BLOCKED, MESSAGE_RINGTONE, CALL_RINGTONE, MESSAGE_VIBRATE, CALL_VIBRATE, MUTE_UNTIL, AVATAR_COLOR, SEEN_INVITE_REMINDER, DEFAULT_SUBSCRIPTION_ID, MESSAGE_EXPIRATION_TIME, REGISTERED,
|
||||
PROFILE_KEY, PROFILE_KEY_CREDENTIAL,
|
||||
SYSTEM_JOINED_NAME, SYSTEM_GIVEN_NAME, SYSTEM_FAMILY_NAME, SYSTEM_PHOTO_URI, SYSTEM_PHONE_LABEL, SYSTEM_PHONE_TYPE, SYSTEM_CONTACT_URI,
|
||||
@@ -329,7 +329,7 @@ public class RecipientDatabase extends Database {
|
||||
|
||||
public static final String CREATE_TABLE =
|
||||
"CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
UUID + " TEXT UNIQUE DEFAULT NULL, " +
|
||||
ACI_COLUMN + " TEXT UNIQUE DEFAULT NULL, " +
|
||||
USERNAME + " TEXT UNIQUE DEFAULT NULL, " +
|
||||
PHONE + " TEXT UNIQUE DEFAULT NULL, " +
|
||||
EMAIL + " TEXT UNIQUE DEFAULT NULL, " +
|
||||
@@ -398,7 +398,7 @@ public class RecipientDatabase extends Database {
|
||||
|
||||
public @NonNull boolean containsPhoneOrUuid(@NonNull String id) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
|
||||
String query = UUID + " = ? OR " + PHONE + " = ?";
|
||||
String query = ACI_COLUMN + " = ? OR " + PHONE + " = ?";
|
||||
String[] args = new String[]{id, id};
|
||||
|
||||
try (Cursor cursor = db.query(TABLE_NAME, new String[] { ID }, query, args, null, null, null)) {
|
||||
@@ -421,8 +421,8 @@ public class RecipientDatabase extends Database {
|
||||
}
|
||||
|
||||
public @NonNull
|
||||
Optional<RecipientId> getByUuid(@NonNull UUID uuid) {
|
||||
return getByColumn(UUID, uuid.toString());
|
||||
Optional<RecipientId> getByAci(@NonNull ACI uuid) {
|
||||
return getByColumn(ACI_COLUMN, uuid.toString());
|
||||
}
|
||||
|
||||
public @NonNull
|
||||
@@ -430,12 +430,12 @@ public class RecipientDatabase extends Database {
|
||||
return getByColumn(USERNAME, username);
|
||||
}
|
||||
|
||||
public @NonNull RecipientId getAndPossiblyMerge(@Nullable UUID uuid, @Nullable String e164, boolean highTrust) {
|
||||
return getAndPossiblyMerge(uuid, e164, highTrust, false);
|
||||
public @NonNull RecipientId getAndPossiblyMerge(@Nullable ACI aci, @Nullable String e164, boolean highTrust) {
|
||||
return getAndPossiblyMerge(aci, e164, highTrust, false);
|
||||
}
|
||||
|
||||
public @NonNull RecipientId getAndPossiblyMerge(@Nullable UUID uuid, @Nullable String e164, boolean highTrust, boolean changeSelf) {
|
||||
if (uuid == null && e164 == null) {
|
||||
public @NonNull RecipientId getAndPossiblyMerge(@Nullable ACI aci, @Nullable String e164, boolean highTrust, boolean changeSelf) {
|
||||
if (aci == null && e164 == null) {
|
||||
throw new IllegalArgumentException("Must provide a UUID or E164!");
|
||||
}
|
||||
|
||||
@@ -449,115 +449,115 @@ public class RecipientDatabase extends Database {
|
||||
|
||||
try {
|
||||
Optional<RecipientId> byE164 = e164 != null ? getByE164(e164) : Optional.absent();
|
||||
Optional<RecipientId> byUuid = uuid != null ? getByUuid(uuid) : Optional.absent();
|
||||
Optional<RecipientId> byAci = aci != null ? getByAci(aci) : Optional.absent();
|
||||
|
||||
RecipientId finalId;
|
||||
|
||||
if (!byE164.isPresent() && !byUuid.isPresent()) {
|
||||
if (!byE164.isPresent() && !byAci.isPresent()) {
|
||||
Log.i(TAG, "Discovered a completely new user. Inserting.", true);
|
||||
if (highTrust) {
|
||||
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(e164, uuid));
|
||||
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(e164, aci));
|
||||
finalId = RecipientId.from(id);
|
||||
} else {
|
||||
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(uuid == null ? e164 : null, uuid));
|
||||
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(aci == null ? e164 : null, aci));
|
||||
finalId = RecipientId.from(id);
|
||||
}
|
||||
} else if (byE164.isPresent() && !byUuid.isPresent()) {
|
||||
if (uuid != null) {
|
||||
} else if (byE164.isPresent() && !byAci.isPresent()) {
|
||||
if (aci != null) {
|
||||
RecipientSettings e164Settings = getRecipientSettings(byE164.get());
|
||||
if (e164Settings.uuid != null) {
|
||||
if (e164Settings.aci != null) {
|
||||
if (highTrust) {
|
||||
Log.w(TAG, String.format(Locale.US, "Found out about a UUID (%s) for a known E164 user (%s), but that user already has a UUID (%s). Likely a case of re-registration. High-trust, so stripping the E164 from the existing account and assigning it to a new entry.", uuid, byE164.get(), e164Settings.uuid), true);
|
||||
Log.w(TAG, String.format(Locale.US, "Found out about an ACI (%s) for a known E164 user (%s), but that user already has an ACI (%s). Likely a case of re-registration. High-trust, so stripping the E164 from the existing account and assigning it to a new entry.", aci, byE164.get(), e164Settings.aci), true);
|
||||
|
||||
removePhoneNumber(byE164.get(), db);
|
||||
recipientNeedingRefresh = byE164.get();
|
||||
|
||||
ContentValues insertValues = buildContentValuesForNewUser(e164, uuid);
|
||||
ContentValues insertValues = buildContentValuesForNewUser(e164, aci);
|
||||
insertValues.put(BLOCKED, e164Settings.blocked ? 1 : 0);
|
||||
|
||||
long id = db.insert(TABLE_NAME, null, insertValues);
|
||||
finalId = RecipientId.from(id);
|
||||
} else {
|
||||
Log.w(TAG, String.format(Locale.US, "Found out about a UUID (%s) for a known E164 user (%s), but that user already has a UUID (%s). Likely a case of re-registration. Low-trust, so making a new user for the UUID.", uuid, byE164.get(), e164Settings.uuid), true);
|
||||
Log.w(TAG, String.format(Locale.US, "Found out about an ACI (%s) for a known E164 user (%s), but that user already has an ACI (%s). Likely a case of re-registration. Low-trust, so making a new user for the UUID.", aci, byE164.get(), e164Settings.aci), true);
|
||||
|
||||
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(null, uuid));
|
||||
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(null, aci));
|
||||
finalId = RecipientId.from(id);
|
||||
}
|
||||
} else {
|
||||
if (highTrust) {
|
||||
Log.i(TAG, String.format(Locale.US, "Found out about a UUID (%s) for a known E164 user (%s). High-trust, so updating.", uuid, byE164.get()), true);
|
||||
markRegisteredOrThrow(byE164.get(), uuid);
|
||||
Log.i(TAG, String.format(Locale.US, "Found out about an ACI (%s) for a known E164 user (%s). High-trust, so updating.", aci, byE164.get()), true);
|
||||
markRegisteredOrThrow(byE164.get(), aci);
|
||||
finalId = byE164.get();
|
||||
} else {
|
||||
Log.i(TAG, String.format(Locale.US, "Found out about a UUID (%s) for a known E164 user (%s). Low-trust, so making a new user for the UUID.", uuid, byE164.get()), true);
|
||||
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(null, uuid));
|
||||
Log.i(TAG, String.format(Locale.US, "Found out about an ACI (%s) for a known E164 user (%s). Low-trust, so making a new user for the ACI.", aci, byE164.get()), true);
|
||||
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(null, aci));
|
||||
finalId = RecipientId.from(id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
finalId = byE164.get();
|
||||
}
|
||||
} else if (!byE164.isPresent() && byUuid.isPresent()) {
|
||||
} else if (!byE164.isPresent() && byAci.isPresent()) {
|
||||
if (e164 != null) {
|
||||
if (highTrust) {
|
||||
if (Objects.equals(uuid, TextSecurePreferences.getLocalUuid(context)) && !changeSelf) {
|
||||
Log.w(TAG, String.format(Locale.US, "Found out about an E164 (%s) for our own UUID user (%s). High-trust but not change self, doing nothing.", e164, byUuid.get()), true);
|
||||
finalId = byUuid.get();
|
||||
if (Objects.equals(aci, TextSecurePreferences.getLocalAci(context)) && !changeSelf) {
|
||||
Log.w(TAG, String.format(Locale.US, "Found out about an E164 (%s) for our own ACI user (%s). High-trust but not change self, doing nothing.", e164, byAci.get()), true);
|
||||
finalId = byAci.get();
|
||||
} else {
|
||||
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known UUID user (%s). High-trust, so updating.", e164, byUuid.get()), true);
|
||||
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known ACI user (%s). High-trust, so updating.", e164, byAci.get()), true);
|
||||
|
||||
RecipientSettings byUuidSettings = getRecipientSettings(byUuid.get());
|
||||
RecipientSettings byUuidSettings = getRecipientSettings(byAci.get());
|
||||
|
||||
setPhoneNumberOrThrow(byUuid.get(), e164);
|
||||
finalId = byUuid.get();
|
||||
setPhoneNumberOrThrow(byAci.get(), e164);
|
||||
finalId = byAci.get();
|
||||
|
||||
if (!Util.isEmpty(byUuidSettings.e164) && !byUuidSettings.e164.equals(e164)) {
|
||||
recipientChangedNumber = finalId;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known UUID user (%s). Low-trust, so doing nothing.", e164, byUuid.get()), true);
|
||||
finalId = byUuid.get();
|
||||
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known ACI user (%s). Low-trust, so doing nothing.", e164, byAci.get()), true);
|
||||
finalId = byAci.get();
|
||||
}
|
||||
} else {
|
||||
finalId = byUuid.get();
|
||||
finalId = byAci.get();
|
||||
}
|
||||
} else {
|
||||
if (byE164.equals(byUuid)) {
|
||||
finalId = byUuid.get();
|
||||
if (byE164.equals(byAci)) {
|
||||
finalId = byAci.get();
|
||||
} else {
|
||||
Log.w(TAG, String.format(Locale.US, "Hit a conflict between %s (E164 of %s) and %s (UUID %s). They map to different recipients.", byE164.get(), e164, byUuid.get(), uuid), new Throwable(), true);
|
||||
Log.w(TAG, String.format(Locale.US, "Hit a conflict between %s (E164 of %s) and %s (ACI %s). They map to different recipients.", byE164.get(), e164, byAci.get(), aci), new Throwable(), true);
|
||||
|
||||
RecipientSettings e164Settings = getRecipientSettings(byE164.get());
|
||||
|
||||
if (e164Settings.getUuid() != null) {
|
||||
if (e164Settings.getAci() != null) {
|
||||
if (highTrust) {
|
||||
Log.w(TAG, "The E164 contact has a different UUID. Likely a case of re-registration. High-trust, so stripping the E164 from the existing account and assigning it to the UUID entry.", true);
|
||||
Log.w(TAG, "The E164 contact has a different ACI. Likely a case of re-registration. High-trust, so stripping the E164 from the existing account and assigning it to the ACI entry.", true);
|
||||
|
||||
removePhoneNumber(byE164.get(), db);
|
||||
recipientNeedingRefresh = byE164.get();
|
||||
|
||||
RecipientSettings byUuidSettings = getRecipientSettings(byUuid.get());
|
||||
RecipientSettings byUuidSettings = getRecipientSettings(byAci.get());
|
||||
|
||||
setPhoneNumberOrThrow(byUuid.get(), Objects.requireNonNull(e164));
|
||||
finalId = byUuid.get();
|
||||
setPhoneNumberOrThrow(byAci.get(), Objects.requireNonNull(e164));
|
||||
finalId = byAci.get();
|
||||
|
||||
if (!Util.isEmpty(byUuidSettings.e164) && !byUuidSettings.e164.equals(e164)) {
|
||||
recipientChangedNumber = finalId;
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "The E164 contact has a different UUID. Likely a case of re-registration. Low-trust, so doing nothing.", true);
|
||||
finalId = byUuid.get();
|
||||
Log.w(TAG, "The E164 contact has a different ACI. Likely a case of re-registration. Low-trust, so doing nothing.", true);
|
||||
finalId = byAci.get();
|
||||
}
|
||||
} else {
|
||||
if (highTrust) {
|
||||
Log.w(TAG, "We have one contact with just an E164, and another with UUID. High-trust, so merging the two rows together.", true);
|
||||
finalId = merge(byUuid.get(), byE164.get());
|
||||
recipientNeedingRefresh = byUuid.get();
|
||||
remapped = new Pair<>(byE164.get(), byUuid.get());
|
||||
Log.w(TAG, "We have one contact with just an E164, and another with just an ACI. High-trust, so merging the two rows together.", true);
|
||||
finalId = merge(byAci.get(), byE164.get());
|
||||
recipientNeedingRefresh = byAci.get();
|
||||
remapped = new Pair<>(byE164.get(), byAci.get());
|
||||
} else {
|
||||
Log.w(TAG, "We have one contact with just an E164, and another with UUID. Low-trust, so doing nothing.", true);
|
||||
finalId = byUuid.get();
|
||||
Log.w(TAG, "We have one contact with just an E164, and another with just an ACI. Low-trust, so doing nothing.", true);
|
||||
finalId = byAci.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -592,13 +592,13 @@ public class RecipientDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
private static ContentValues buildContentValuesForNewUser(@Nullable String e164, @Nullable UUID uuid) {
|
||||
private static ContentValues buildContentValuesForNewUser(@Nullable String e164, @Nullable ACI aci) {
|
||||
ContentValues values = new ContentValues();
|
||||
|
||||
values.put(PHONE, e164);
|
||||
|
||||
if (uuid != null) {
|
||||
values.put(UUID, uuid.toString().toLowerCase());
|
||||
if (aci != null) {
|
||||
values.put(ACI_COLUMN, aci.toString().toLowerCase());
|
||||
values.put(REGISTERED, RegisteredState.REGISTERED.getId());
|
||||
values.put(STORAGE_SERVICE_ID, Base64.encodeBytes(StorageSyncHelper.generateKey()));
|
||||
values.put(AVATAR_COLOR, AvatarColor.random().serialize());
|
||||
@@ -608,8 +608,8 @@ public class RecipientDatabase extends Database {
|
||||
}
|
||||
|
||||
|
||||
public @NonNull RecipientId getOrInsertFromUuid(@NonNull UUID uuid) {
|
||||
return getOrInsertByColumn(UUID, uuid.toString()).recipientId;
|
||||
public @NonNull RecipientId getOrInsertFromAci(@NonNull ACI aci) {
|
||||
return getOrInsertByColumn(ACI_COLUMN, aci.toString()).recipientId;
|
||||
}
|
||||
|
||||
public @NonNull RecipientId getOrInsertFromE164(@NonNull String e164) {
|
||||
@@ -829,13 +829,13 @@ public class RecipientDatabase extends Database {
|
||||
|
||||
if (id < 0) {
|
||||
Log.w(TAG, "[applyStorageSyncContactInsert] Failed to insert. Possibly merging.");
|
||||
recipientId = getAndPossiblyMerge(insert.getAddress().hasValidUuid() ? insert.getAddress().getUuid() : null, insert.getAddress().getNumber().get(), true);
|
||||
recipientId = getAndPossiblyMerge(insert.getAddress().hasValidAci() ? insert.getAddress().getAci() : null, insert.getAddress().getNumber().get(), true);
|
||||
db.update(TABLE_NAME, values, ID_WHERE, SqlUtil.buildArgs(recipientId));
|
||||
} else {
|
||||
recipientId = RecipientId.from(id);
|
||||
}
|
||||
|
||||
if (insert.getIdentityKey().isPresent() && insert.getAddress().hasValidUuid()) {
|
||||
if (insert.getIdentityKey().isPresent() && insert.getAddress().hasValidAci()) {
|
||||
try {
|
||||
IdentityKey identityKey = new IdentityKey(insert.getIdentityKey().get(), 0);
|
||||
|
||||
@@ -864,7 +864,7 @@ public class RecipientDatabase extends Database {
|
||||
RecipientId recipientId = getByColumn(STORAGE_SERVICE_ID, Base64.encodeBytes(update.getOld().getId().getRaw())).get();
|
||||
Log.w(TAG, "[applyStorageSyncContactUpdate] Found user " + recipientId + ". Possibly merging.");
|
||||
|
||||
recipientId = getAndPossiblyMerge(update.getNew().getAddress().hasValidUuid() ? update.getNew().getAddress().getUuid() : null, update.getNew().getAddress().getNumber().orNull(), true);
|
||||
recipientId = getAndPossiblyMerge(update.getNew().getAddress().hasValidAci() ? update.getNew().getAddress().getAci() : null, update.getNew().getAddress().getNumber().orNull(), true);
|
||||
Log.w(TAG, "[applyStorageSyncContactUpdate] Merged into " + recipientId);
|
||||
|
||||
db.update(TABLE_NAME, values, ID_WHERE, SqlUtil.buildArgs(recipientId));
|
||||
@@ -881,7 +881,7 @@ public class RecipientDatabase extends Database {
|
||||
try {
|
||||
Optional<IdentityRecord> oldIdentityRecord = identityStore.getIdentityRecord(recipientId);
|
||||
|
||||
if (update.getNew().getIdentityKey().isPresent() && update.getNew().getAddress().hasValidUuid()) {
|
||||
if (update.getNew().getIdentityKey().isPresent() && update.getNew().getAddress().hasValidAci()) {
|
||||
IdentityKey identityKey = new IdentityKey(update.getNew().getIdentityKey().get(), 0);
|
||||
DatabaseFactory.getIdentityDatabase(context).updateIdentityAfterSync(update.getNew().getAddress().getIdentifier(), recipientId, identityKey, StorageSyncModels.remoteToLocalIdentityStatus(update.getNew().getIdentityState()));
|
||||
}
|
||||
@@ -1059,8 +1059,8 @@ public class RecipientDatabase extends Database {
|
||||
ProfileName profileName = ProfileName.fromParts(contact.getGivenName().orNull(), contact.getFamilyName().orNull());
|
||||
String username = contact.getUsername().orNull();
|
||||
|
||||
if (contact.getAddress().hasValidUuid()) {
|
||||
values.put(UUID, contact.getAddress().getUuid().toString());
|
||||
if (contact.getAddress().hasValidAci()) {
|
||||
values.put(ACI_COLUMN, contact.getAddress().getAci().toString());
|
||||
}
|
||||
|
||||
values.put(PHONE, contact.getAddress().getNumber().orNull());
|
||||
@@ -1133,9 +1133,9 @@ public class RecipientDatabase extends Database {
|
||||
|
||||
private List<RecipientSettings> getRecipientSettingsForSync(@Nullable String query, @Nullable String[] args) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
|
||||
String table = TABLE_NAME + " LEFT OUTER JOIN " + IdentityDatabase.TABLE_NAME + " ON " + TABLE_NAME + "." + UUID + " = " + IdentityDatabase.TABLE_NAME + "." + IdentityDatabase.ADDRESS
|
||||
+ " LEFT OUTER JOIN " + GroupDatabase.TABLE_NAME + " ON " + TABLE_NAME + "." + GROUP_ID + " = " + GroupDatabase.TABLE_NAME + "." + GroupDatabase.GROUP_ID
|
||||
+ " LEFT OUTER JOIN " + ThreadDatabase.TABLE_NAME + " ON " + TABLE_NAME + "." + ID + " = " + ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.RECIPIENT_ID;
|
||||
String table = TABLE_NAME + " LEFT OUTER JOIN " + IdentityDatabase.TABLE_NAME + " ON " + TABLE_NAME + "." + ACI_COLUMN + " = " + IdentityDatabase.TABLE_NAME + "." + IdentityDatabase.ADDRESS
|
||||
+ " LEFT OUTER JOIN " + GroupDatabase.TABLE_NAME + " ON " + TABLE_NAME + "." + GROUP_ID + " = " + GroupDatabase.TABLE_NAME + "." + GroupDatabase.GROUP_ID
|
||||
+ " LEFT OUTER JOIN " + ThreadDatabase.TABLE_NAME + " ON " + TABLE_NAME + "." + ID + " = " + ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.RECIPIENT_ID;
|
||||
List<RecipientSettings> out = new ArrayList<>();
|
||||
|
||||
String[] columns = Stream.of(TYPED_RECIPIENT_PROJECTION,
|
||||
@@ -1169,7 +1169,7 @@ public class RecipientDatabase extends Database {
|
||||
*/
|
||||
public @NonNull Map<RecipientId, StorageId> getContactStorageSyncIdsMap() {
|
||||
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
|
||||
String query = STORAGE_SERVICE_ID + " NOT NULL AND " + UUID + " NOT NULL AND " + ID + " != ? AND " + GROUP_TYPE + " != ?";
|
||||
String query = STORAGE_SERVICE_ID + " NOT NULL AND " + ACI_COLUMN + " NOT NULL AND " + ID + " != ? AND " + GROUP_TYPE + " != ?";
|
||||
String[] args = SqlUtil.buildArgs(Recipient.self().getId(), String.valueOf(GroupType.SIGNAL_V2.getId()));
|
||||
Map<RecipientId, StorageId> out = new HashMap<>();
|
||||
|
||||
@@ -1215,7 +1215,7 @@ public class RecipientDatabase extends Database {
|
||||
|
||||
static @NonNull RecipientSettings getRecipientSettings(@NonNull Context context, @NonNull Cursor cursor, @NonNull String idColumnName) {
|
||||
long id = CursorUtil.requireLong(cursor, idColumnName);
|
||||
UUID uuid = UuidUtil.parseOrNull(CursorUtil.requireString(cursor, UUID));
|
||||
ACI uuid = ACI.parseOrNull(CursorUtil.requireString(cursor, ACI_COLUMN));
|
||||
String username = CursorUtil.requireString(cursor, USERNAME);
|
||||
String e164 = CursorUtil.requireString(cursor, PHONE);
|
||||
String email = CursorUtil.requireString(cursor, EMAIL);
|
||||
@@ -1840,9 +1840,9 @@ public class RecipientDatabase extends Database {
|
||||
* database if missing.
|
||||
*/
|
||||
public Set<RecipientId> persistProfileKeySet(@NonNull ProfileKeySet profileKeySet) {
|
||||
Map<UUID, ProfileKey> profileKeys = profileKeySet.getProfileKeys();
|
||||
Map<UUID, ProfileKey> authoritativeProfileKeys = profileKeySet.getAuthoritativeProfileKeys();
|
||||
int totalKeys = profileKeys.size() + authoritativeProfileKeys.size();
|
||||
Map<ACI, ProfileKey> profileKeys = profileKeySet.getProfileKeys();
|
||||
Map<ACI, ProfileKey> authoritativeProfileKeys = profileKeySet.getAuthoritativeProfileKeys();
|
||||
int totalKeys = profileKeys.size() + authoritativeProfileKeys.size();
|
||||
|
||||
if (totalKeys == 0) {
|
||||
return Collections.emptySet();
|
||||
@@ -1853,8 +1853,8 @@ public class RecipientDatabase extends Database {
|
||||
HashSet<RecipientId> updated = new HashSet<>(totalKeys);
|
||||
RecipientId selfId = Recipient.self().getId();
|
||||
|
||||
for (Map.Entry<UUID, ProfileKey> entry : profileKeys.entrySet()) {
|
||||
RecipientId recipientId = getOrInsertFromUuid(entry.getKey());
|
||||
for (Map.Entry<ACI, ProfileKey> entry : profileKeys.entrySet()) {
|
||||
RecipientId recipientId = getOrInsertFromAci(entry.getKey());
|
||||
|
||||
if (setProfileKeyIfAbsent(recipientId, entry.getValue())) {
|
||||
Log.i(TAG, "Learned new profile key");
|
||||
@@ -1862,8 +1862,8 @@ public class RecipientDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<UUID, ProfileKey> entry : authoritativeProfileKeys.entrySet()) {
|
||||
RecipientId recipientId = getOrInsertFromUuid(entry.getKey());
|
||||
for (Map.Entry<ACI, ProfileKey> entry : authoritativeProfileKeys.entrySet()) {
|
||||
RecipientId recipientId = getOrInsertFromAci(entry.getKey());
|
||||
|
||||
if (selfId.equals(recipientId)) {
|
||||
Log.i(TAG, "Seen authoritative update for self");
|
||||
@@ -2111,7 +2111,7 @@ public class RecipientDatabase extends Database {
|
||||
Log.w(TAG, "[setPhoneNumber] Hit a conflict when trying to update " + id + ". Possibly merging.");
|
||||
|
||||
RecipientSettings existing = getRecipientSettings(id);
|
||||
RecipientId newId = getAndPossiblyMerge(existing.getUuid(), e164, true);
|
||||
RecipientId newId = getAndPossiblyMerge(existing.getAci(), e164, true);
|
||||
Log.w(TAG, "[setPhoneNumber] Resulting id: " + newId);
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
@@ -2147,7 +2147,7 @@ public class RecipientDatabase extends Database {
|
||||
|
||||
try {
|
||||
RecipientId id = Recipient.self().getId();
|
||||
RecipientId newId = getAndPossiblyMerge(Recipient.self().requireUuid(), e164, true, true);
|
||||
RecipientId newId = getAndPossiblyMerge(Recipient.self().requireAci(), e164, true, true);
|
||||
|
||||
if (id.equals(newId)) {
|
||||
Log.i(TAG, "[updateSelfPhone] Phone updated for self");
|
||||
@@ -2206,19 +2206,19 @@ public class RecipientDatabase extends Database {
|
||||
/**
|
||||
* @return True if setting the UUID resulted in changed recipientId, otherwise false.
|
||||
*/
|
||||
public boolean markRegistered(@NonNull RecipientId id, @NonNull UUID uuid) {
|
||||
public boolean markRegistered(@NonNull RecipientId id, @NonNull ACI aci) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
||||
try {
|
||||
markRegisteredOrThrow(id, uuid);
|
||||
markRegisteredOrThrow(id, aci);
|
||||
db.setTransactionSuccessful();
|
||||
return false;
|
||||
} catch (SQLiteConstraintException e) {
|
||||
Log.w(TAG, "[markRegistered] Hit a conflict when trying to update " + id + ". Possibly merging.");
|
||||
|
||||
RecipientSettings existing = getRecipientSettings(id);
|
||||
RecipientId newId = getAndPossiblyMerge(uuid, existing.getE164(), true);
|
||||
RecipientId newId = getAndPossiblyMerge(aci, existing.getE164(), true);
|
||||
Log.w(TAG, "[markRegistered] Merged into " + newId);
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
@@ -2231,10 +2231,10 @@ public class RecipientDatabase extends Database {
|
||||
/**
|
||||
* Should only use if you are confident that this shouldn't result in any contact merging.
|
||||
*/
|
||||
public void markRegisteredOrThrow(@NonNull RecipientId id, @NonNull UUID uuid) {
|
||||
public void markRegisteredOrThrow(@NonNull RecipientId id, @NonNull ACI aci) {
|
||||
ContentValues contentValues = new ContentValues(2);
|
||||
contentValues.put(REGISTERED, RegisteredState.REGISTERED.getId());
|
||||
contentValues.put(UUID, uuid.toString().toLowerCase());
|
||||
contentValues.put(ACI_COLUMN, aci.toString().toLowerCase());
|
||||
|
||||
if (update(id, contentValues)) {
|
||||
setStorageIdIfNotSet(id);
|
||||
@@ -2252,28 +2252,31 @@ public class RecipientDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
public void bulkUpdatedRegisteredStatus(@NonNull Map<RecipientId, String> registered, Collection<RecipientId> unregistered) {
|
||||
public void bulkUpdatedRegisteredStatus(@NonNull Map<RecipientId, ACI> registered, Collection<RecipientId> unregistered) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
||||
try {
|
||||
for (Map.Entry<RecipientId, String> entry : registered.entrySet()) {
|
||||
for (Map.Entry<RecipientId, ACI> entry : registered.entrySet()) {
|
||||
RecipientId recipientId = entry.getKey();
|
||||
ACI aci = entry.getValue();
|
||||
|
||||
ContentValues values = new ContentValues(2);
|
||||
values.put(REGISTERED, RegisteredState.REGISTERED.getId());
|
||||
|
||||
if (entry.getValue() != null) {
|
||||
values.put(UUID, entry.getValue().toLowerCase());
|
||||
if (aci != null) {
|
||||
values.put(ACI_COLUMN, aci.toString().toLowerCase());
|
||||
}
|
||||
|
||||
try {
|
||||
if (update(entry.getKey(), values)) {
|
||||
setStorageIdIfNotSet(entry.getKey());
|
||||
if (update(recipientId, values)) {
|
||||
setStorageIdIfNotSet(recipientId);
|
||||
}
|
||||
} catch (SQLiteConstraintException e) {
|
||||
Log.w(TAG, "[bulkUpdateRegisteredStatus] Hit a conflict when trying to update " + entry.getKey() + ". Possibly merging.");
|
||||
Log.w(TAG, "[bulkUpdateRegisteredStatus] Hit a conflict when trying to update " + recipientId + ". Possibly merging.");
|
||||
|
||||
RecipientSettings existing = getRecipientSettings(entry.getKey());
|
||||
RecipientId newId = getAndPossiblyMerge(UuidUtil.parseOrThrow(entry.getValue()), existing.getE164(), true);
|
||||
RecipientId newId = getAndPossiblyMerge(aci, existing.getE164(), true);
|
||||
Log.w(TAG, "[bulkUpdateRegisteredStatus] Merged into " + newId);
|
||||
}
|
||||
}
|
||||
@@ -2298,27 +2301,27 @@ public class RecipientDatabase extends Database {
|
||||
*
|
||||
* @return A mapping of (RecipientId, UUID)
|
||||
*/
|
||||
public @NonNull Map<RecipientId, String> bulkProcessCdsResult(@NonNull Map<String, UUID> mapping) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
HashMap<RecipientId, String> uuidMap = new HashMap<>();
|
||||
public @NonNull Map<RecipientId, ACI> bulkProcessCdsResult(@NonNull Map<String, ACI> mapping) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
HashMap<RecipientId, ACI> aciMap = new HashMap<>();
|
||||
|
||||
db.beginTransaction();
|
||||
try {
|
||||
for (Map.Entry<String, UUID> entry : mapping.entrySet()) {
|
||||
for (Map.Entry<String, ACI> entry : mapping.entrySet()) {
|
||||
String e164 = entry.getKey();
|
||||
UUID uuid = entry.getValue();
|
||||
Optional<RecipientId> uuidEntry = uuid != null ? getByUuid(uuid) : Optional.absent();
|
||||
ACI aci = entry.getValue();
|
||||
Optional<RecipientId> aciEntry = aci != null ? getByAci(aci) : Optional.absent();
|
||||
|
||||
if (uuidEntry.isPresent()) {
|
||||
boolean idChanged = setPhoneNumber(uuidEntry.get(), e164);
|
||||
if (aciEntry.isPresent()) {
|
||||
boolean idChanged = setPhoneNumber(aciEntry.get(), e164);
|
||||
if (idChanged) {
|
||||
uuidEntry = getByUuid(Objects.requireNonNull(uuid));
|
||||
aciEntry = getByAci(Objects.requireNonNull(aci));
|
||||
}
|
||||
}
|
||||
|
||||
RecipientId id = uuidEntry.isPresent() ? uuidEntry.get() : getOrInsertFromE164(e164);
|
||||
RecipientId id = aciEntry.isPresent() ? aciEntry.get() : getOrInsertFromE164(e164);
|
||||
|
||||
uuidMap.put(id, uuid != null ? uuid.toString() : null);
|
||||
aciMap.put(id, aci);
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
@@ -2326,7 +2329,7 @@ public class RecipientDatabase extends Database {
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
return uuidMap;
|
||||
return aciMap;
|
||||
}
|
||||
|
||||
public @NonNull List<RecipientId> getUninvitedRecipientsForInsights() {
|
||||
@@ -2730,7 +2733,7 @@ public class RecipientDatabase extends Database {
|
||||
.map(b -> b.getNumber().get())
|
||||
.toList();
|
||||
List<String> blockedUuid = Stream.of(blocked)
|
||||
.map(b -> b.getUuid().toString().toLowerCase())
|
||||
.map(b -> b.getAci().toString().toLowerCase())
|
||||
.toList();
|
||||
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
@@ -2750,7 +2753,7 @@ public class RecipientDatabase extends Database {
|
||||
}
|
||||
|
||||
for (String uuid : blockedUuid) {
|
||||
db.update(TABLE_NAME, setBlocked, UUID + " = ?", new String[] { uuid });
|
||||
db.update(TABLE_NAME, setBlocked, ACI_COLUMN + " = ?", new String[] { uuid });
|
||||
}
|
||||
|
||||
List<GroupId.V1> groupIdStrings = new ArrayList<>(groupIds.size());
|
||||
@@ -3106,7 +3109,7 @@ public class RecipientDatabase extends Database {
|
||||
SessionDatabase sessionDatabase = DatabaseFactory.getSessionDatabase(context);
|
||||
|
||||
boolean hasE164Session = sessionDatabase.getAllFor(e164Settings.e164).size() > 0;
|
||||
boolean hasUuidSession = sessionDatabase.getAllFor(uuidSettings.uuid.toString()).size() > 0;
|
||||
boolean hasUuidSession = sessionDatabase.getAllFor(uuidSettings.aci.toString()).size() > 0;
|
||||
|
||||
if (hasE164Session && hasUuidSession) {
|
||||
Log.w(TAG, "Had a session for both users. Deleting the E164.", true);
|
||||
@@ -3114,7 +3117,7 @@ public class RecipientDatabase extends Database {
|
||||
} else if (hasE164Session && !hasUuidSession) {
|
||||
Log.w(TAG, "Had a session for E164, but not UUID. Re-assigning to the UUID.", true);
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(SessionDatabase.ADDRESS, uuidSettings.uuid.toString());
|
||||
values.put(SessionDatabase.ADDRESS, uuidSettings.aci.toString());
|
||||
db.update(SessionDatabase.TABLE_NAME, values, SessionDatabase.ADDRESS + " = ?", SqlUtil.buildArgs(e164Settings.e164));
|
||||
} else if (!hasE164Session && hasUuidSession) {
|
||||
Log.w(TAG, "Had a session for UUID, but not E164. No action necessary.", true);
|
||||
@@ -3260,7 +3263,7 @@ public class RecipientDatabase extends Database {
|
||||
|
||||
public static class RecipientSettings {
|
||||
private final RecipientId id;
|
||||
private final UUID uuid;
|
||||
private final ACI aci;
|
||||
private final String username;
|
||||
private final String e164;
|
||||
private final String email;
|
||||
@@ -3310,7 +3313,7 @@ public class RecipientDatabase extends Database {
|
||||
private final List<Badge> badges;
|
||||
|
||||
RecipientSettings(@NonNull RecipientId id,
|
||||
@Nullable UUID uuid,
|
||||
@Nullable ACI uuid,
|
||||
@Nullable String username,
|
||||
@Nullable String e164,
|
||||
@Nullable String email,
|
||||
@@ -3355,7 +3358,7 @@ public class RecipientDatabase extends Database {
|
||||
@NonNull List<Badge> badges)
|
||||
{
|
||||
this.id = id;
|
||||
this.uuid = uuid;
|
||||
this.aci = uuid;
|
||||
this.username = username;
|
||||
this.e164 = e164;
|
||||
this.email = email;
|
||||
@@ -3409,8 +3412,8 @@ public class RecipientDatabase extends Database {
|
||||
return id;
|
||||
}
|
||||
|
||||
public @Nullable UUID getUuid() {
|
||||
return uuid;
|
||||
public @Nullable ACI getAci() {
|
||||
return aci;
|
||||
}
|
||||
|
||||
public @Nullable String getUsername() {
|
||||
|
||||
@@ -143,8 +143,8 @@ public class SenderKeySharedDatabase extends Database {
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
Recipient recipient = Recipient.resolved(recipientId);
|
||||
|
||||
if (recipient.hasUuid()) {
|
||||
db.delete(TABLE_NAME, ADDRESS + " = ?", SqlUtil.buildArgs(recipient.getUuid().get().toString()));
|
||||
if (recipient.hasAci()) {
|
||||
db.delete(TABLE_NAME, ADDRESS + " = ?", SqlUtil.buildArgs(recipient.requireAci().toString()));
|
||||
} else {
|
||||
Log.w(TAG, "Recipient doesn't have a UUID! " + recipientId);
|
||||
}
|
||||
|
||||
@@ -723,11 +723,11 @@ public class SmsDatabase extends MessageDatabase {
|
||||
|
||||
if (!peerEraIdSameAsPrevious && !Util.isEmpty(peekGroupCallEraId)) {
|
||||
Recipient self = Recipient.self();
|
||||
boolean markRead = peekJoinedUuids.contains(self.requireUuid()) || self.getId().equals(sender);
|
||||
boolean markRead = peekJoinedUuids.contains(self.requireAci().uuid()) || self.getId().equals(sender);
|
||||
|
||||
byte[] updateDetails = GroupCallUpdateDetails.newBuilder()
|
||||
.setEraId(Util.emptyIfNull(peekGroupCallEraId))
|
||||
.setStartedCallUuid(Recipient.resolved(sender).requireUuid().toString())
|
||||
.setStartedCallUuid(Recipient.resolved(sender).requireAci().toString())
|
||||
.setStartedCallTimestamp(timestamp)
|
||||
.addAllInCallUuids(Stream.of(peekJoinedUuids).map(UUID::toString).toList())
|
||||
.setIsCallFull(isCallFull)
|
||||
@@ -804,7 +804,7 @@ public class SmsDatabase extends MessageDatabase {
|
||||
if (!sameEraId && !Util.isEmpty(messageGroupCallEraId)) {
|
||||
byte[] updateDetails = GroupCallUpdateDetails.newBuilder()
|
||||
.setEraId(Util.emptyIfNull(messageGroupCallEraId))
|
||||
.setStartedCallUuid(Recipient.resolved(sender).requireUuid().toString())
|
||||
.setStartedCallUuid(Recipient.resolved(sender).requireAci().toString())
|
||||
.setStartedCallTimestamp(timestamp)
|
||||
.addAllInCallUuids(Collections.emptyList())
|
||||
.setIsCallFull(false)
|
||||
@@ -853,7 +853,7 @@ public class SmsDatabase extends MessageDatabase {
|
||||
}
|
||||
|
||||
GroupCallUpdateDetails groupCallUpdateDetails = GroupCallUpdateDetailsUtil.parse(record.getBody());
|
||||
boolean containsSelf = peekJoinedUuids.contains(Recipient.self().requireUuid());
|
||||
boolean containsSelf = peekJoinedUuids.contains(Recipient.self().requireAci().uuid());
|
||||
|
||||
sameEraId = groupCallUpdateDetails.getEraId().equals(peekGroupCallEraId) && !Util.isEmpty(peekGroupCallEraId);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ import org.thoughtcrime.securesms.util.SqlUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
|
||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
|
||||
import org.whispersystems.signalservice.api.storage.SignalGroupV1Record;
|
||||
@@ -1446,7 +1447,7 @@ public class ThreadDatabase extends Database {
|
||||
if (threadRecipient.isPushV2Group()) {
|
||||
MessageRecord.InviteAddState inviteAddState = record.getGv2AddInviteState();
|
||||
if (inviteAddState != null) {
|
||||
RecipientId from = RecipientId.from(inviteAddState.getAddedOrInvitedBy(), null);
|
||||
RecipientId from = RecipientId.from(ACI.from(inviteAddState.getAddedOrInvitedBy()), null);
|
||||
if (inviteAddState.isInvited()) {
|
||||
Log.i(TAG, "GV2 invite message request from " + from);
|
||||
return Extra.forGroupV2invite(from, individualRecipientId);
|
||||
|
||||
@@ -10,26 +10,25 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Create a group call update message based on time and joined members.
|
||||
*/
|
||||
public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFactory {
|
||||
private final Context context;
|
||||
private final List<UUID> joinedMembers;
|
||||
private final List<ACI> joinedMembers;
|
||||
private final boolean withTime;
|
||||
private final GroupCallUpdateDetails groupCallUpdateDetails;
|
||||
private final UUID selfUuid;
|
||||
private final ACI selfAci;
|
||||
|
||||
public GroupCallUpdateMessageFactory(@NonNull Context context,
|
||||
@NonNull List<UUID> joinedMembers,
|
||||
@NonNull List<ACI> joinedMembers,
|
||||
boolean withTime,
|
||||
@NonNull GroupCallUpdateDetails groupCallUpdateDetails)
|
||||
{
|
||||
@@ -37,11 +36,11 @@ public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFa
|
||||
this.joinedMembers = new ArrayList<>(joinedMembers);
|
||||
this.withTime = withTime;
|
||||
this.groupCallUpdateDetails = groupCallUpdateDetails;
|
||||
this.selfUuid = TextSecurePreferences.getLocalUuid(context);
|
||||
this.selfAci = TextSecurePreferences.getLocalAci(context);
|
||||
|
||||
boolean removed = this.joinedMembers.remove(selfUuid);
|
||||
boolean removed = this.joinedMembers.remove(selfAci);
|
||||
if (removed) {
|
||||
this.joinedMembers.add(selfUuid);
|
||||
this.joinedMembers.add(selfAci);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +56,7 @@ public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFa
|
||||
if (joinedMembers.get(0).toString().equals(groupCallUpdateDetails.getStartedCallUuid())) {
|
||||
return withTime ? context.getString(R.string.MessageRecord_s_started_a_group_call_s, describe(joinedMembers.get(0)), time)
|
||||
: context.getString(R.string.MessageRecord_s_started_a_group_call, describe(joinedMembers.get(0)));
|
||||
} else if (Objects.equals(joinedMembers.get(0), selfUuid)) {
|
||||
} else if (Objects.equals(joinedMembers.get(0), selfAci)) {
|
||||
return withTime ? context.getString(R.string.MessageRecord_you_are_in_the_group_call_s1, time)
|
||||
: context.getString(R.string.MessageRecord_you_are_in_the_group_call);
|
||||
} else {
|
||||
@@ -88,12 +87,12 @@ public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFa
|
||||
}
|
||||
}
|
||||
|
||||
private @NonNull String describe(@NonNull UUID uuid) {
|
||||
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
|
||||
private @NonNull String describe(@NonNull ACI aci) {
|
||||
if (aci.isUnknown()) {
|
||||
return context.getString(R.string.MessageRecord_unknown);
|
||||
}
|
||||
|
||||
Recipient recipient = Recipient.resolved(RecipientId.from(uuid, null));
|
||||
Recipient recipient = Recipient.resolved(RecipientId.from(aci, null));
|
||||
|
||||
if (recipient.isSelf()) {
|
||||
return context.getString(R.string.MessageRecord_you);
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.util.ExpirationUtil;
|
||||
import org.thoughtcrime.securesms.util.StringUtil;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -744,11 +745,12 @@ final class GroupsV2UpdateMessageProducer {
|
||||
interface DescribeMemberStrategy {
|
||||
|
||||
/**
|
||||
* Map a UUID to a string that describes the group member.
|
||||
* Map an ACI to a string that describes the group member.
|
||||
* @param aci
|
||||
*/
|
||||
@NonNull
|
||||
@WorkerThread
|
||||
String describe(@NonNull UUID uuid);
|
||||
String describe(@NonNull ACI aci);
|
||||
}
|
||||
|
||||
private interface StringFactory1Arg {
|
||||
@@ -769,9 +771,9 @@ final class GroupsV2UpdateMessageProducer {
|
||||
@NonNull StringFactory1Arg stringFactory,
|
||||
@DrawableRes int iconResource)
|
||||
{
|
||||
UUID uuid1 = UuidUtil.fromByteStringOrUnknown(uuid1Bytes);
|
||||
ACI aci1 = ACI.fromByteStringOrUnknown(uuid1Bytes);
|
||||
|
||||
return UpdateDescription.mentioning(Collections.singletonList(uuid1), () -> stringFactory.create(descriptionStrategy.describe(uuid1)), iconResource);
|
||||
return UpdateDescription.mentioning(Collections.singletonList(aci1), () -> stringFactory.create(descriptionStrategy.describe(aci1)), iconResource);
|
||||
}
|
||||
|
||||
private UpdateDescription updateDescription(@NonNull ByteString uuid1Bytes,
|
||||
@@ -779,9 +781,9 @@ final class GroupsV2UpdateMessageProducer {
|
||||
@NonNull StringFactory2Args stringFactory,
|
||||
@DrawableRes int iconResource)
|
||||
{
|
||||
UUID uuid1 = UuidUtil.fromByteStringOrUnknown(uuid1Bytes);
|
||||
UUID uuid2 = UuidUtil.fromByteStringOrUnknown(uuid2Bytes);
|
||||
ACI aci1 = ACI.fromByteStringOrUnknown(uuid1Bytes);
|
||||
ACI aci2 = ACI.fromByteStringOrUnknown(uuid2Bytes);
|
||||
|
||||
return UpdateDescription.mentioning(Arrays.asList(uuid1, uuid2), () -> stringFactory.create(descriptionStrategy.describe(uuid1), descriptionStrategy.describe(uuid2)), iconResource);
|
||||
return UpdateDescription.mentioning(Arrays.asList(aci1, aci2), () -> stringFactory.create(descriptionStrategy.describe(aci1), descriptionStrategy.describe(aci2)), iconResource);
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ import org.thoughtcrime.securesms.util.StringUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.util.guava.Function;
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -240,7 +241,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
|
||||
private static boolean selfCreatedGroup(@NonNull DecryptedGroupChange change) {
|
||||
return change.getRevision() == 0 &&
|
||||
change.getEditor().equals(UuidUtil.toByteString(Recipient.self().requireUuid()));
|
||||
change.getEditor().equals(UuidUtil.toByteString(Recipient.self().requireAci().uuid()));
|
||||
}
|
||||
|
||||
public static @NonNull UpdateDescription getGv2ChangeDescription(@NonNull Context context, @NonNull String body) {
|
||||
@@ -248,7 +249,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
ShortStringDescriptionStrategy descriptionStrategy = new ShortStringDescriptionStrategy(context);
|
||||
byte[] decoded = Base64.decode(body);
|
||||
DecryptedGroupV2Context decryptedGroupV2Context = DecryptedGroupV2Context.parseFrom(decoded);
|
||||
GroupsV2UpdateMessageProducer updateMessageProducer = new GroupsV2UpdateMessageProducer(context, descriptionStrategy, Recipient.self().getUuid().get());
|
||||
GroupsV2UpdateMessageProducer updateMessageProducer = new GroupsV2UpdateMessageProducer(context, descriptionStrategy, Recipient.self().requireAci().uuid());
|
||||
|
||||
if (decryptedGroupV2Context.hasChange() && (decryptedGroupV2Context.getGroupState().getRevision() != 0 || decryptedGroupV2Context.hasPreviousGroupState())) {
|
||||
return UpdateDescription.concatWithNewLines(updateMessageProducer.describeChanges(decryptedGroupV2Context.getPreviousGroupState(), decryptedGroupV2Context.getChange()));
|
||||
@@ -279,7 +280,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
}
|
||||
|
||||
DecryptedGroup groupState = decryptedGroupV2Context.getGroupState();
|
||||
boolean invited = DecryptedGroupUtil.findPendingByUuid(groupState.getPendingMembersList(), Recipient.self().requireUuid()).isPresent();
|
||||
boolean invited = DecryptedGroupUtil.findPendingByUuid(groupState.getPendingMembersList(), Recipient.self().requireAci().uuid()).isPresent();
|
||||
|
||||
if (decryptedGroupV2Context.hasChange()) {
|
||||
UUID changeEditor = UuidUtil.fromByteStringOrNull(decryptedGroupV2Context.getChange().getEditor());
|
||||
@@ -301,7 +302,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
@NonNull Function<Recipient, String> stringGenerator,
|
||||
@DrawableRes int iconResource)
|
||||
{
|
||||
return UpdateDescription.mentioning(Collections.singletonList(recipient.getUuid().or(UuidUtil.UNKNOWN_UUID)),
|
||||
return UpdateDescription.mentioning(Collections.singletonList(recipient.getAci().or(ACI.UNKNOWN)),
|
||||
() -> stringGenerator.apply(recipient.resolve()),
|
||||
iconResource);
|
||||
}
|
||||
@@ -369,10 +370,11 @@ 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<UUID> joinedMembers = Stream.of(groupCallUpdateDetails.getInCallUuidsList())
|
||||
.map(UuidUtil::parseOrNull)
|
||||
.withoutNulls()
|
||||
.toList();
|
||||
List<ACI> joinedMembers = Stream.of(groupCallUpdateDetails.getInCallUuidsList())
|
||||
.map(UuidUtil::parseOrNull)
|
||||
.withoutNulls()
|
||||
.map(ACI::from)
|
||||
.toList();
|
||||
|
||||
UpdateDescription.StringFactory stringFactory = new GroupCallUpdateMessageFactory(context, joinedMembers, withTime, groupCallUpdateDetails);
|
||||
|
||||
@@ -407,11 +409,11 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String describe(@NonNull UUID uuid) {
|
||||
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
|
||||
public @NonNull String describe(@NonNull ACI aci) {
|
||||
if (aci.isUnknown()) {
|
||||
return context.getString(R.string.MessageRecord_unknown);
|
||||
}
|
||||
return Recipient.resolved(RecipientId.from(uuid, null)).getDisplayName(context);
|
||||
return Recipient.resolved(RecipientId.from(aci, null)).getDisplayName(context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import org.signal.core.util.ThreadUtil;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -27,14 +28,14 @@ public final class UpdateDescription {
|
||||
String create();
|
||||
}
|
||||
|
||||
private final Collection<UUID> mentioned;
|
||||
private final StringFactory stringFactory;
|
||||
private final String staticString;
|
||||
private final int lightIconResource;
|
||||
private final int lightTint;
|
||||
private final int darkTint;
|
||||
private final Collection<ACI> mentioned;
|
||||
private final StringFactory stringFactory;
|
||||
private final String staticString;
|
||||
private final int lightIconResource;
|
||||
private final int lightTint;
|
||||
private final int darkTint;
|
||||
|
||||
private UpdateDescription(@NonNull Collection<UUID> mentioned,
|
||||
private UpdateDescription(@NonNull Collection<ACI> mentioned,
|
||||
@Nullable StringFactory stringFactory,
|
||||
@Nullable String staticString,
|
||||
@DrawableRes int iconResource,
|
||||
@@ -59,11 +60,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<UUID> mentioned,
|
||||
public static UpdateDescription mentioning(@NonNull Collection<ACI> mentioned,
|
||||
@NonNull StringFactory stringFactory,
|
||||
@DrawableRes int iconResource)
|
||||
{
|
||||
return new UpdateDescription(UuidUtil.filterKnown(mentioned),
|
||||
return new UpdateDescription(ACI.filterKnown(mentioned),
|
||||
stringFactory,
|
||||
null,
|
||||
iconResource,
|
||||
@@ -117,7 +118,7 @@ public final class UpdateDescription {
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
public Collection<UUID> getMentioned() {
|
||||
public Collection<ACI> getMentioned() {
|
||||
return mentioned;
|
||||
}
|
||||
|
||||
@@ -148,7 +149,7 @@ public final class UpdateDescription {
|
||||
);
|
||||
}
|
||||
|
||||
Set<UUID> allMentioned = new HashSet<>();
|
||||
Set<ACI> allMentioned = new HashSet<>();
|
||||
|
||||
for (UpdateDescription updateDescription : updateDescriptions) {
|
||||
allMentioned.addAll(updateDescription.getMentioned());
|
||||
|
||||
Reference in New Issue
Block a user