Add payment activation capability.

main
Cody Henthorne 2022-12-21 10:01:20 -05:00 zatwierdzone przez Greyson Parrelli
rodzic 96b2051400
commit a13599ae2a
15 zmienionych plików z 137 dodań i 267 usunięć

Wyświetl plik

@ -418,8 +418,8 @@ class RecipientTableTest_getAndPossiblyMerge {
SignalDatabase.sessions.store(ACI_SELF, SignalProtocolAddress(ACI_A.toString(), 1), SessionRecord())
SignalDatabase.reactions.addReaction(MessageId(smsId1, false), ReactionRecord("a", recipientIdAci, 1, 1))
SignalDatabase.reactions.addReaction(MessageId(mmsId1, true), ReactionRecord("b", recipientIdE164, 1, 1))
SignalDatabase.reactions.addReaction(MessageId(smsId1), ReactionRecord("a", recipientIdAci, 1, 1))
SignalDatabase.reactions.addReaction(MessageId(mmsId1), ReactionRecord("b", recipientIdE164, 1, 1))
val profile1: NotificationProfile = notificationProfile(name = "Test")
val profile2: NotificationProfile = notificationProfile(name = "Test2")
@ -497,8 +497,8 @@ class RecipientTableTest_getAndPossiblyMerge {
Assert.assertNotNull(SignalDatabase.sessions.load(ACI_SELF, SignalProtocolAddress(ACI_A.toString(), 1)))
// Reaction validation
val reactionsSms: List<ReactionRecord> = SignalDatabase.reactions.getReactions(MessageId(smsId1, false))
val reactionsMms: List<ReactionRecord> = SignalDatabase.reactions.getReactions(MessageId(mmsId1, true))
val reactionsSms: List<ReactionRecord> = SignalDatabase.reactions.getReactions(MessageId(smsId1))
val reactionsMms: List<ReactionRecord> = SignalDatabase.reactions.getReactions(MessageId(mmsId1))
assertEquals(1, reactionsSms.size)
assertEquals(ReactionRecord("a", recipientIdAci, 1, 1), reactionsSms[0])

Wyświetl plik

@ -108,7 +108,7 @@ class SignalActivityRule(private val othersCount: Int = 4) : ExternalResource()
val recipientId = RecipientId.from(SignalServiceAddress(aci, "+15555551%03d".format(i)))
SignalDatabase.recipients.setProfileName(recipientId, ProfileName.fromParts("Buddy", "#$i"))
SignalDatabase.recipients.setProfileKeyIfAbsent(recipientId, ProfileKeyUtil.createNew())
SignalDatabase.recipients.setCapabilities(recipientId, SignalServiceProfile.Capabilities(true, true, true, true, true, true, true, true))
SignalDatabase.recipients.setCapabilities(recipientId, SignalServiceProfile.Capabilities(true, true, true, true, true, true, true, true, true))
SignalDatabase.recipients.setProfileSharing(recipientId, true)
SignalDatabase.recipients.markRegistered(recipientId, aci)
ApplicationDependencies.getProtocolStore().aci().saveIdentity(SignalProtocolAddress(aci.toString(), 0), IdentityKeyUtil.generateIdentityKeyPair().publicKey)

Wyświetl plik

@ -1,28 +0,0 @@
package org.thoughtcrime.securesms;
import org.thoughtcrime.securesms.stories.Stories;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.whispersystems.signalservice.api.account.AccountAttributes;
public final class AppCapabilities {
private AppCapabilities() {
}
private static final boolean UUID_CAPABLE = false;
private static final boolean GV2_CAPABLE = true;
private static final boolean GV1_MIGRATION = true;
private static final boolean ANNOUNCEMENT_GROUPS = true;
private static final boolean SENDER_KEY = true;
private static final boolean CHANGE_NUMBER = true;
private static final boolean STORIES = true;
private static final boolean GIFT_BADGES = true;
/**
* @param storageCapable Whether or not the user can use storage service. This is another way of
* asking if the user has set a Signal PIN or not.
*/
public static AccountAttributes.Capabilities getCapabilities(boolean storageCapable) {
return new AccountAttributes.Capabilities(UUID_CAPABLE, GV2_CAPABLE, storageCapable, GV1_MIGRATION, SENDER_KEY, ANNOUNCEMENT_GROUPS, CHANGE_NUMBER, STORIES, GIFT_BADGES, FeatureFlags.phoneNumberPrivacy());
}
}

Wyświetl plik

@ -0,0 +1,27 @@
package org.thoughtcrime.securesms
import org.thoughtcrime.securesms.util.FeatureFlags
import org.whispersystems.signalservice.api.account.AccountAttributes
object AppCapabilities {
/**
* @param storageCapable Whether or not the user can use storage service. This is another way of
* asking if the user has set a Signal PIN or not.
*/
@JvmStatic
fun getCapabilities(storageCapable: Boolean): AccountAttributes.Capabilities {
return AccountAttributes.Capabilities(
isUuid = false,
isGv2 = true,
isStorage = storageCapable,
isGv1Migration = true,
isSenderKey = true,
isAnnouncementGroup = true,
isChangeNumber = true,
isStories = true,
isGiftBadges = true,
isPnp = FeatureFlags.phoneNumberPrivacy(),
paymentActivation = true
)
}
}

Wyświetl plik

@ -1552,6 +1552,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
value = Bitmask.update(value, Capabilities.STORIES, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isStories).serialize().toLong())
value = Bitmask.update(value, Capabilities.GIFT_BADGES, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isGiftBadges).serialize().toLong())
value = Bitmask.update(value, Capabilities.PNP, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isPnp).serialize().toLong())
value = Bitmask.update(value, Capabilities.PAYMENT_ACTIVATION, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isPaymentActivation).serialize().toLong())
val values = ContentValues(1).apply {
put(CAPABILITIES, value)
@ -3919,6 +3920,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
storiesCapability = Recipient.Capability.deserialize(Bitmask.read(capabilities, Capabilities.STORIES, Capabilities.BIT_LENGTH).toInt()),
giftBadgesCapability = Recipient.Capability.deserialize(Bitmask.read(capabilities, Capabilities.GIFT_BADGES, Capabilities.BIT_LENGTH).toInt()),
pnpCapability = Recipient.Capability.deserialize(Bitmask.read(capabilities, Capabilities.PNP, Capabilities.BIT_LENGTH).toInt()),
paymentActivation = Recipient.Capability.deserialize(Bitmask.read(capabilities, Capabilities.PAYMENT_ACTIVATION, Capabilities.BIT_LENGTH).toInt()),
)
}
@ -4240,6 +4242,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
const val STORIES = 5
const val GIFT_BADGES = 6
const val PNP = 7
const val PAYMENT_ACTIVATION = 8
}
enum class VibrateState(val id: Int) {

Wyświetl plik

@ -125,6 +125,7 @@ data class RecipientRecord(
val storiesCapability: Recipient.Capability,
val giftBadgesCapability: Recipient.Capability,
val pnpCapability: Recipient.Capability,
val paymentActivation: Recipient.Capability
) {
companion object {
@JvmField
@ -136,6 +137,7 @@ data class RecipientRecord(
Recipient.Capability.UNKNOWN,
Recipient.Capability.UNKNOWN,
Recipient.Capability.UNKNOWN,
Recipient.Capability.UNKNOWN,
Recipient.Capability.UNKNOWN
)
}

Wyświetl plik

@ -108,17 +108,7 @@ public class RefreshAttributesJob extends BaseJob {
Log.i(TAG, "Calling setAccountAttributes() reglockV1? " + !TextUtils.isEmpty(registrationLockV1) + ", reglockV2? " + !TextUtils.isEmpty(registrationLockV2) + ", pin? " + kbsValues.hasPin() +
"\n Phone number discoverable : " + phoneNumberDiscoverable +
"\n Device Name : " + (encryptedDeviceName != null) +
"\n Capabilities:" +
"\n Storage? " + capabilities.isStorage() +
"\n GV2? " + capabilities.isGv2() +
"\n GV1 Migration? " + capabilities.isGv1Migration() +
"\n Sender Key? " + capabilities.isSenderKey() +
"\n Announcement Groups? " + capabilities.isAnnouncementGroup() +
"\n Change Number? " + capabilities.isChangeNumber() +
"\n Stories? " + capabilities.isStories() +
"\n Gift Badges? " + capabilities.isGiftBadges() +
"\n PNP? " + capabilities.isPnp() +
"\n UUID? " + capabilities.isUuid());
"\n Capabilities: " + capabilities);
SignalServiceAccountManager signalAccountManager = ApplicationDependencies.getSignalServiceAccountManager();
signalAccountManager.setAccountAttributes(null,

Wyświetl plik

@ -450,7 +450,7 @@ public class AttachmentManager {
intent.putExtra(PaymentsActivity.EXTRA_PAYMENTS_STARTING_ACTION, R.id.action_directly_to_createPayment);
intent.putExtra(PaymentsActivity.EXTRA_STARTING_ARGUMENTS, new CreatePaymentFragmentArgs.Builder(new PayeeParcelable(recipient.getId())).setFinishOnConfirm(true).build().toBundle());
fragment.startActivity(intent);
} else if (FeatureFlags.paymentsRequestActivateFlow()) {
} else if (FeatureFlags.paymentsRequestActivateFlow() && recipient.getPaymentActivationCapability().isSupported()) {
showRequestToActivatePayments(fragment.requireContext(), recipient);
} else {
RecipientHasNotEnabledPaymentsDialog.show(fragment.requireContext());

Wyświetl plik

@ -1024,6 +1024,10 @@ public class Recipient {
return capabilities.getPnpCapability();
}
public @NonNull Capability getPaymentActivationCapability() {
return capabilities.getPaymentActivation();
}
public @Nullable byte[] getProfileKey() {
return profileKey;
}
@ -1213,6 +1217,10 @@ public class Recipient {
return value;
}
public boolean isSupported() {
return this == SUPPORTED;
}
public static Capability deserialize(int value) {
switch (value) {
case 0: return UNKNOWN;

Wyświetl plik

@ -136,6 +136,7 @@ object RecipientDatabaseTestUtils {
Recipient.Capability.deserialize(Bitmask.read(capabilities, RecipientTable.Capabilities.STORIES, RecipientTable.Capabilities.BIT_LENGTH).toInt()),
Recipient.Capability.deserialize(Bitmask.read(capabilities, RecipientTable.Capabilities.GIFT_BADGES, RecipientTable.Capabilities.BIT_LENGTH).toInt()),
Recipient.Capability.deserialize(Bitmask.read(capabilities, RecipientTable.Capabilities.PNP, RecipientTable.Capabilities.BIT_LENGTH).toInt()),
Recipient.Capability.deserialize(Bitmask.read(capabilities, RecipientTable.Capabilities.PAYMENT_ACTIVATION, RecipientTable.Capabilities.BIT_LENGTH).toInt()),
),
insightBannerTier,
storageId,

Wyświetl plik

@ -3692,6 +3692,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="59c57ab609494d2a30d6ea3737428a56918ff0b8031081ea73b8472fdec06e44" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-reflect" version="1.4.10">
<artifact name="kotlin-reflect-1.4.10.jar">
<sha256 value="3ab3413ec945f801448360ad97bc6e14fec6d606889ede3c707cc277b4467f45" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-reflect" version="1.4.32">
<artifact name="kotlin-reflect-1.4.32.jar">
<sha256 value="dbf19e9cdaa9c3c170f3f6f6ce3922f38dfc1d7fa1cab5b7c23a19da8b5eec5b" origin="Generated by Gradle"/>
@ -3792,6 +3797,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="5ace22b102a96425e4ac44e0558b927f3857b56a33cbc289cf1b70aee645e6a7" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.4.10">
<artifact name="kotlin-stdlib-1.4.10.jar">
<sha256 value="01ecb09782c042b931c1839acf21a188340b295d05400afd6e3415d4475b8daa" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.4.20">
<artifact name="kotlin-stdlib-1.4.20.jar">
<sha256 value="b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656" origin="Generated by Gradle"/>

Wyświetl plik

@ -35,6 +35,7 @@ dependencies {
implementation libs.google.protobuf.javalite
api libs.google.libphonenumber
api libs.jackson.core
api libs.jackson.module.kotlin
implementation libs.libsignal.client
api libs.square.okhttp3

Wyświetl plik

@ -1,221 +0,0 @@
/*
* Copyright (C) 2014-2016 Open Whisper Systems
*
* Licensed according to the LICENSE file in this repository.
*/
package org.whispersystems.signalservice.api.account;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class AccountAttributes {
@JsonProperty
private String signalingKey;
@JsonProperty
private int registrationId;
@JsonProperty
private boolean voice;
@JsonProperty
private boolean video;
@JsonProperty
private boolean fetchesMessages;
@JsonProperty
private String pin;
@JsonProperty
private String registrationLock;
@JsonProperty
private byte[] unidentifiedAccessKey;
@JsonProperty
private boolean unrestrictedUnidentifiedAccess;
@JsonProperty
private boolean discoverableByPhoneNumber;
@JsonProperty
private Capabilities capabilities;
@JsonProperty
private String name;
@JsonProperty
private int pniRegistrationId;
public AccountAttributes(String signalingKey,
int registrationId,
boolean fetchesMessages,
String pin,
String registrationLock,
byte[] unidentifiedAccessKey,
boolean unrestrictedUnidentifiedAccess,
Capabilities capabilities,
boolean discoverableByPhoneNumber,
String name,
int pniRegistrationId)
{
this.signalingKey = signalingKey;
this.registrationId = registrationId;
this.voice = true;
this.video = true;
this.fetchesMessages = fetchesMessages;
this.pin = pin;
this.registrationLock = registrationLock;
this.unidentifiedAccessKey = unidentifiedAccessKey;
this.unrestrictedUnidentifiedAccess = unrestrictedUnidentifiedAccess;
this.capabilities = capabilities;
this.discoverableByPhoneNumber = discoverableByPhoneNumber;
this.name = name;
this.pniRegistrationId = pniRegistrationId;
}
public AccountAttributes() {}
public String getSignalingKey() {
return signalingKey;
}
public int getRegistrationId() {
return registrationId;
}
public boolean isVoice() {
return voice;
}
public boolean isVideo() {
return video;
}
public boolean isFetchesMessages() {
return fetchesMessages;
}
public String getPin() {
return pin;
}
public String getRegistrationLock() {
return registrationLock;
}
public byte[] getUnidentifiedAccessKey() {
return unidentifiedAccessKey;
}
public boolean isUnrestrictedUnidentifiedAccess() {
return unrestrictedUnidentifiedAccess;
}
public boolean isDiscoverableByPhoneNumber() {
return discoverableByPhoneNumber;
}
public Capabilities getCapabilities() {
return capabilities;
}
public String getName() {
return name;
}
public int getPniRegistrationId() {
return pniRegistrationId;
}
public static class Capabilities {
@JsonProperty
private boolean uuid;
@JsonProperty("gv2-3")
private boolean gv2;
@JsonProperty
private boolean storage;
@JsonProperty("gv1-migration")
private boolean gv1Migration;
@JsonProperty
private boolean senderKey;
@JsonProperty
private boolean announcementGroup;
@JsonProperty
private boolean changeNumber;
@JsonProperty
private boolean stories;
@JsonProperty
private boolean giftBadges;
@JsonProperty
private boolean pni;
@JsonCreator
public Capabilities() {}
public Capabilities(boolean uuid, boolean gv2, boolean storage, boolean gv1Migration, boolean senderKey, boolean announcementGroup, boolean changeNumber, boolean stories, boolean giftBadges, boolean pni) {
this.uuid = uuid;
this.gv2 = gv2;
this.storage = storage;
this.gv1Migration = gv1Migration;
this.senderKey = senderKey;
this.announcementGroup = announcementGroup;
this.changeNumber = changeNumber;
this.stories = stories;
this.giftBadges = giftBadges;
this.pni = pni;
}
public boolean isUuid() {
return uuid;
}
public boolean isGv2() {
return gv2;
}
public boolean isStorage() {
return storage;
}
public boolean isGv1Migration() {
return gv1Migration;
}
public boolean isSenderKey() {
return senderKey;
}
public boolean isAnnouncementGroup() {
return announcementGroup;
}
public boolean isChangeNumber() {
return changeNumber;
}
public boolean isStories() {
return stories;
}
public boolean isGiftBadges() {
return giftBadges;
}
public boolean isPnp() {
return pni;
}
}
}

Wyświetl plik

@ -0,0 +1,69 @@
/*
* Copyright (C) 2014-2016 Open Whisper Systems
*
* Licensed according to the LICENSE file in this repository.
*/
package org.whispersystems.signalservice.api.account
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import com.fasterxml.jackson.annotation.JsonProperty
@JsonIgnoreProperties(ignoreUnknown = true)
class AccountAttributes @JsonCreator constructor(
@JsonProperty val signalingKey: String?,
@JsonProperty val registrationId: Int,
@JsonProperty val isVoice: Boolean,
@JsonProperty val isVideo: Boolean,
@JsonProperty val isFetchesMessages: Boolean,
@JsonProperty val pin: String?,
@JsonProperty val registrationLock: String?,
@JsonProperty val unidentifiedAccessKey: ByteArray?,
@JsonProperty val isUnrestrictedUnidentifiedAccess: Boolean,
@JsonProperty val isDiscoverableByPhoneNumber: Boolean,
@JsonProperty val capabilities: Capabilities?,
@JsonProperty val name: String?,
@JsonProperty val pniRegistrationId: Int,
) {
constructor(
signalingKey: String?,
registrationId: Int,
isFetchesMessages: Boolean,
pin: String?,
registrationLock: String?,
unidentifiedAccessKey: ByteArray?,
isUnrestrictedUnidentifiedAccess: Boolean,
capabilities: Capabilities?,
isDiscoverableByPhoneNumber: Boolean,
name: String?,
pniRegistrationId: Int
) : this(
signalingKey = signalingKey,
registrationId = registrationId,
isVoice = true,
isVideo = true,
isFetchesMessages = isFetchesMessages,
pin = pin,
registrationLock = registrationLock,
unidentifiedAccessKey = unidentifiedAccessKey,
isUnrestrictedUnidentifiedAccess = isUnrestrictedUnidentifiedAccess,
isDiscoverableByPhoneNumber = isDiscoverableByPhoneNumber,
capabilities = capabilities,
name = name,
pniRegistrationId = pniRegistrationId
)
data class Capabilities @JsonCreator constructor(
@JsonProperty val isUuid: Boolean,
@JsonProperty("gv2-3") val isGv2: Boolean,
@JsonProperty val isStorage: Boolean,
@JsonProperty("gv1-migration") val isGv1Migration: Boolean,
@JsonProperty val isSenderKey: Boolean,
@JsonProperty val isAnnouncementGroup: Boolean,
@JsonProperty val isChangeNumber: Boolean,
@JsonProperty val isStories: Boolean,
@JsonProperty val isGiftBadges: Boolean,
@JsonProperty val isPnp: Boolean,
@JsonProperty val paymentActivation: Boolean
)
}

Wyświetl plik

@ -206,10 +206,13 @@ public class SignalServiceProfile {
@JsonProperty
private boolean pnp;
@JsonProperty
private boolean paymentActivation;
@JsonCreator
public Capabilities() {}
public Capabilities(boolean storage, boolean gv1Migration, boolean senderKey, boolean announcementGroup, boolean changeNumber, boolean stories, boolean giftBadges, boolean pnp) {
public Capabilities(boolean storage, boolean gv1Migration, boolean senderKey, boolean announcementGroup, boolean changeNumber, boolean stories, boolean giftBadges, boolean pnp, boolean paymentActivation) {
this.storage = storage;
this.gv1Migration = gv1Migration;
this.senderKey = senderKey;
@ -218,6 +221,7 @@ public class SignalServiceProfile {
this.stories = stories;
this.giftBadges = giftBadges;
this.pnp = pnp;
this.paymentActivation = paymentActivation;
}
public boolean isStorage() {
@ -251,6 +255,10 @@ public class SignalServiceProfile {
public boolean isPnp() {
return pnp;
}
public boolean isPaymentActivation() {
return paymentActivation;
}
}
public ExpiringProfileKeyCredentialResponse getExpiringProfileKeyCredentialResponse() {