Update MobileCoin Payments Beta country codes.

fork-5.53.8
Alex Hart 2021-11-12 14:53:35 -04:00 zatwierdzone przez GitHub
rodzic 51c86cab10
commit 0cb53f40f4
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
5 zmienionych plików z 211 dodań i 37 usunięć

Wyświetl plik

@ -171,7 +171,7 @@ android {
buildConfigField "String[]", "LANGUAGES", "new String[]{\"" + autoResConfig().collect { s -> s.replace('-r', '_') }.join('", "') + '"}'
buildConfigField "int", "CANONICAL_VERSION_CODE", "$canonicalVersionCode"
buildConfigField "String", "DEFAULT_CURRENCIES", "\"EUR,AUD,GBP,CAD,CNY\""
buildConfigField "int[]", "MOBILE_COIN_BLACKLIST", "new int[]{98,963,53,850,7}"
buildConfigField "int[]", "MOBILE_COIN_REGIONS", "new int[]{44,49,33,41}"
buildConfigField "String", "GIPHY_API_KEY", "\"3o6ZsYH6U6Eri53TXy\""
buildConfigField "String", "RECAPTCHA_PROOF_URL", "\"https://signalcaptchas.org/challenge/generate.html\""

Wyświetl plik

@ -108,15 +108,15 @@ public final class PaymentsValues extends SignalStoreValues {
public PaymentsAvailability getPaymentsAvailability() {
Context context = ApplicationDependencies.getApplication();
if (!TextSecurePreferences.isPushRegistered(context) ||
!GeographicalRestrictions.e164Allowed(TextSecurePreferences.getLocalNumber(context)))
{
if (!TextSecurePreferences.isPushRegistered(context)) {
return PaymentsAvailability.NOT_IN_REGION;
}
if (FeatureFlags.payments()) {
if (mobileCoinPaymentsEnabled()) {
return PaymentsAvailability.WITHDRAW_AND_SEND;
} else if (!GeographicalRestrictions.e164Allowed(TextSecurePreferences.getLocalNumber(context))) {
return PaymentsAvailability.NOT_IN_REGION;
} else {
return PaymentsAvailability.REGISTRATION_AVAILABLE;
}

Wyświetl plik

@ -1,49 +1,185 @@
package org.thoughtcrime.securesms.payments;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
import org.signal.core.util.MapUtil;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.Util;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import io.reactivex.rxjava3.annotations.NonNull;
public final class GeographicalRestrictions {
private static final String TAG = Log.tag(GeographicalRestrictions.class);
private GeographicalRestrictions() {}
private static final Validator BUILD_CONFIG_VALIDATOR = new BuildConfigWhitelistValidator();
private static final Set<Integer> BLACKLIST;
static {
Set<Integer> set = new HashSet<>(BuildConfig.MOBILE_COIN_BLACKLIST.length);
for (int i = 0; i < BuildConfig.MOBILE_COIN_BLACKLIST.length; i++) {
set.add(BuildConfig.MOBILE_COIN_BLACKLIST[i]);
}
BLACKLIST = Collections.unmodifiableSet(set);
}
public static boolean regionAllowed(int regionCode) {
return !BLACKLIST.contains(regionCode);
private GeographicalRestrictions() {
}
public static boolean e164Allowed(@Nullable String e164) {
try {
int countryCode = PhoneNumberUtil.getInstance()
.parse(e164, null)
.getCountryCode();
return selectValidator(FeatureFlags.mobileCoinBlacklist()).e164Allowed(e164);
}
return GeographicalRestrictions.regionAllowed(countryCode);
} catch (NumberParseException e) {
Log.w(TAG, e);
return false;
@VisibleForTesting
static boolean e164Allowed(@Nullable String e164, @Nullable String featureFlagBlacklist) {
return selectValidator(featureFlagBlacklist).e164Allowed(e164);
}
public static @NonNull Validator selectValidator(@Nullable String featureFlagBlacklist) {
String[] blacklist = parseBlacklist(featureFlagBlacklist);
if (blacklist == null || blacklist.length == 0) {
return BUILD_CONFIG_VALIDATOR;
} else {
return new FeatureFlagBlacklistValidator(blacklist);
}
}
public static @Nullable String[] parseBlacklist(@Nullable String featureFlagBlacklist) {
if (Util.isEmpty(featureFlagBlacklist)) {
return null;
}
String[] parts = featureFlagBlacklist.split(",");
if (parts.length == 0) {
return null;
}
return parts;
}
private static class FeatureFlagBlacklistValidator implements Validator {
private final Set<Integer> blacklistCountries;
private final Map<Integer, Set<Integer>> blacklistRegions;
private FeatureFlagBlacklistValidator(@NonNull String[] blacklist) {
Set<Integer> countries = new HashSet<>(blacklist.length);
Map<Integer, Set<Integer>> regions = new HashMap<>();
for (final String entry : blacklist) {
try {
String[] parts = entry.trim().split(" ");
Integer countryCode = Integer.parseInt(parts[0].trim());
if (parts.length == 1) {
countries.add(countryCode);
} else if (parts.length == 2) {
Integer regionCode = Integer.parseInt(parts[1].trim());
Set<Integer> regionsForCountry = MapUtil.getOrDefault(regions, countryCode, new HashSet<>());
regionsForCountry.add(regionCode);
regions.put(countryCode, regionsForCountry);
} else {
Log.w(TAG, "Bad entry: " + entry.trim());
}
} catch (NumberFormatException e) {
Log.w(TAG, "Failure parsing part", e);
}
}
for (final Integer countryCode : regions.keySet()) {
Set<Integer> regionCodes = regions.get(countryCode);
if (regionCodes != null) {
regions.put(countryCode, Collections.unmodifiableSet(regionCodes));
}
}
blacklistCountries = Collections.unmodifiableSet(countries);
blacklistRegions = Collections.unmodifiableMap(regions);
}
@Override
public boolean e164Allowed(@Nullable String e164) {
try {
Phonenumber.PhoneNumber phoneNumber = PhoneNumberUtil.getInstance().parse(e164, null);
int countryCode = phoneNumber.getCountryCode();
if (blacklistCountries.contains(countryCode)) {
return false;
}
if (blacklistRegions.containsKey(countryCode)) {
Set<Integer> regionsInCountry = blacklistRegions.get(countryCode);
if (regionsInCountry == null) {
return true;
}
int nationalDestinationCodeLength = PhoneNumberUtil.getInstance().getLengthOfNationalDestinationCode(phoneNumber);
if (nationalDestinationCodeLength > 0) {
String nationalSignificantNumber = PhoneNumberUtil.getInstance().getNationalSignificantNumber(phoneNumber);
int nationalDestinationCode = Integer.parseInt(nationalSignificantNumber.substring(0, nationalDestinationCodeLength));
if (regionsInCountry.contains(nationalDestinationCode)) {
return false;
}
}
int areaCodeLength = PhoneNumberUtil.getInstance().getLengthOfGeographicalAreaCode(phoneNumber);
if (areaCodeLength > 0) {
String nationalSignificantNumber = PhoneNumberUtil.getInstance().getNationalSignificantNumber(phoneNumber);
int areaCode = Integer.parseInt(nationalSignificantNumber.substring(0, areaCodeLength));
if (regionsInCountry.contains(areaCode)) {
return false;
}
}
}
return true;
} catch (NumberParseException e) {
Log.w(TAG, e);
return false;
}
}
}
private static class BuildConfigWhitelistValidator implements Validator {
private static final Set<Integer> REGION_CODE_SET;
static {
Set<Integer> set = new HashSet<>(BuildConfig.MOBILE_COIN_REGIONS.length);
for (int i = 0; i < BuildConfig.MOBILE_COIN_REGIONS.length; i++) {
set.add(BuildConfig.MOBILE_COIN_REGIONS[i]);
}
REGION_CODE_SET = Collections.unmodifiableSet(set);
}
private static boolean regionAllowed(int regionCode) {
return REGION_CODE_SET.contains(regionCode);
}
@Override
public boolean e164Allowed(@Nullable String e164) {
try {
int countryCode = PhoneNumberUtil.getInstance()
.parse(e164, null)
.getCountryCode();
return regionAllowed(countryCode);
} catch (NumberParseException e) {
Log.w(TAG, e);
return false;
}
}
}
private interface Validator {
boolean e164Allowed(@Nullable String e164);
}
}

Wyświetl plik

@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.util;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
@ -88,6 +89,7 @@ public final class FeatureFlags {
private static final String DONOR_BADGES_MEGAPHONE = "android.donorBadges.megaphone";
private static final String DONOR_BADGES_DISPLAY = "android.donorBadges.display";
private static final String CDSH = "android.cdsh";
private static final String MOBILECOIN_BLACKLIST = "android.mobilecoin.blacklist";
/**
* We will only store remote values for flags in this set. If you want a flag to be controllable
@ -128,7 +130,8 @@ public final class FeatureFlags {
SENDER_KEY_MAX_AGE,
DONOR_BADGES,
DONOR_BADGES_MEGAPHONE,
DONOR_BADGES_DISPLAY
DONOR_BADGES_DISPLAY,
MOBILECOIN_BLACKLIST
);
@VisibleForTesting
@ -434,6 +437,10 @@ public final class FeatureFlags {
return Environment.IS_STAGING && getBoolean(CDSH, false);
}
public static @Nullable String mobileCoinBlacklist() {
return getString(MOBILECOIN_BLACKLIST, null);
}
/** Only for rendering debug info. */
public static synchronized @NonNull Map<String, Object> getMemoryValues() {
return new TreeMap<>(REMOTE_VALUES);

Wyświetl plik

@ -13,6 +13,8 @@ import static org.junit.Assume.assumeTrue;
public final class GeographicalRestrictionsTest {
private static final String INVALID_BLACKLIST = "asdfkljsdhfla";
@Before
public void setup() {
Log.initialize(new EmptyLogger());
@ -20,28 +22,57 @@ public final class GeographicalRestrictionsTest {
@Test
public void bad_number_not_allowed() {
assertFalse(GeographicalRestrictions.e164Allowed("bad_number"));
assertFalse(GeographicalRestrictions.e164Allowed("bad_number", null));
}
@Test
public void null_not_allowed() {
assertFalse(GeographicalRestrictions.e164Allowed(null));
assertFalse(GeographicalRestrictions.e164Allowed(null, null));
}
@Test
public void uk_allowed() {
assertTrue(GeographicalRestrictions.e164Allowed("+441617151234"));
assertTrue(GeographicalRestrictions.e164Allowed("+441617151234", null));
}
@Test
public void crimea_not_allowed() {
assertFalse(GeographicalRestrictions.e164Allowed("+79782222222"));
public void us_not_allowed_in_release() {
assumeFalse(BuildConfig.DEBUG);
assertFalse(GeographicalRestrictions.e164Allowed("+15407011234", null));
}
@Test
public void blacklist_not_allowed() {
for (int code : BuildConfig.MOBILE_COIN_BLACKLIST) {
assertFalse(GeographicalRestrictions.regionAllowed(code));
}
public void givenAnInvalidBlackList_whenIE164AllowedAUkNumber_thenIExpectTrue() {
assertTrue(GeographicalRestrictions.e164Allowed("+441617151234", INVALID_BLACKLIST));
}
@Test
public void givenAValidBlacklistWithRegionBlock_whenIE164AllowedANumberInThatRegion_thenIExpectFalse() {
assertFalse(GeographicalRestrictions.e164Allowed("+73652222222", "7 365"));
}
@Test
public void givenAValidBlacklistWithInvalidRegionBlock_whenIE164AllowedANumberInThatRegion_thenIExpectTrue() {
assertTrue(GeographicalRestrictions.e164Allowed("+73652222222", "4,7 365 2"));
}
@Test
public void givenAValidBlacklist_whenIE164AllowedANumberNotInTheBlacklist_thenIExpectTrue() {
assertTrue(GeographicalRestrictions.e164Allowed("+73632222222", "4,7 365,44,33"));
}
@Test
public void givenAValidBlacklist_whenIE164AllowedANumberInTheBlacklist_thenIExpectFalse() {
assertFalse(GeographicalRestrictions.e164Allowed("+73632222222", "4,7,44,33"));
}
@Test
public void givenAValidBlacklistWithExtraSpaces_whenIE164AllowedANumberInTheBlacklist_thenIExpectFalse() {
assertFalse(GeographicalRestrictions.e164Allowed("+73632222222", " 4, 7, 44, 33 "));
}
@Test
public void givenAValidBlacklistWithAreaCode_whenIE164AllowedANumberInTheBlacklistAreaCode_thenIExpectFalse() {
assertFalse(GeographicalRestrictions.e164Allowed("+15065550199", "1 506"));
}
}