Move from ACI to a generic ServiceId.

This commit is contained in:
Greyson Parrelli
2022-02-17 15:55:54 -05:00
parent 9f1deda220
commit 7ca2420287
110 changed files with 841 additions and 824 deletions

View File

@@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.crypto.SenderKeyUtil;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor;
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.push.DistributionId;
import org.thoughtcrime.securesms.groups.GroupAccessControl;
@@ -40,6 +41,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
import org.whispersystems.signalservice.api.groupsv2.GroupChangeReconstruct;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.io.Closeable;
@@ -821,7 +823,7 @@ private static final String[] GROUP_PROJECTION = {
}
private static boolean gv2GroupActive(@NonNull DecryptedGroup decryptedGroup) {
ACI aci = Recipient.self().requireAci();
ACI aci = SignalStore.account().requireAci();
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), aci.uuid()).isPresent() ||
DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), aci.uuid()).isPresent();
@@ -1232,9 +1234,9 @@ private static final String[] GROUP_PROJECTION = {
*/
public boolean isPendingMember(@NonNull Recipient recipient) {
if (isV2Group()) {
Optional<ACI> aci = recipient.getAci();
if (aci.isPresent()) {
return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().getDecryptedGroup().getPendingMembersList(), aci.get().uuid())
Optional<ServiceId> serviceId = recipient.getServiceId();
if (serviceId.isPresent()) {
return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().getDecryptedGroup().getPendingMembersList(), serviceId.get().uuid())
.isPresent();
}
}
@@ -1275,13 +1277,13 @@ private static final String[] GROUP_PROJECTION = {
}
public boolean isAdmin(@NonNull Recipient recipient) {
Optional<ACI> aci = recipient.getAci();
Optional<ServiceId> serviceId = recipient.getServiceId();
if (!aci.isPresent()) {
if (!serviceId.isPresent()) {
return false;
}
return DecryptedGroupUtil.findMemberByUuid(getDecryptedGroup().getMembersList(), aci.get().uuid())
return DecryptedGroupUtil.findMemberByUuid(getDecryptedGroup().getMembersList(), serviceId.get().uuid())
.transform(t -> t.getRole() == Member.Role.ADMINISTRATOR)
.or(false);
}
@@ -1291,21 +1293,21 @@ private static final String[] GROUP_PROJECTION = {
}
public MemberLevel memberLevel(@NonNull Recipient recipient) {
Optional<ACI> aci = recipient.getAci();
Optional<ServiceId> serviceId = recipient.getServiceId();
if (!aci.isPresent()) {
if (!serviceId.isPresent()) {
return MemberLevel.NOT_A_MEMBER;
}
DecryptedGroup decryptedGroup = getDecryptedGroup();
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), aci.get().uuid())
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), serviceId.get().uuid())
.transform(member -> member.getRole() == Member.Role.ADMINISTRATOR
? MemberLevel.ADMINISTRATOR
: MemberLevel.FULL_MEMBER)
.or(() -> DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), aci.get().uuid())
.or(() -> DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), serviceId.get().uuid())
.transform(m -> MemberLevel.PENDING_MEMBER)
.or(() -> DecryptedGroupUtil.findRequestingByUuid(decryptedGroup.getRequestingMembersList(), aci.get().uuid())
.or(() -> DecryptedGroupUtil.findRequestingByUuid(decryptedGroup.getRequestingMembersList(), serviceId.get().uuid())
.transform(m -> MemberLevel.REQUESTING_MEMBER)
.or(MemberLevel.NOT_A_MEMBER)));
}
@@ -1317,7 +1319,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().requireAci().uuid();
UUID selfUuid = Recipient.self().requireServiceId().uuid();
List<RecipientId> recipients = new ArrayList<>(groupV2.getMembersCount() + groupV2.getPendingMembersCount());
int unknownMembers = 0;
int unknownPending = 0;

View File

@@ -19,7 +19,6 @@ 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;
import java.util.Collections;
@@ -106,7 +105,7 @@ public final class MentionUtil {
BodyRangeList.Builder builder = BodyRangeList.newBuilder();
for (Mention mention : mentions) {
String uuid = Recipient.resolved(mention.getRecipientId()).requireAci().toString();
String uuid = Recipient.resolved(mention.getRecipientId()).requireServiceId().toString();
builder.addRanges(BodyRangeList.BodyRange.newBuilder()
.setMentionUuid(uuid)
.setStart(mention.getStart())
@@ -122,7 +121,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, ACI.parseOrThrow(mention.getMentionUuid()), null, false).getId();
RecipientId id = Recipient.externalPush(ACI.parseOrThrow(mention.getMentionUuid()), null, false).getId();
return new Mention(id, mention.getStart(), mention.getLength());
})
.toList();

View File

