diff --git a/app/build.gradle b/app/build.gradle index e731ff303..9bb2778d1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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_REGIONS", "new int[]{44,49,33,41}" + buildConfigField "int[]", "MOBILE_COIN_BLACKLIST", "new int[]{98,963,53,850,7}" buildConfigField "String", "GIPHY_API_KEY", "\"3o6ZsYH6U6Eri53TXy\"" buildConfigField "String", "RECAPTCHA_PROOF_URL", "\"https://signalcaptchas.org/challenge/generate.html\"" diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/PaymentsValues.java b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/PaymentsValues.java index d4d030f53..8b7c83b79 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/PaymentsValues.java +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/PaymentsValues.java @@ -108,15 +108,15 @@ public final class PaymentsValues extends SignalStoreValues { public PaymentsAvailability getPaymentsAvailability() { Context context = ApplicationDependencies.getApplication(); - if (!TextSecurePreferences.isPushRegistered(context)) { + if (!TextSecurePreferences.isPushRegistered(context) || + !GeographicalRestrictions.e164Allowed(TextSecurePreferences.getLocalNumber(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; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/payments/GeographicalRestrictions.java b/app/src/main/java/org/thoughtcrime/securesms/payments/GeographicalRestrictions.java index 1cada7839..6708c206a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/payments/GeographicalRestrictions.java +++ b/app/src/main/java/org/thoughtcrime/securesms/payments/GeographicalRestrictions.java @@ -1,185 +1,49 @@ 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 static final Validator BUILD_CONFIG_VALIDATOR = new BuildConfigWhitelistValidator(); + private GeographicalRestrictions() {} - private GeographicalRestrictions() { + private static final Set BLACKLIST; + + static { + Set 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); } public static boolean e164Allowed(@Nullable String e164) { - return selectValidator(FeatureFlags.mobileCoinBlacklist()).e164Allowed(e164); - } + try { + int countryCode = PhoneNumberUtil.getInstance() + .parse(e164, null) + .getCountryCode(); - @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); + return GeographicalRestrictions.regionAllowed(countryCode); + } catch (NumberParseException e) { + Log.w(TAG, e); + return false; } } - - 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 blacklistCountries; - private final Map> blacklistRegions; - - private FeatureFlagBlacklistValidator(@NonNull String[] blacklist) { - Set countries = new HashSet<>(blacklist.length); - Map> 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 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 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 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 REGION_CODE_SET; - - static { - Set 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); - } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java index 3c492ebe4..3edd292ea 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java @@ -3,7 +3,6 @@ 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; @@ -89,7 +88,6 @@ 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 @@ -130,8 +128,7 @@ public final class FeatureFlags { SENDER_KEY_MAX_AGE, DONOR_BADGES, DONOR_BADGES_MEGAPHONE, - DONOR_BADGES_DISPLAY, - MOBILECOIN_BLACKLIST + DONOR_BADGES_DISPLAY ); @VisibleForTesting @@ -437,10 +434,6 @@ 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 getMemoryValues() { return new TreeMap<>(REMOTE_VALUES); diff --git a/app/src/test/java/org/thoughtcrime/securesms/payments/GeographicalRestrictionsTest.java b/app/src/test/java/org/thoughtcrime/securesms/payments/GeographicalRestrictionsTest.java index b874d446f..c1978d4e8 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/payments/GeographicalRestrictionsTest.java +++ b/app/src/test/java/org/thoughtcrime/securesms/payments/GeographicalRestrictionsTest.java @@ -13,8 +13,6 @@ 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()); @@ -22,57 +20,28 @@ public final class GeographicalRestrictionsTest { @Test public void bad_number_not_allowed() { - assertFalse(GeographicalRestrictions.e164Allowed("bad_number", null)); + assertFalse(GeographicalRestrictions.e164Allowed("bad_number")); } @Test public void null_not_allowed() { - assertFalse(GeographicalRestrictions.e164Allowed(null, null)); + assertFalse(GeographicalRestrictions.e164Allowed(null)); } @Test public void uk_allowed() { - assertTrue(GeographicalRestrictions.e164Allowed("+441617151234", null)); + assertTrue(GeographicalRestrictions.e164Allowed("+441617151234")); } @Test - public void us_not_allowed_in_release() { - assumeFalse(BuildConfig.DEBUG); - assertFalse(GeographicalRestrictions.e164Allowed("+15407011234", null)); + public void crimea_not_allowed() { + assertFalse(GeographicalRestrictions.e164Allowed("+79782222222")); } @Test - 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")); + public void blacklist_not_allowed() { + for (int code : BuildConfig.MOBILE_COIN_BLACKLIST) { + assertFalse(GeographicalRestrictions.regionAllowed(code)); + } } }