Update enum for phone number sharing mode.

This commit is contained in:
Greyson Parrelli
2023-10-20 08:20:13 -07:00
committed by Cody Henthorne
parent 6295041341
commit d866646f66
11 changed files with 90 additions and 91 deletions

View File

@@ -307,8 +307,8 @@ class ChangeNumberRepository(
return Single.fromCallable {
for (certificateType in certificateTypes) {
val certificate: ByteArray? = when (certificateType) {
CertificateType.UUID_AND_E164 -> accountManager.getSenderCertificate()
CertificateType.UUID_ONLY -> accountManager.getSenderCertificateForPhoneNumberPrivacy()
CertificateType.ACI_AND_E164 -> accountManager.getSenderCertificate()
CertificateType.ACI_ONLY -> accountManager.getSenderCertificateForPhoneNumberPrivacy()
else -> throw AssertionError()
}

View File

@@ -25,8 +25,6 @@ import org.signal.core.ui.Texts
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.compose.ComposeFragment
import org.thoughtcrime.securesms.compose.StatusBarColorNestedScrollConnection
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues.PhoneNumberListingMode
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues.PhoneNumberSharingMode
class PhoneNumberPrivacySettingsFragment : ComposeFragment() {
@@ -67,7 +65,7 @@ class PhoneNumberPrivacySettingsFragment : ComposeFragment() {
item {
Rows.RadioRow(
selected = state.seeMyPhoneNumber == PhoneNumberSharingMode.EVERYONE,
selected = state.phoneNumberSharing,
text = stringResource(id = R.string.PhoneNumberPrivacy_everyone),
modifier = Modifier.clickable(onClick = viewModel::setEveryoneCanSeeMyNumber)
)
@@ -75,7 +73,7 @@ class PhoneNumberPrivacySettingsFragment : ComposeFragment() {
item {
Rows.RadioRow(
selected = state.seeMyPhoneNumber == PhoneNumberSharingMode.NOBODY,
selected = !state.phoneNumberSharing,
text = stringResource(id = R.string.PhoneNumberPrivacy_nobody),
modifier = Modifier.clickable(onClick = viewModel::setNobodyCanSeeMyNumber)
)
@@ -84,10 +82,10 @@ class PhoneNumberPrivacySettingsFragment : ComposeFragment() {
item {
Text(
text = stringResource(
id = when (state.seeMyPhoneNumber) {
PhoneNumberSharingMode.EVERYONE -> R.string.PhoneNumberPrivacySettingsFragment__your_phone_number
PhoneNumberSharingMode.NOBODY -> R.string.PhoneNumberPrivacySettingsFragment__nobody_will_see
else -> error("Unexpected state $state")
id = if (state.phoneNumberSharing) {
R.string.PhoneNumberPrivacySettingsFragment__your_phone_number
} else {
R.string.PhoneNumberPrivacySettingsFragment__nobody_will_see
}
),
style = MaterialTheme.typography.bodyMedium,
@@ -106,16 +104,16 @@ class PhoneNumberPrivacySettingsFragment : ComposeFragment() {
item {
Rows.RadioRow(
selected = state.findMeByPhoneNumber == PhoneNumberListingMode.LISTED,
selected = state.discoverableByPhoneNumber,
text = stringResource(id = R.string.PhoneNumberPrivacy_everyone),
modifier = Modifier.clickable(onClick = viewModel::setEveryoneCanFindMeByMyNumber)
)
}
if (state.seeMyPhoneNumber == PhoneNumberSharingMode.NOBODY) {
if (!state.phoneNumberSharing) {
item {
Rows.RadioRow(
selected = state.findMeByPhoneNumber == PhoneNumberListingMode.UNLISTED,
selected = !state.discoverableByPhoneNumber,
text = stringResource(id = R.string.PhoneNumberPrivacy_nobody),
modifier = Modifier.clickable(onClick = viewModel::setNobodyCanFindMeByMyNumber)
)
@@ -125,9 +123,10 @@ class PhoneNumberPrivacySettingsFragment : ComposeFragment() {
item {
Text(
text = stringResource(
id = when (state.findMeByPhoneNumber) {
PhoneNumberListingMode.UNLISTED -> R.string.WhoCanSeeMyPhoneNumberFragment__nobody_on_signal
PhoneNumberListingMode.LISTED -> R.string.WhoCanSeeMyPhoneNumberFragment__anyone_who_has
id = if (state.discoverableByPhoneNumber) {
R.string.WhoCanSeeMyPhoneNumberFragment__anyone_who_has
} else {
R.string.WhoCanSeeMyPhoneNumberFragment__nobody_on_signal
}
),
style = MaterialTheme.typography.bodyMedium,

View File

@@ -1,8 +1,6 @@
package org.thoughtcrime.securesms.components.settings.app.privacy.pnp
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues
data class PhoneNumberPrivacySettingsState(
val seeMyPhoneNumber: PhoneNumberPrivacyValues.PhoneNumberSharingMode,
val findMeByPhoneNumber: PhoneNumberPrivacyValues.PhoneNumberListingMode
val phoneNumberSharing: Boolean,
val discoverableByPhoneNumber: Boolean
)

View File

@@ -17,39 +17,39 @@ class PhoneNumberPrivacySettingsViewModel : ViewModel() {
private val _state = mutableStateOf(
PhoneNumberPrivacySettingsState(
seeMyPhoneNumber = SignalStore.phoneNumberPrivacy().phoneNumberSharingMode,
findMeByPhoneNumber = SignalStore.phoneNumberPrivacy().phoneNumberListingMode
phoneNumberSharing = SignalStore.phoneNumberPrivacy().isPhoneNumberSharingEnabled,
discoverableByPhoneNumber = SignalStore.phoneNumberPrivacy().isDiscoverableByPhoneNumber
)
)
val state: State<PhoneNumberPrivacySettingsState> = _state
fun setNobodyCanSeeMyNumber() {
setPhoneNumberSharingMode(PhoneNumberSharingMode.NOBODY)
setPhoneNumberSharingEnabled(false)
}
fun setEveryoneCanSeeMyNumber() {
setPhoneNumberSharingMode(PhoneNumberSharingMode.EVERYONE)
setPhoneNumberListingMode(PhoneNumberListingMode.LISTED)
setPhoneNumberSharingEnabled(true)
setDiscoverableByPhoneNumber(true)
}
fun setNobodyCanFindMeByMyNumber() {
setPhoneNumberListingMode(PhoneNumberListingMode.UNLISTED)
setDiscoverableByPhoneNumber(false)
}
fun setEveryoneCanFindMeByMyNumber() {
setPhoneNumberListingMode(PhoneNumberListingMode.LISTED)
setDiscoverableByPhoneNumber(true)
}
private fun setPhoneNumberSharingMode(phoneNumberSharingMode: PhoneNumberSharingMode) {
SignalStore.phoneNumberPrivacy().phoneNumberSharingMode = phoneNumberSharingMode
private fun setPhoneNumberSharingEnabled(phoneNumberSharingEnabled: Boolean) {
SignalStore.phoneNumberPrivacy().phoneNumberSharingMode = if (phoneNumberSharingEnabled) PhoneNumberSharingMode.EVERYBODY else PhoneNumberSharingMode.NOBODY
SignalDatabase.recipients.markNeedsSync(Recipient.self().id)
StorageSyncHelper.scheduleSyncForDataChange()
refresh()
}
private fun setPhoneNumberListingMode(phoneNumberListingMode: PhoneNumberListingMode) {
SignalStore.phoneNumberPrivacy().phoneNumberListingMode = phoneNumberListingMode
private fun setDiscoverableByPhoneNumber(discoverable: Boolean) {
SignalStore.phoneNumberPrivacy().phoneNumberListingMode = if (discoverable) PhoneNumberListingMode.LISTED else PhoneNumberListingMode.UNLISTED
StorageSyncHelper.scheduleSyncForDataChange()
ApplicationDependencies.getJobManager().startChain(RefreshAttributesJob()).then(RefreshOwnProfileJob()).enqueue()
refresh()
@@ -57,8 +57,8 @@ class PhoneNumberPrivacySettingsViewModel : ViewModel() {
fun refresh() {
_state.value = PhoneNumberPrivacySettingsState(
seeMyPhoneNumber = SignalStore.phoneNumberPrivacy().phoneNumberSharingMode,
findMeByPhoneNumber = SignalStore.phoneNumberPrivacy().phoneNumberListingMode
phoneNumberSharing = SignalStore.phoneNumberPrivacy().isPhoneNumberSharingEnabled,
discoverableByPhoneNumber = SignalStore.phoneNumberPrivacy().isDiscoverableByPhoneNumber
)
}
}

View File

@@ -18,7 +18,6 @@ import org.signal.libsignal.protocol.ecc.ECPublicKey;
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.keyvalue.CertificateType;
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
@@ -93,16 +92,10 @@ public class UnidentifiedAccessUtil {
List<Optional<UnidentifiedAccessPair>> access = new ArrayList<>(recipients.size());
Map<CertificateType, Integer> typeCounts = new HashMap<>();
CertificateType certificateType = getUnidentifiedAccessCertificateType();
byte[] ourUnidentifiedAccessCertificate = SignalStore.certificateValues().getUnidentifiedAccessCertificate(certificateType);
for (Recipient recipient : recipients) {
CertificateType certificateType = getUnidentifiedAccessCertificateType(recipient);
byte[] ourUnidentifiedAccessCertificate = SignalStore.certificateValues().getUnidentifiedAccessCertificate(certificateType);
int typeCount = Util.getOrDefault(typeCounts, certificateType, 0);
typeCount++;
typeCounts.put(certificateType, typeCount);
if (ourUnidentifiedAccessCertificate != null) {
try {
UnidentifiedAccess theirAccess = getTargetUnidentifiedAccess(recipient, ourUnidentifiedAccessCertificate, isForStory);
@@ -127,7 +120,7 @@ public class UnidentifiedAccessUtil {
int otherCount = access.size() - unidentifiedCount;
if (log) {
Log.i(TAG, "Unidentified: " + unidentifiedCount + ", Other: " + otherCount + ". Types: " + typeCounts);
Log.i(TAG, "Unidentified: " + unidentifiedCount + ", Other: " + otherCount);
}
return access;
@@ -136,7 +129,7 @@ public class UnidentifiedAccessUtil {
public static Optional<UnidentifiedAccessPair> getAccessForSync(@NonNull Context context) {
try {
byte[] ourUnidentifiedAccessKey = UnidentifiedAccess.deriveAccessKeyFrom(ProfileKeyUtil.getSelfProfileKey());
byte[] ourUnidentifiedAccessCertificate = getUnidentifiedAccessCertificate(Recipient.self());
byte[] ourUnidentifiedAccessCertificate = getUnidentifiedAccessCertificate();
if (TextSecurePreferences.isUniversalUnidentifiedAccess(context)) {
ourUnidentifiedAccessKey = UNRESTRICTED_KEY;
@@ -158,20 +151,17 @@ public class UnidentifiedAccessUtil {
}
}
private static @NonNull CertificateType getUnidentifiedAccessCertificateType(@NonNull Recipient recipient) {
PhoneNumberPrivacyValues.PhoneNumberSharingMode sendPhoneNumberTo = SignalStore.phoneNumberPrivacy().getPhoneNumberSharingMode();
switch (sendPhoneNumberTo) {
case EVERYONE: return CertificateType.UUID_AND_E164;
case CONTACTS: return recipient.isSystemContact() ? CertificateType.UUID_AND_E164 : CertificateType.UUID_ONLY;
case NOBODY : return CertificateType.UUID_ONLY;
default : throw new AssertionError();
private static @NonNull CertificateType getUnidentifiedAccessCertificateType() {
if (SignalStore.phoneNumberPrivacy().isPhoneNumberSharingEnabled()) {
return CertificateType.ACI_AND_E164;
} else {
return CertificateType.ACI_ONLY;
}
}
private static byte[] getUnidentifiedAccessCertificate(@NonNull Recipient recipient) {
private static byte[] getUnidentifiedAccessCertificate() {
return SignalStore.certificateValues()
.getUnidentifiedAccessCertificate(getUnidentifiedAccessCertificateType(recipient));
.getUnidentifiedAccessCertificate(getUnidentifiedAccessCertificateType());
}
private static @Nullable UnidentifiedAccess getTargetUnidentifiedAccess(@NonNull Recipient recipient, @NonNull byte[] certificate, boolean isForStory) throws InvalidCertificateException {

View File

@@ -66,9 +66,9 @@ public final class RotateCertificateJob extends BaseJob {
byte[] certificate;
switch (certificateType) {
case UUID_AND_E164: certificate = accountManager.getSenderCertificate(); break;
case UUID_ONLY : certificate = accountManager.getSenderCertificateForPhoneNumberPrivacy(); break;
default : throw new AssertionError();
case ACI_AND_E164: certificate = accountManager.getSenderCertificate(); break;
case ACI_ONLY : certificate = accountManager.getSenderCertificateForPhoneNumberPrivacy(); break;
default : throw new AssertionError();
}
Log.i(TAG, String.format("Successfully got %s certificate", certificateType));

View File

@@ -1,6 +1,6 @@
package org.thoughtcrime.securesms.keyvalue;
public enum CertificateType {
UUID_AND_E164,
UUID_ONLY
ACI_AND_E164,
ACI_ONLY
}

View File

@@ -9,8 +9,8 @@ import java.util.List;
public final class CertificateValues extends SignalStoreValues {
private static final String UD_CERTIFICATE_UUID_AND_E164 = "certificate.uuidAndE164";
private static final String UD_CERTIFICATE_UUID_ONLY = "certificate.uuidOnly";
private static final String SEALED_SENDER_CERT_ACI_AND_E164 = "certificate.uuidAndE164";
private static final String SEALED_SENDER_CERT_ACI_ONLY = "certificate.uuidOnly";
CertificateValues(@NonNull KeyValueStore store) {
super(store);
@@ -32,9 +32,9 @@ public final class CertificateValues extends SignalStoreValues {
KeyValueStore.Writer writer = getStore().beginWrite();
switch (certificateType) {
case UUID_AND_E164: writer.putBlob(UD_CERTIFICATE_UUID_AND_E164, certificate); break;
case UUID_ONLY : writer.putBlob(UD_CERTIFICATE_UUID_ONLY, certificate); break;
default : throw new AssertionError();
case ACI_AND_E164: writer.putBlob(SEALED_SENDER_CERT_ACI_AND_E164, certificate); break;
case ACI_ONLY : writer.putBlob(SEALED_SENDER_CERT_ACI_ONLY, certificate); break;
default : throw new AssertionError();
}
writer.commit();
@@ -42,9 +42,9 @@ public final class CertificateValues extends SignalStoreValues {
public @Nullable byte[] getUnidentifiedAccessCertificate(@NonNull CertificateType certificateType) {
switch (certificateType) {
case UUID_AND_E164: return getBlob(UD_CERTIFICATE_UUID_AND_E164, null);
case UUID_ONLY : return getBlob(UD_CERTIFICATE_UUID_ONLY, null);
default : throw new AssertionError();
case ACI_AND_E164: return getBlob(SEALED_SENDER_CERT_ACI_AND_E164, null);
case ACI_ONLY : return getBlob(SEALED_SENDER_CERT_ACI_ONLY, null);
default : throw new AssertionError();
}
}

View File

@@ -2,8 +2,6 @@ package org.thoughtcrime.securesms.keyvalue;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.util.FeatureFlags;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -15,9 +13,9 @@ public final class PhoneNumberPrivacyValues extends SignalStoreValues {
public static final String LISTING_MODE = "phoneNumberPrivacy.listingMode";
public static final String LISTING_TIMESTAMP = "phoneNumberPrivacy.listingMode.timestamp";
private static final Collection<CertificateType> REGULAR_CERTIFICATE = Collections.singletonList(CertificateType.UUID_AND_E164);
private static final Collection<CertificateType> PRIVACY_CERTIFICATE = Collections.singletonList(CertificateType.UUID_ONLY);
private static final Collection<CertificateType> BOTH_CERTIFICATES = Collections.unmodifiableCollection(Arrays.asList(CertificateType.UUID_AND_E164, CertificateType.UUID_ONLY));
private static final Collection<CertificateType> ACI_AND_E164_CERTIFICATE = Collections.singletonList(CertificateType.ACI_AND_E164);
private static final Collection<CertificateType> ACI_ONLY_CERTIFICATE = Collections.singletonList(CertificateType.ACI_ONLY);
private static final Collection<CertificateType> BOTH_CERTIFICATES = Collections.unmodifiableCollection(Arrays.asList(CertificateType.ACI_AND_E164, CertificateType.ACI_ONLY));
PhoneNumberPrivacyValues(@NonNull KeyValueStore store) {
super(store);
@@ -36,14 +34,30 @@ public final class PhoneNumberPrivacyValues extends SignalStoreValues {
return Arrays.asList(SHARING_MODE, LISTING_MODE, LISTING_TIMESTAMP);
}
/**
* Note: Only giving raw access to the underlying value for storage service.
* Most callers should use {@link #isPhoneNumberSharingEnabled()}.
*/
public @NonNull PhoneNumberSharingMode getPhoneNumberSharingMode() {
return PhoneNumberSharingMode.deserialize(getInteger(SHARING_MODE, PhoneNumberSharingMode.EVERYONE.serialize()));
return PhoneNumberSharingMode.deserialize(getInteger(SHARING_MODE, PhoneNumberSharingMode.DEFAULT.serialize()));
}
public boolean isPhoneNumberSharingEnabled() {
// TODO [pnp] When we launch usernames, the default should return false
return switch (getPhoneNumberSharingMode()) {
case DEFAULT, EVERYBODY -> true;
case NOBODY -> false;
};
}
public void setPhoneNumberSharingMode(@NonNull PhoneNumberSharingMode phoneNumberSharingMode) {
putInteger(SHARING_MODE, phoneNumberSharingMode.serialize());
}
public boolean isDiscoverableByPhoneNumber() {
return getPhoneNumberListingMode() == PhoneNumberPrivacyValues.PhoneNumberListingMode.LISTED;
}
public @NonNull PhoneNumberListingMode getPhoneNumberListingMode() {
return PhoneNumberListingMode.deserialize(getInteger(LISTING_MODE, PhoneNumberListingMode.LISTED.serialize()));
}
@@ -65,11 +79,10 @@ public final class PhoneNumberPrivacyValues extends SignalStoreValues {
* these certificates types.
*/
public Collection<CertificateType> getRequiredCertificateTypes() {
switch (getPhoneNumberSharingMode()) {
case EVERYONE: return REGULAR_CERTIFICATE;
case CONTACTS: return BOTH_CERTIFICATES;
case NOBODY : return PRIVACY_CERTIFICATE;
default : throw new AssertionError();
if (isPhoneNumberSharingEnabled()) {
return ACI_AND_E164_CERTIFICATE;
} else {
return ACI_ONLY_CERTIFICATE;
}
}
@@ -81,8 +94,8 @@ public final class PhoneNumberPrivacyValues extends SignalStoreValues {
}
public enum PhoneNumberSharingMode {
EVERYONE(0),
CONTACTS(1),
DEFAULT(0),
EVERYBODY(1),
NOBODY(2);
private final int code;

View File

@@ -18,7 +18,6 @@ import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.subscription.Subscriber;
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
@@ -66,20 +65,20 @@ public final class StorageSyncModels {
}
public static AccountRecord.PhoneNumberSharingMode localToRemotePhoneNumberSharingMode(PhoneNumberPrivacyValues.PhoneNumberSharingMode phoneNumberPhoneNumberSharingMode) {
// TODO [pnp] When we launch usernames, we want DEFAULT to map to NOBODY. In fact, we can just pass a boolean into this function instead of an enum.
switch (phoneNumberPhoneNumberSharingMode) {
case EVERYONE: return AccountRecord.PhoneNumberSharingMode.EVERYBODY;
case CONTACTS: return AccountRecord.PhoneNumberSharingMode.CONTACTS_ONLY;
case NOBODY : return AccountRecord.PhoneNumberSharingMode.NOBODY;
default : throw new AssertionError();
case DEFAULT : return AccountRecord.PhoneNumberSharingMode.UNKNOWN;
case EVERYBODY: return AccountRecord.PhoneNumberSharingMode.EVERYBODY;
case NOBODY : return AccountRecord.PhoneNumberSharingMode.NOBODY;
default : throw new AssertionError();
}
}
public static PhoneNumberPrivacyValues.PhoneNumberSharingMode remoteToLocalPhoneNumberSharingMode(AccountRecord.PhoneNumberSharingMode phoneNumberPhoneNumberSharingMode) {
switch (phoneNumberPhoneNumberSharingMode) {
case EVERYBODY : return PhoneNumberPrivacyValues.PhoneNumberSharingMode.EVERYONE;
case CONTACTS_ONLY: return PhoneNumberPrivacyValues.PhoneNumberSharingMode.CONTACTS;
case EVERYBODY : return PhoneNumberPrivacyValues.PhoneNumberSharingMode.EVERYBODY;
case NOBODY : return PhoneNumberPrivacyValues.PhoneNumberSharingMode.NOBODY;
default : return PhoneNumberPrivacyValues.PhoneNumberSharingMode.CONTACTS;
default : return PhoneNumberPrivacyValues.PhoneNumberSharingMode.DEFAULT;
}
}

View File

@@ -138,9 +138,9 @@ message Payments {
message AccountRecord {
enum PhoneNumberSharingMode {
EVERYBODY = 0;
CONTACTS_ONLY = 1;
NOBODY = 2;
UNKNOWN = 0;
EVERYBODY = 1;
NOBODY = 2;
}
message PinnedConversation {