@@ -9,7 +9,7 @@ import org.whispersystems.libsignal.InvalidKeyException
import org.whispersystems.libsignal.ecc.Curve
import org.whispersystems.libsignal.ecc.ECKeyPair
import org.whispersystems.libsignal.state.PreKeyRecord
import org.whispersystems.signalservice.api.push.AccountIdentifier
import org.whispersystems.signalservice.api.push.ServiceId
import java.io.IOException
class OneTimePreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : Database(context, databaseHelper) {
@@ -34,8 +34,8 @@ class OneTimePreKeyDatabase(context: Context, databaseHelper: SignalDatabase) :
"""
}
fun get(accountId: AccountIdentifier, keyId: Int): PreKeyRecord? {
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(accountId, keyId), null, null, null).use { cursor ->
fun get(serviceId: ServiceId, keyId: Int): PreKeyRecord? {
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(serviceId, keyId), null, null, null).use { cursor ->
if (cursor.moveToFirst()) {
try {
val publicKey = Curve.decodePoint(Base64.decode(cursor.requireNonNullString(PUBLIC_KEY)), 0)
@@ -52,9 +52,9 @@ class OneTimePreKeyDatabase(context: Context, databaseHelper: SignalDatabase) :
return null
}
fun insert(accountId: AccountIdentifier, keyId: Int, record: PreKeyRecord) {
fun insert(serviceId: ServiceId, keyId: Int, record: PreKeyRecord) {
val contentValues = contentValuesOf(
ACCOUNT_ID to accountId.toString(),
ACCOUNT_ID to serviceId.toString(),
KEY_ID to keyId,
PUBLIC_KEY to Base64.encodeBytes(record.keyPair.publicKey.serialize()),
PRIVATE_KEY to Base64.encodeBytes(record.keyPair.privateKey.serialize())
@@ -63,8 +63,8 @@ class OneTimePreKeyDatabase(context: Context, databaseHelper: SignalDatabase) :
writableDatabase.replace(TABLE_NAME, null, contentValues)
}
fun delete(accountId: AccountIdentifier, keyId: Int) {
fun delete(serviceId: ServiceId, keyId: Int) {
val database = databaseHelper.signalWritableDatabase
database.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(accountId, keyId))
database.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(serviceId, keyId))
}
}

View File

@@ -79,6 +79,7 @@ import org.whispersystems.libsignal.util.guava.Optional
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile
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.SignalServiceAddress
import org.whispersystems.signalservice.api.storage.SignalAccountRecord
import org.whispersystems.signalservice.api.storage.SignalContactRecord
@@ -110,7 +111,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
const val TABLE_NAME = "recipient"
const val ID = "_id"
private const val ACI_COLUMN = "uuid"
private const val SERVICE_ID = "uuid"
private const val PNI_COLUMN = "pni"
private const val USERNAME = "username"
const val PHONE = "phone"
@@ -171,7 +172,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
"""
CREATE TABLE $TABLE_NAME (
$ID INTEGER PRIMARY KEY AUTOINCREMENT,
$ACI_COLUMN TEXT UNIQUE DEFAULT NULL,
$SERVICE_ID TEXT UNIQUE DEFAULT NULL,
$USERNAME TEXT UNIQUE DEFAULT NULL,
$PHONE TEXT UNIQUE DEFAULT NULL,
$EMAIL TEXT UNIQUE DEFAULT NULL,
@@ -232,7 +233,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
private val RECIPIENT_PROJECTION: Array<String> = arrayOf(
ID,
ACI_COLUMN,
SERVICE_ID,
PNI_COLUMN,
USERNAME,
PHONE,
@@ -367,7 +368,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
}
fun containsPhoneOrUuid(id: String): Boolean {
val query = "$ACI_COLUMN = ? OR $PHONE = ?"
val query = "$SERVICE_ID = ? OR $PHONE = ?"
val args = arrayOf(id, id)
readableDatabase.query(TABLE_NAME, arrayOf(ID), query, args, null, null, null).use { cursor -> return cursor != null && cursor.moveToFirst() }
}
@@ -384,20 +385,20 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
return getByColumn(GROUP_ID, groupId.toString())
}
fun getByAci(uuid: ACI): Optional<RecipientId> {
return getByColumn(ACI_COLUMN, uuid.toString())
fun getByServiceId(serviceId: ServiceId): Optional<RecipientId> {
return getByColumn(SERVICE_ID, serviceId.toString())
}
fun getByUsername(username: String): Optional<RecipientId> {
return getByColumn(USERNAME, username)
}
fun getAndPossiblyMerge(aci: ACI?, e164: String?, highTrust: Boolean): RecipientId {
return getAndPossiblyMerge(aci, e164, highTrust, false)
fun getAndPossiblyMerge(serviceId: ServiceId?, e164: String?, highTrust: Boolean): RecipientId {
return getAndPossiblyMerge(serviceId, e164, highTrust, false)
}
fun getAndPossiblyMerge(aci: ACI?, e164: String?, highTrust: Boolean, changeSelf: Boolean): RecipientId {
require(!(aci == null && e164 == null)) { "Must provide an ACI or E164!" }
fun getAndPossiblyMerge(serviceId: ServiceId?, e164: String?, highTrust: Boolean, changeSelf: Boolean): RecipientId {
require(!(serviceId == null && e164 == null)) { "Must provide an ACI or E164!" }
val db = writableDatabase
@@ -408,7 +409,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
db.beginTransaction()
try {
val fetch: RecipientFetch = fetchRecipient(aci, e164, highTrust, changeSelf)
val fetch: RecipientFetch = fetchRecipient(serviceId, e164, highTrust, changeSelf)
if (fetch.logBundle != null) {
Log.w(TAG, fetch.toString())
@@ -432,29 +433,29 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
fetch.id
}
is RecipientFetch.MatchAndUpdateAci -> {
markRegistered(fetch.id, fetch.aci)
markRegistered(fetch.id, fetch.serviceId)
recipientsNeedingRefresh = listOf(fetch.id)
fetch.id
}
is RecipientFetch.MatchAndInsertAci -> {
val id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(null, fetch.aci))
val id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(null, fetch.serviceId))
RecipientId.from(id)
}
is RecipientFetch.MatchAndMerge -> {
remapped = Pair(fetch.e164Id, fetch.aciId)
val mergedId: RecipientId = merge(fetch.aciId, fetch.e164Id)
remapped = Pair(fetch.e164Id, fetch.sidId)
val mergedId: RecipientId = merge(fetch.sidId, fetch.e164Id)
recipientsNeedingRefresh = listOf(mergedId)
recipientChangedNumber = fetch.changedNumber
mergedId
}
is RecipientFetch.Insert -> {
val id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(fetch.e164, fetch.aci))
val id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(fetch.e164, fetch.serviceId))
RecipientId.from(id)
}
is RecipientFetch.InsertAndReassignE164 -> {
removePhoneNumber(fetch.e164Id, db)
recipientsNeedingRefresh = listOf(fetch.e164Id)
val id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(fetch.e164, fetch.aci))
val id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(fetch.e164, fetch.serviceId))
RecipientId.from(id)
}
}
@@ -488,12 +489,12 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
}
}
private fun fetchRecipient(aci: ACI?, e164: String?, highTrust: Boolean, changeSelf: Boolean): RecipientFetch {
private fun fetchRecipient(serviceId: ServiceId?, e164: String?, highTrust: Boolean, changeSelf: Boolean): RecipientFetch {
val byE164 = e164?.let { getByE164(it) } ?: Optional.absent()
val byAci = aci?.let { getByAci(it) } ?: Optional.absent()
val byAci = serviceId?.let { getByServiceId(it) } ?: Optional.absent()
var logs = LogBundle(
byAci = byAci.transform { id -> RecipientLogDetails(id = id) }.orNull(),
bySid = byAci.transform { id -> RecipientLogDetails(id = id) }.orNull(),
byE164 = byE164.transform { id -> RecipientLogDetails(id = id) }.orNull(),
label = "L0"
)
@@ -504,9 +505,9 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
if (byAci.isPresent && byE164.isAbsent()) {
val aciRecord: RecipientRecord = getRecord(byAci.get())
logs = logs.copy(byAci = aciRecord.toLogDetails())
logs = logs.copy(bySid = aciRecord.toLogDetails())
if (highTrust && e164 != null && (changeSelf || aci != SignalStore.account().aci)) {
if (highTrust && e164 != null && (changeSelf || serviceId != SignalStore.account().aci)) {
val changedNumber: RecipientId? = if (aciRecord.e164 != null && aciRecord.e164 != e164) aciRecord.id else null
return RecipientFetch.MatchAndUpdateE164(byAci.get(), e164, changedNumber, logs.label("L1"))
} else if (e164 == null) {
@@ -520,12 +521,12 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
val e164Record: RecipientRecord = getRecord(byE164.get())
logs = logs.copy(byE164 = e164Record.toLogDetails())
if (highTrust && aci != null && e164Record.aci == null) {
return RecipientFetch.MatchAndUpdateAci(byE164.get(), aci, logs.label("L3"))
} else if (highTrust && aci != null && e164Record.aci != SignalStore.account().aci) {
return RecipientFetch.InsertAndReassignE164(aci, e164, byE164.get(), logs.label("L4"))
} else if (aci != null) {
return RecipientFetch.Insert(aci, null, logs.label("L5"))
if (highTrust && serviceId != null && e164Record.serviceId == null) {
return RecipientFetch.MatchAndUpdateAci(byE164.get(), serviceId, logs.label("L3"))
} else if (highTrust && serviceId != null && e164Record.serviceId != SignalStore.account().aci) {
return RecipientFetch.InsertAndReassignE164(serviceId, e164, byE164.get(), logs.label("L4"))
} else if (serviceId != null) {
return RecipientFetch.Insert(serviceId, null, logs.label("L5"))
} else {
return RecipientFetch.Match(byE164.get(), null)
}
@@ -533,9 +534,9 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
if (byAci.isAbsent() && byE164.isAbsent()) {
if (highTrust) {
return RecipientFetch.Insert(aci, e164, logs.label("L6"))
} else if (aci != null) {
return RecipientFetch.Insert(aci, null, logs.label("L7"))
return RecipientFetch.Insert(serviceId, e164, logs.label("L6"))
} else if (serviceId != null) {
return RecipientFetch.Insert(serviceId, null, logs.label("L7"))
} else {
return RecipientFetch.Insert(null, e164, logs.label("L8"))
}
@@ -546,17 +547,17 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
val aciRecord: RecipientRecord = getRecord(byAci.get())
val e164Record: RecipientRecord = getRecord(byE164.get())
logs = logs.copy(byAci = aciRecord.toLogDetails(), byE164 = e164Record.toLogDetails())
logs = logs.copy(bySid = aciRecord.toLogDetails(), byE164 = e164Record.toLogDetails())
if (e164Record.aci == null) {
if (e164Record.serviceId == null) {
if (highTrust) {
val changedNumber: RecipientId? = if (aciRecord.e164 != null) aciRecord.id else null
return RecipientFetch.MatchAndMerge(aciId = byAci.get(), e164Id = byE164.get(), changedNumber = changedNumber, logs.label("L9"))
return RecipientFetch.MatchAndMerge(sidId = byAci.get(), e164Id = byE164.get(), changedNumber = changedNumber, logs.label("L9"))
} else {
return RecipientFetch.Match(byAci.get(), logs.label("L10"))
}
} else {
if (highTrust && e164Record.aci != SignalStore.account().aci) {
if (highTrust && e164Record.serviceId != SignalStore.account().aci) {
val changedNumber: RecipientId? = if (aciRecord.e164 != null) aciRecord.id else null
return RecipientFetch.MatchAndReassignE164(id = byAci.get(), e164Id = byE164.get(), e164 = e164!!, changedNumber = changedNumber, logs.label("L11"))
} else {
@@ -565,8 +566,8 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
}
}
fun getOrInsertFromAci(aci: ACI): RecipientId {
return getOrInsertByColumn(ACI_COLUMN, aci.toString()).recipientId
fun getOrInsertFromServiceId(serviceId: ServiceId): RecipientId {
return getOrInsertByColumn(SERVICE_ID, serviceId.toString()).recipientId
}
fun getOrInsertFromE164(e164: String): RecipientId {
@@ -785,13 +786,13 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
val recipientId: RecipientId?
if (id < 0) {
Log.w(TAG, "[applyStorageSyncContactInsert] Failed to insert. Possibly merging.")
recipientId = getAndPossiblyMerge(if (insert.address.hasValidAci()) insert.address.aci else null, insert.address.number.orNull(), true)
recipientId = getAndPossiblyMerge(if (insert.address.hasValidServiceId()) insert.address.serviceId else null, insert.address.number.orNull(), true)
db.update(TABLE_NAME, values, ID_WHERE, SqlUtil.buildArgs(recipientId))
} else {
recipientId = RecipientId.from(id)
}
if (insert.identityKey.isPresent && insert.address.hasValidAci()) {
if (insert.identityKey.isPresent && insert.address.hasValidServiceId()) {
try {
val identityKey = IdentityKey(insert.identityKey.get(), 0)
identities.updateIdentityAfterSync(insert.address.identifier, recipientId!!, identityKey, StorageSyncModels.remoteToLocalIdentityStatus(insert.identityState))
@@ -818,7 +819,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
var recipientId = getByColumn(STORAGE_SERVICE_ID, Base64.encodeBytes(update.old.id.raw)).get()
Log.w(TAG, "[applyStorageSyncContactUpdate] Found user $recipientId. Possibly merging.")
recipientId = getAndPossiblyMerge(if (update.new.address.hasValidAci()) update.new.address.aci else null, update.new.address.number.orNull(), true)
recipientId = getAndPossiblyMerge(if (update.new.address.hasValidServiceId()) update.new.address.serviceId else null, update.new.address.number.orNull(), true)
Log.w(TAG, "[applyStorageSyncContactUpdate] Merged into $recipientId")
db.update(TABLE_NAME, values, ID_WHERE, SqlUtil.buildArgs(recipientId))
@@ -834,7 +835,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
try {
val oldIdentityRecord = identityStore.getIdentityRecord(recipientId)
if (update.new.identityKey.isPresent && update.new.address.hasValidAci()) {
if (update.new.identityKey.isPresent && update.new.address.hasValidServiceId()) {
val identityKey = IdentityKey(update.new.identityKey.get(), 0)
identities.updateIdentityAfterSync(update.new.address.identifier, recipientId, identityKey, StorageSyncModels.remoteToLocalIdentityStatus(update.new.identityState))
}
@@ -982,7 +983,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
private fun getRecordForSync(query: String?, args: Array<String>?): List<RecipientRecord> {
val table =
"""
$TABLE_NAME LEFT OUTER JOIN ${IdentityDatabase.TABLE_NAME} ON $TABLE_NAME.$ACI_COLUMN = ${IdentityDatabase.TABLE_NAME}.${IdentityDatabase.ADDRESS}
$TABLE_NAME LEFT OUTER JOIN ${IdentityDatabase.TABLE_NAME} ON $TABLE_NAME.$SERVICE_ID = ${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}
""".trimIndent()
@@ -1018,7 +1019,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
fun getContactStorageSyncIdsMap(): Map<RecipientId, StorageId> {
val query = """
$STORAGE_SERVICE_ID NOT NULL AND (
($GROUP_TYPE = ? AND $ACI_COLUMN NOT NULL AND $ID != ?)
($GROUP_TYPE = ? AND $SERVICE_ID NOT NULL AND $ID != ?)
OR
$GROUP_TYPE IN (?)
)
@@ -1505,7 +1506,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
val selfId = Recipient.self().id
for ((key, value) in profileKeys) {
val recipientId = getOrInsertFromAci(key)
val recipientId = getOrInsertFromServiceId(key)
if (setProfileKeyIfAbsent(recipientId, value)) {
Log.i(TAG, "Learned new profile key")
updated.add(recipientId)
@@ -1513,7 +1514,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
}
for ((key, value) in authoritativeProfileKeys) {
val recipientId = getOrInsertFromAci(key)
val recipientId = getOrInsertFromServiceId(key)
if (selfId == recipientId) {
Log.i(TAG, "Seen authoritative update for self")
@@ -1760,7 +1761,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
Log.w(TAG, "[setPhoneNumber] Hit a conflict when trying to update $id. Possibly merging.")
val existing: RecipientRecord = getRecord(id)
val newId = getAndPossiblyMerge(existing.aci, e164, true)
val newId = getAndPossiblyMerge(existing.serviceId, e164, true)
Log.w(TAG, "[setPhoneNumber] Resulting id: $newId")
db.setTransactionSuccessful()
@@ -1812,7 +1813,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
db.beginTransaction()
try {
val id = Recipient.self().id
val newId = getAndPossiblyMerge(Recipient.self().requireAci(), e164, highTrust = true, changeSelf = true)
val newId = getAndPossiblyMerge(Recipient.self().requireServiceId(), e164, highTrust = true, changeSelf = true)
if (id == newId) {
Log.i(TAG, "[updateSelfPhone] Phone updated for self")
@@ -1874,19 +1875,19 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
/**
* @return True if setting the UUID resulted in changed recipientId, otherwise false.
*/
fun markRegistered(id: RecipientId, aci: ACI): Boolean {
fun markRegistered(id: RecipientId, serviceId: ServiceId): Boolean {
val db = writableDatabase
db.beginTransaction()
try {
markRegisteredOrThrow(id, aci)
markRegisteredOrThrow(id, serviceId)
db.setTransactionSuccessful()
return false
} catch (e: SQLiteConstraintException) {
Log.w(TAG, "[markRegistered] Hit a conflict when trying to update $id. Possibly merging.")
val existing = getRecord(id)
val newId = getAndPossiblyMerge(aci, existing.e164, true)
val newId = getAndPossiblyMerge(serviceId, existing.e164, true)
Log.w(TAG, "[markRegistered] Merged into $newId")
db.setTransactionSuccessful()
@@ -1899,10 +1900,10 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
/**
* Should only use if you are confident that this shouldn't result in any contact merging.
*/
fun markRegisteredOrThrow(id: RecipientId, aci: ACI) {
fun markRegisteredOrThrow(id: RecipientId, serviceId: ServiceId) {
val contentValues = ContentValues(2).apply {
put(REGISTERED, RegisteredState.REGISTERED.id)
put(ACI_COLUMN, aci.toString().toLowerCase())
put(SERVICE_ID, serviceId.toString().toLowerCase())
}
if (update(id, contentValues)) {
setStorageIdIfNotSet(id)
@@ -1920,7 +1921,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
}
}
fun bulkUpdatedRegisteredStatus(registered: Map<RecipientId, ACI?>, unregistered: Collection<RecipientId>) {
fun bulkUpdatedRegisteredStatus(registered: Map<RecipientId, ServiceId?>, unregistered: Collection<RecipientId>) {
val db = writableDatabase
db.beginTransaction()
@@ -1929,7 +1930,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
val values = ContentValues(2).apply {
put(REGISTERED, RegisteredState.REGISTERED.id)
if (aci != null) {
put(ACI_COLUMN, aci.toString().toLowerCase())
put(SERVICE_ID, aci.toString().toLowerCase())
}
}
@@ -1972,12 +1973,12 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
db.beginTransaction()
try {
for ((e164, aci) in mapping) {
var aciEntry = if (aci != null) getByAci(aci) else Optional.absent()
var aciEntry = if (aci != null) getByServiceId(aci) else Optional.absent()
if (aciEntry.isPresent) {
val idChanged = setPhoneNumber(aciEntry.get(), e164)
if (idChanged) {
aciEntry = getByAci(aci!!)
aciEntry = getByServiceId(aci!!)
}
}
@@ -2272,7 +2273,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
.toList()
val blockedUuid = blocked
.map { b: SignalServiceAddress -> b.aci.toString().toLowerCase() }
.map { b: SignalServiceAddress -> b.serviceId.toString().toLowerCase() }
.toList()
val db = writableDatabase
@@ -2293,7 +2294,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
}
for (uuid in blockedUuid) {
db.update(TABLE_NAME, setBlocked, "$ACI_COLUMN = ?", arrayOf(uuid))
db.update(TABLE_NAME, setBlocked, "$SERVICE_ID = ?", arrayOf(uuid))
}
val groupIdStrings: MutableList<V1> = ArrayList(groupIds.size)
@@ -2604,10 +2605,10 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
}
// Sessions
val localAci: ACI = SignalStore.account().aci!!
val localAci: ACI = SignalStore.account().requireAci()
val sessionDatabase = sessions
val hasE164Session = sessionDatabase.getAllFor(localAci, e164Record.e164).isNotEmpty()
val hasAciSession = sessionDatabase.getAllFor(localAci, aciRecord.aci.toString()).isNotEmpty()
val hasAciSession = sessionDatabase.getAllFor(localAci, aciRecord.serviceId.toString()).isNotEmpty()
if (hasE164Session && hasAciSession) {
Log.w(TAG, "Had a session for both users. Deleting the E164.", true)
@@ -2615,7 +2616,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
} else if (hasE164Session && !hasAciSession) {
Log.w(TAG, "Had a session for E164, but not ACI. Re-assigning to the ACI.", true)
val values = ContentValues().apply {
put(SessionDatabase.ADDRESS, aciRecord.aci.toString())
put(SessionDatabase.ADDRESS, aciRecord.serviceId.toString())
}
db.update(SessionDatabase.TABLE_NAME, values, "${SessionDatabase.ACCOUNT_ID} = ? AND ${SessionDatabase.ADDRESS} = ?", SqlUtil.buildArgs(localAci, e164Record.e164))
} else if (!hasE164Session && hasAciSession) {
@@ -2694,11 +2695,11 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
check(writableDatabase.inTransaction()) { "Must be in a transaction!" }
}
private fun buildContentValuesForNewUser(e164: String?, aci: ACI?): ContentValues {
private fun buildContentValuesForNewUser(e164: String?, serviceId: ServiceId?): ContentValues {
val values = ContentValues()
values.put(PHONE, e164)
if (aci != null) {
values.put(ACI_COLUMN, aci.toString().toLowerCase())
if (serviceId != null) {
values.put(SERVICE_ID, serviceId.toString().toLowerCase())
values.put(REGISTERED, RegisteredState.REGISTERED.id)
values.put(STORAGE_SERVICE_ID, Base64.encodeBytes(StorageSyncHelper.generateKey()))
values.put(AVATAR_COLOR, AvatarColor.random().serialize())
@@ -2711,8 +2712,8 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
val profileName = ProfileName.fromParts(contact.givenName.orNull(), contact.familyName.orNull())
val username = contact.username.orNull()
if (contact.address.hasValidAci()) {
put(ACI_COLUMN, contact.address.aci.toString())
if (contact.address.hasValidServiceId()) {
put(SERVICE_ID, contact.address.serviceId.toString())
}
put(PHONE, contact.address.number.orNull())
@@ -2845,7 +2846,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
return RecipientRecord(
id = recipientId,
aci = ACI.parseOrNull(cursor.requireString(ACI_COLUMN)),
serviceId = ACI.parseOrNull(cursor.requireString(SERVICE_ID)),
pni = PNI.parseOrNull(cursor.requireString(PNI_COLUMN)),
username = cursor.requireString(USERNAME),
e164 = cursor.requireString(PHONE),
@@ -3045,7 +3046,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
private fun RecipientRecord.toLogDetails(): RecipientLogDetails {
return RecipientLogDetails(
id = this.id,
aci = this.aci,
serviceId = this.serviceId,
e164 = this.e164
)
}
@@ -3357,27 +3358,27 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
/**
* We found a matching recipient and can update them with a new ACI.
*/
data class MatchAndUpdateAci(val id: RecipientId, val aci: ACI, val bundle: LogBundle) : RecipientFetch(bundle)
data class MatchAndUpdateAci(val id: RecipientId, val serviceId: ServiceId, val bundle: LogBundle) : RecipientFetch(bundle)
/**
* We found a matching recipient and can insert an ACI as a *new user*.
*/
data class MatchAndInsertAci(val id: RecipientId, val aci: ACI, val bundle: LogBundle) : RecipientFetch(bundle)
data class MatchAndInsertAci(val id: RecipientId, val serviceId: ServiceId, val bundle: LogBundle) : RecipientFetch(bundle)
/**
* The ACI maps to ACI-only recipient, and the E164 maps to a different E164-only recipient. We need to merge the two together.
*/
data class MatchAndMerge(val aciId: RecipientId, val e164Id: RecipientId, val changedNumber: RecipientId?, val bundle: LogBundle) : RecipientFetch(bundle)
data class MatchAndMerge(val sidId: RecipientId, val e164Id: RecipientId, val changedNumber: RecipientId?, val bundle: LogBundle) : RecipientFetch(bundle)
/**
* We don't have a matching recipient, so we need to insert one.
*/
data class Insert(val aci: ACI?, val e164: String?, val bundle: LogBundle) : RecipientFetch(bundle)
data class Insert(val serviceId: ServiceId?, val e164: String?, val bundle: LogBundle) : RecipientFetch(bundle)
/**
* We need to create a new recipient and give it the E164 of an existing recipient.
*/
data class InsertAndReassignE164(val aci: ACI?, val e164: String?, val e164Id: RecipientId, val bundle: LogBundle) : RecipientFetch(bundle)
data class InsertAndReassignE164(val serviceId: ServiceId?, val e164: String?, val e164Id: RecipientId, val bundle: LogBundle) : RecipientFetch(bundle)
}
/**
@@ -3385,9 +3386,9 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
*/
private data class LogBundle(
val label: String,
val aci: ACI? = null,
val serviceId: ServiceId? = null,
val e164: String? = null,
val byAci: RecipientLogDetails? = null,
val bySid: RecipientLogDetails? = null,
val byE164: RecipientLogDetails? = null
) {
fun label(label: String): LogBundle {
@@ -3400,7 +3401,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
*/
private data class RecipientLogDetails(
val id: RecipientId,
val aci: ACI? = null,
val serviceId: ServiceId? = null,
val e164: String? = null
)
}

View File

@@ -133,7 +133,7 @@ public class SenderKeyDatabase extends Database {
public Cursor getAllCreatedBySelf() {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
String query = ADDRESS + " = ?";
String[] args = SqlUtil.buildArgs(Recipient.self().requireAci());
String[] args = SqlUtil.buildArgs(Recipient.self().requireServiceId());
return db.query(TABLE_NAME, new String[]{ ID, DISTRIBUTION_ID, CREATED_AT }, query, args, null, null, CREATED_AT + " DESC");
}

View File

@@ -145,8 +145,8 @@ public class SenderKeySharedDatabase extends Database {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
Recipient recipient = Recipient.resolved(recipientId);
if (recipient.hasAci()) {
db.delete(TABLE_NAME, ADDRESS + " = ?", SqlUtil.buildArgs(recipient.requireAci().toString()));
if (recipient.hasServiceId()) {
db.delete(TABLE_NAME, ADDRESS + " = ?", SqlUtil.buildArgs(recipient.requireServiceId().toString()));
} else {
Log.w(TAG, "Recipient doesn't have a UUID! " + recipientId);
}

View File

@@ -6,7 +6,7 @@ import org.thoughtcrime.securesms.util.CursorUtil
import org.thoughtcrime.securesms.util.SqlUtil
import org.whispersystems.libsignal.SignalProtocolAddress
import org.whispersystems.libsignal.state.SessionRecord
import org.whispersystems.signalservice.api.push.AccountIdentifier
import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.api.push.SignalServiceAddress
import java.io.IOException
import java.util.ArrayList
@@ -36,12 +36,12 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
"""
}
fun store(accountId: AccountIdentifier, address: SignalProtocolAddress, record: SessionRecord) {
fun store(serviceId: ServiceId, address: SignalProtocolAddress, record: SessionRecord) {
require(address.name[0] != '+') { "Cannot insert an e164 into this table!" }
writableDatabase.compileStatement("INSERT INTO $TABLE_NAME ($ACCOUNT_ID, $ADDRESS, $DEVICE, $RECORD) VALUES (?, ?, ?, ?) ON CONFLICT ($ACCOUNT_ID, $ADDRESS, $DEVICE) DO UPDATE SET $RECORD = excluded.$RECORD").use { statement ->
statement.apply {
bindString(1, accountId.toString())
bindString(1, serviceId.toString())
bindString(2, address.name)
bindLong(3, address.deviceId.toLong())
bindBlob(4, record.serialize())
@@ -50,10 +50,10 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
}
}
fun load(accountId: AccountIdentifier, address: SignalProtocolAddress): SessionRecord? {
fun load(serviceId: ServiceId, address: SignalProtocolAddress): SessionRecord? {
val projection = arrayOf(RECORD)
val selection = "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE = ?"
val args = SqlUtil.buildArgs(accountId, address.name, address.deviceId)
val args = SqlUtil.buildArgs(serviceId, address.name, address.deviceId)
readableDatabase.query(TABLE_NAME, projection, selection, args, null, null, null).use { cursor ->
if (cursor.moveToFirst()) {
@@ -68,14 +68,14 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
return null
}
fun load(accountId: AccountIdentifier, addresses: List<SignalProtocolAddress>): List<SessionRecord?> {
fun load(serviceId: ServiceId, addresses: List<SignalProtocolAddress>): List<SessionRecord?> {
val projection = arrayOf(ADDRESS, DEVICE, RECORD)
val query = "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE = ?"
val args: MutableList<Array<String>> = ArrayList(addresses.size)
val sessions: HashMap<SignalProtocolAddress, SessionRecord?> = LinkedHashMap(addresses.size)
for (address in addresses) {
args.add(SqlUtil.buildArgs(accountId, address.name, address.deviceId))
args.add(SqlUtil.buildArgs(serviceId, address.name, address.deviceId))
sessions[address] = null
}
@@ -97,10 +97,10 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
return sessions.values.toList()
}
fun getAllFor(accountId: AccountIdentifier, addressName: String): List<SessionRow> {
fun getAllFor(serviceId: ServiceId, addressName: String): List<SessionRow> {
val results: MutableList<SessionRow> = mutableListOf()
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $ADDRESS = ?", SqlUtil.buildArgs(accountId, addressName), null, null, null).use { cursor ->
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $ADDRESS = ?", SqlUtil.buildArgs(serviceId, addressName), null, null, null).use { cursor ->
while (cursor.moveToNext()) {
try {
results.add(
@@ -118,12 +118,12 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
return results
}
fun getAllFor(accountId: AccountIdentifier, addressNames: List<String?>): List<SessionRow> {
fun getAllFor(serviceId: ServiceId, addressNames: List<String?>): List<SessionRow> {
val query: SqlUtil.Query = SqlUtil.buildCollectionQuery(ADDRESS, addressNames)
val results: MutableList<SessionRow> = LinkedList()
val queryString = "$ACCOUNT_ID = ? AND (${query.where})"
val queryArgs: Array<String> = arrayOf(accountId.toString()) + query.whereArgs
val queryArgs: Array<String> = arrayOf(serviceId.toString()) + query.whereArgs
readableDatabase.query(TABLE_NAME, null, queryString, queryArgs, null, null, null).use { cursor ->
while (cursor.moveToNext()) {
@@ -143,10 +143,10 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
return results
}
fun getAll(accountId: AccountIdentifier): List<SessionRow> {
fun getAll(serviceId: ServiceId): List<SessionRow> {
val results: MutableList<SessionRow> = mutableListOf()
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ?", SqlUtil.buildArgs(accountId), null, null, null).use { cursor ->
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ?", SqlUtil.buildArgs(serviceId), null, null, null).use { cursor ->
while (cursor.moveToNext()) {
try {
results.add(
@@ -164,10 +164,10 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
return results
}
fun getSubDevices(accountId: AccountIdentifier, addressName: String): List<Int> {
fun getSubDevices(serviceId: ServiceId, addressName: String): List<Int> {
val projection = arrayOf(DEVICE)
val selection = "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE != ?"
val args = SqlUtil.buildArgs(accountId, addressName, SignalServiceAddress.DEFAULT_DEVICE_ID)
val args = SqlUtil.buildArgs(serviceId, addressName, SignalServiceAddress.DEFAULT_DEVICE_ID)
val results: MutableList<Int> = mutableListOf()
@@ -179,17 +179,17 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
return results
}
fun delete(accountId: AccountIdentifier, address: SignalProtocolAddress) {
writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE = ?", SqlUtil.buildArgs(accountId, address.name, address.deviceId))
fun delete(serviceId: ServiceId, address: SignalProtocolAddress) {
writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE = ?", SqlUtil.buildArgs(serviceId, address.name, address.deviceId))
}
fun deleteAllFor(accountId: AccountIdentifier, addressName: String) {
writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $ADDRESS = ?", SqlUtil.buildArgs(accountId, addressName))
fun deleteAllFor(serviceId: ServiceId, addressName: String) {
writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $ADDRESS = ?", SqlUtil.buildArgs(serviceId, addressName))
}
fun hasSessionFor(accountId: AccountIdentifier, addressName: String): Boolean {
fun hasSessionFor(serviceId: ServiceId, addressName: String): Boolean {
val query = "$ACCOUNT_ID = ? AND $ADDRESS = ?"
val args = SqlUtil.buildArgs(accountId, addressName)
val args = SqlUtil.buildArgs(serviceId, addressName)
readableDatabase.query(TABLE_NAME, arrayOf("1"), query, args, null, null, null, "1").use { cursor ->
return cursor.moveToFirst()
}

View File

@@ -9,7 +9,7 @@ import org.whispersystems.libsignal.InvalidKeyException
import org.whispersystems.libsignal.ecc.Curve
import org.whispersystems.libsignal.ecc.ECKeyPair
import org.whispersystems.libsignal.state.SignedPreKeyRecord
import org.whispersystems.signalservice.api.push.AccountIdentifier
import org.whispersystems.signalservice.api.push.ServiceId
import java.io.IOException
import java.util.LinkedList
@@ -39,8 +39,8 @@ class SignedPreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : D
"""
}
fun get(accountId: AccountIdentifier, keyId: Int): SignedPreKeyRecord? {
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(accountId, keyId), null, null, null).use { cursor ->
fun get(serviceId: ServiceId, keyId: Int): SignedPreKeyRecord? {
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(serviceId, keyId), null, null, null).use { cursor ->
if (cursor.moveToFirst()) {
try {
val publicKey = Curve.decodePoint(Base64.decode(cursor.requireNonNullString(PUBLIC_KEY)), 0)
@@ -58,10 +58,10 @@ class SignedPreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : D
return null
}
fun getAll(accountId: AccountIdentifier): List<SignedPreKeyRecord> {
fun getAll(serviceId: ServiceId): List<SignedPreKeyRecord> {
val results: MutableList<SignedPreKeyRecord> = LinkedList()
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ?", SqlUtil.buildArgs(accountId), null, null, null).use { cursor ->
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ?", SqlUtil.buildArgs(serviceId), null, null, null).use { cursor ->
while (cursor.moveToNext()) {
try {
val keyId = cursor.requireInt(KEY_ID)
@@ -81,9 +81,9 @@ class SignedPreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : D
return results
}
fun insert(accountId: AccountIdentifier, keyId: Int, record: SignedPreKeyRecord) {
fun insert(serviceId: ServiceId, keyId: Int, record: SignedPreKeyRecord) {
val contentValues = contentValuesOf(
ACCOUNT_ID to accountId.toString(),
ACCOUNT_ID to serviceId.toString(),
KEY_ID to keyId,
PUBLIC_KEY to Base64.encodeBytes(record.keyPair.publicKey.serialize()),
PRIVATE_KEY to Base64.encodeBytes(record.keyPair.privateKey.serialize()),
@@ -93,7 +93,7 @@ class SignedPreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : D
writableDatabase.replace(TABLE_NAME, null, contentValues)
}
fun delete(accountId: AccountIdentifier, keyId: Int) {
writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(accountId, keyId))
fun delete(serviceId: ServiceId, keyId: Int) {
writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(serviceId, keyId))
}
}

View File

@@ -719,11 +719,11 @@ public class SmsDatabase extends MessageDatabase {
if (!peerEraIdSameAsPrevious && !Util.isEmpty(peekGroupCallEraId)) {
Recipient self = Recipient.self();
boolean markRead = peekJoinedUuids.contains(self.requireAci().uuid()) || self.getId().equals(sender);
boolean markRead = peekJoinedUuids.contains(self.requireServiceId().uuid()) || self.getId().equals(sender);
byte[] updateDetails = GroupCallUpdateDetails.newBuilder()
.setEraId(Util.emptyIfNull(peekGroupCallEraId))
.setStartedCallUuid(Recipient.resolved(sender).requireAci().toString())
.setStartedCallUuid(Recipient.resolved(sender).requireServiceId().toString())
.setStartedCallTimestamp(timestamp)
.addAllInCallUuids(Stream.of(peekJoinedUuids).map(UUID::toString).toList())
.setIsCallFull(isCallFull)
@@ -800,7 +800,7 @@ public class SmsDatabase extends MessageDatabase {
if (!sameEraId && !Util.isEmpty(messageGroupCallEraId)) {
byte[] updateDetails = GroupCallUpdateDetails.newBuilder()
.setEraId(Util.emptyIfNull(messageGroupCallEraId))
.setStartedCallUuid(Recipient.resolved(sender).requireAci().toString())
.setStartedCallUuid(Recipient.resolved(sender).requireServiceId().toString())
.setStartedCallTimestamp(timestamp)
.addAllInCallUuids(Collections.emptyList())
.setIsCallFull(false)
@@ -849,7 +849,7 @@ public class SmsDatabase extends MessageDatabase {
}
GroupCallUpdateDetails groupCallUpdateDetails = GroupCallUpdateDetailsUtil.parse(record.getBody());
boolean containsSelf = peekJoinedUuids.contains(Recipient.self().requireAci().uuid());
boolean containsSelf = peekJoinedUuids.contains(Recipient.self().requireServiceId().uuid());
sameEraId = groupCallUpdateDetails.getEraId().equals(peekGroupCallEraId) && !Util.isEmpty(peekGroupCallEraId);

View File

@@ -1208,7 +1208,7 @@ public class ThreadDatabase extends Database {
Recipient pinnedRecipient;
if (pinned.getContact().isPresent()) {
pinnedRecipient = Recipient.externalPush(context, pinned.getContact().get());
pinnedRecipient = Recipient.externalPush(pinned.getContact().get());
} else if (pinned.getGroupV1Id().isPresent()) {
try {
pinnedRecipient = Recipient.externalGroupExact(context, GroupId.v1(pinned.getGroupV1Id().get()));

View File

@@ -6,11 +6,12 @@ import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.model.databaseprotos.GroupCallUpdateDetails;
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.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.push.ServiceId;
import java.util.ArrayList;
import java.util.List;
@@ -22,13 +23,13 @@ import java.util.Objects;
*/
public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFactory {
private final Context context;
private final List<ACI> joinedMembers;
private final List<ServiceId> joinedMembers;
private final boolean withTime;
private final GroupCallUpdateDetails groupCallUpdateDetails;
private final ACI selfAci;
public GroupCallUpdateMessageFactory(@NonNull Context context,
@NonNull List<ACI> joinedMembers,
@NonNull List<ServiceId> joinedMembers,
boolean withTime,
@NonNull GroupCallUpdateDetails groupCallUpdateDetails)
{
@@ -36,7 +37,7 @@ public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFa
this.joinedMembers = new ArrayList<>(joinedMembers);
this.withTime = withTime;
this.groupCallUpdateDetails = groupCallUpdateDetails;
this.selfAci = Recipient.self().requireAci();
this.selfAci = SignalStore.account().requireAci();
boolean removed = this.joinedMembers.remove(selfAci);
if (removed) {
@@ -87,12 +88,12 @@ public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFa
}
}
private @NonNull String describe(@NonNull ACI aci) {
if (aci.isUnknown()) {
private @NonNull String describe(@NonNull ServiceId serviceId) {
if (serviceId.isUnknown()) {
return context.getString(R.string.MessageRecord_unknown);
}
Recipient recipient = Recipient.resolved(RecipientId.from(aci, null));
Recipient recipient = Recipient.resolved(RecipientId.from(serviceId, null));
if (recipient.isSelf()) {
return context.getString(R.string.MessageRecord_you);

View File

@@ -27,6 +27,7 @@ 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.push.ServiceId;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.Arrays;
@@ -746,11 +747,11 @@ final class GroupsV2UpdateMessageProducer {
/**
* Map an ACI to a string that describes the group member.
* @param aci
* @param serviceId
*/
@NonNull
@WorkerThread
String describe(@NonNull ACI aci);
String describe(@NonNull ServiceId serviceId);
}
private interface StringFactory1Arg {
@@ -771,9 +772,9 @@ final class GroupsV2UpdateMessageProducer {
@NonNull StringFactory1Arg stringFactory,
@DrawableRes int iconResource)
{
ACI aci1 = ACI.fromByteStringOrUnknown(uuid1Bytes);
ServiceId serviceId = ServiceId.fromByteStringOrUnknown(uuid1Bytes);
return UpdateDescription.mentioning(Collections.singletonList(aci1), () -> stringFactory.create(descriptionStrategy.describe(aci1)), iconResource);
return UpdateDescription.mentioning(Collections.singletonList(serviceId), () -> stringFactory.create(descriptionStrategy.describe(serviceId)), iconResource);
}
private UpdateDescription updateDescription(@NonNull ByteString uuid1Bytes,
@@ -781,9 +782,9 @@ final class GroupsV2UpdateMessageProducer {
@NonNull StringFactory2Args stringFactory,
@DrawableRes int iconResource)
{
ACI aci1 = ACI.fromByteStringOrUnknown(uuid1Bytes);
ACI aci2 = ACI.fromByteStringOrUnknown(uuid2Bytes);
ServiceId sid1 = ServiceId.fromByteStringOrUnknown(uuid1Bytes);
ServiceId sid2 = ServiceId.fromByteStringOrUnknown(uuid2Bytes);
return UpdateDescription.mentioning(Arrays.asList(aci1, aci2), () -> stringFactory.create(descriptionStrategy.describe(aci1), descriptionStrategy.describe(aci2)), iconResource);
return UpdateDescription.mentioning(Arrays.asList(sid1, sid2), () -> stringFactory.create(descriptionStrategy.describe(sid1), descriptionStrategy.describe(sid2)), iconResource);
}
}

View File

@@ -60,7 +60,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.push.ServiceId;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.io.IOException;
@@ -253,7 +253,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().requireAci().uuid()));
change.getEditor().equals(UuidUtil.toByteString(Recipient.self().requireServiceId().uuid()));
}
public static @NonNull UpdateDescription getGv2ChangeDescription(@NonNull Context context, @NonNull String body) {
@@ -261,7 +261,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().requireAci().uuid());
GroupsV2UpdateMessageProducer updateMessageProducer = new GroupsV2UpdateMessageProducer(context, descriptionStrategy, Recipient.self().requireServiceId().uuid());
if (decryptedGroupV2Context.hasChange() && (decryptedGroupV2Context.getGroupState().getRevision() != 0 || decryptedGroupV2Context.hasPreviousGroupState())) {
return UpdateDescription.concatWithNewLines(updateMessageProducer.describeChanges(decryptedGroupV2Context.getPreviousGroupState(), decryptedGroupV2Context.getChange()));
@@ -292,7 +292,7 @@ public abstract class MessageRecord extends DisplayRecord {
}
DecryptedGroup groupState = decryptedGroupV2Context.getGroupState();
boolean invited = DecryptedGroupUtil.findPendingByUuid(groupState.getPendingMembersList(), Recipient.self().requireAci().uuid()).isPresent();
boolean invited = DecryptedGroupUtil.findPendingByUuid(groupState.getPendingMembersList(), Recipient.self().requireServiceId().uuid()).isPresent();
if (decryptedGroupV2Context.hasChange()) {
UUID changeEditor = UuidUtil.fromByteStringOrNull(decryptedGroupV2Context.getChange().getEditor());
@@ -314,7 +314,7 @@ public abstract class MessageRecord extends DisplayRecord {
@NonNull Function<Recipient, String> stringGenerator,
@DrawableRes int iconResource)
{
return UpdateDescription.mentioning(Collections.singletonList(recipient.getAci().or(ACI.UNKNOWN)),
return UpdateDescription.mentioning(Collections.singletonList(recipient.getServiceId().or(ServiceId.UNKNOWN)),
() -> stringGenerator.apply(recipient.resolve()),
iconResource);
}
@@ -382,11 +382,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<ACI> joinedMembers = Stream.of(groupCallUpdateDetails.getInCallUuidsList())
.map(UuidUtil::parseOrNull)
.withoutNulls()
.map(ACI::from)
.toList();
List<ServiceId> joinedMembers = Stream.of(groupCallUpdateDetails.getInCallUuidsList())
.map(UuidUtil::parseOrNull)
.withoutNulls()
.map(ServiceId::from)
.toList();
UpdateDescription.StringFactory stringFactory = new GroupCallUpdateMessageFactory(context, joinedMembers, withTime, groupCallUpdateDetails);
@@ -421,11 +421,11 @@ public abstract class MessageRecord extends DisplayRecord {
}
@Override
public @NonNull String describe(@NonNull ACI aci) {
if (aci.isUnknown()) {
public @NonNull String describe(@NonNull ServiceId serviceId) {
if (serviceId.isUnknown()) {
return context.getString(R.string.MessageRecord_unknown);
}
return Recipient.resolved(RecipientId.from(aci, null)).getDisplayName(context);
return Recipient.resolved(RecipientId.from(serviceId, null)).getDisplayName(context);
}
}

View File

@@ -20,15 +20,15 @@ import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper
import org.whispersystems.libsignal.util.guava.Optional
import org.whispersystems.signalservice.api.push.ACI
import org.whispersystems.signalservice.api.push.PNI
import org.whispersystems.signalservice.api.push.ServiceId
/**
* Database model for [RecipientDatabase].
*/
data class RecipientRecord(
val id: RecipientId,
val aci: ACI?,
val serviceId: ServiceId?,
val pni: PNI?,
val username: String?,
val e164: String?,

View File

@@ -9,6 +9,7 @@ import androidx.annotation.WorkerThread;
import org.signal.core.util.ThreadUtil;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.Collection;
@@ -28,14 +29,14 @@ public final class UpdateDescription {
String create();
}
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 final Collection<ServiceId> 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<ACI> mentioned,
private UpdateDescription(@NonNull Collection<ServiceId> mentioned,
@Nullable StringFactory stringFactory,
@Nullable String staticString,
@DrawableRes int iconResource,
@@ -60,11 +61,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<ACI> mentioned,
public static UpdateDescription mentioning(@NonNull Collection<ServiceId> mentioned,
@NonNull StringFactory stringFactory,
@DrawableRes int iconResource)
{
return new UpdateDescription(ACI.filterKnown(mentioned),
return new UpdateDescription(ServiceId.filterKnown(mentioned),
stringFactory,
null,
iconResource,
@@ -118,7 +119,7 @@ public final class UpdateDescription {
}
@AnyThread
public Collection<ACI> getMentioned() {
public Collection<ServiceId> getMentioned() {
return mentioned;
}
@@ -149,7 +150,7 @@ public final class UpdateDescription {
);
}
Set<ACI> allMentioned = new HashSet<>();
Set<ServiceId> allMentioned = new HashSet<>();
for (UpdateDescription updateDescription : updateDescriptions) {
allMentioned.addAll(updateDescription.getMentioned());