diff --git a/src/main/java/biz/nynja/account/phone/PhoneNumberNormalizer.java b/src/main/java/biz/nynja/account/phone/PhoneNumberNormalizer.java index 806362f6e40bdb24f48a8e59ce6f0616d760df90..ce836d7ffdf9150342500270ad8825df97a36344 100644 --- a/src/main/java/biz/nynja/account/phone/PhoneNumberNormalizer.java +++ b/src/main/java/biz/nynja/account/phone/PhoneNumberNormalizer.java @@ -3,16 +3,14 @@ */ package biz.nynja.account.phone; -import biz.nynja.account.models.CountryInfo; -import biz.nynja.account.validation.Validators; -import com.google.i18n.phonenumbers.NumberParseException; -import com.google.i18n.phonenumbers.PhoneNumberUtil; -import com.google.i18n.phonenumbers.Phonenumber; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import com.google.i18n.phonenumbers.NumberParseException; +import com.google.i18n.phonenumbers.PhoneNumberUtil; +import com.google.i18n.phonenumbers.Phonenumber; + import biz.nynja.account.grpc.AddContactInfoRequest; import biz.nynja.account.grpc.AuthProviderDetails; import biz.nynja.account.grpc.AuthenticationType; diff --git a/src/main/java/biz/nynja/account/phone/PhoneNumberUtils.java b/src/main/java/biz/nynja/account/phone/PhoneNumberUtils.java index f5914c661a88638e9d94a5dbfc749bf2f0f9a7ae..62c84462a734769647151c862405a00e05760f51 100644 --- a/src/main/java/biz/nynja/account/phone/PhoneNumberUtils.java +++ b/src/main/java/biz/nynja/account/phone/PhoneNumberUtils.java @@ -3,78 +3,20 @@ */ package biz.nynja.account.phone; -import biz.nynja.account.models.CountryInfo; -import com.google.i18n.phonenumbers.NumberParseException; -import com.google.i18n.phonenumbers.PhoneNumberUtil; -import com.google.i18n.phonenumbers.Phonenumber; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.HashMap; +import com.google.i18n.phonenumbers.NumberParseException; +import com.google.i18n.phonenumbers.PhoneNumberUtil; +import com.google.i18n.phonenumbers.Phonenumber; public class PhoneNumberUtils { private static final Logger logger = LoggerFactory.getLogger(PhoneNumberUtils.class); - public static HashMap countryInfoMap; - public static HashMap countryMapByCountryCode; - - static { - init(); - } - - private static void init() { - - CountryInfo countryInfo = null; - BufferedReader reader = null; - countryInfoMap = new HashMap<>(); - countryMapByCountryCode = new HashMap<>(); - - logger.debug("Loading phones information from file."); - try { - Resource resource = new ClassPathResource("countries.txt"); - InputStream resourceInputStream = resource.getInputStream(); - logger.debug("Phones information loaded."); - reader = new BufferedReader(new InputStreamReader(resourceInputStream)); - String line; - while ((line = reader.readLine()) != null) { - String[] args = line.split(";"); - countryInfo = new CountryInfo(); - countryInfo.setCountryCode(args[1]); - countryInfo.setCountryPhoneCode(args[0]); - countryInfo.setCountryName(args[2]); - if (args.length > 3) { - countryInfo.setPhoneFormat(args[3]); - } - countryInfoMap.put(args[1], countryInfo); - countryMapByCountryCode.put(args[0], countryInfo); - } - } catch (IOException e) { - logger.error("Error during load phones information: {}", e.getMessage()); - } finally { - try { - reader.close(); - } catch (IOException e) { - logger.error("Close reader error: {}", e.getMessage()); - } - } - } public static String getCountrySelector(String phoneNumber) throws InvalidPhoneNumberException { - String countryCode; - countryCode = getCountryCode(phoneNumber); - - CountryInfo countryInfo = PhoneNumberUtils.countryMapByCountryCode.get(countryCode); - if (countryInfo != null) { - return countryInfo.getCountryCode(); - } else { - logger.debug("Country selector not found in'countries.txt' for country code: {}", countryCode); - throw new InvalidPhoneNumberException("No country found for code: " + countryCode); - } + String countryCode = getCountryCode(phoneNumber); + logger.debug("Retrieving country selector for code: {}", countryCode); + return PhoneNumberUtil.getInstance().getRegionCodeForCountryCode(Integer.valueOf(countryCode)); } public static String getCountryCode(String phoneNumber) { diff --git a/src/main/java/biz/nynja/account/validation/Validators.java b/src/main/java/biz/nynja/account/validation/Validators.java index 55010bdcfa5a789b0a724da9afd45cdf09bb6e2d..930b836ad497429ef6461dc7f9655adf9fae24ca 100644 --- a/src/main/java/biz/nynja/account/validation/Validators.java +++ b/src/main/java/biz/nynja/account/validation/Validators.java @@ -16,9 +16,21 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import biz.nynja.account.grpc.*; +import com.google.i18n.phonenumbers.NumberParseException; +import com.google.i18n.phonenumbers.PhoneNumberUtil; +import com.google.i18n.phonenumbers.Phonenumber; + +import biz.nynja.account.grpc.AddAuthenticationProviderRequest; +import biz.nynja.account.grpc.AuthProviderDetails; +import biz.nynja.account.grpc.AuthenticationType; +import biz.nynja.account.grpc.CompletePendingAccountCreationRequest; +import biz.nynja.account.grpc.ContactDetails; +import biz.nynja.account.grpc.ContactType; +import biz.nynja.account.grpc.CreatePendingAccountRequest; +import biz.nynja.account.grpc.Date; +import biz.nynja.account.grpc.DeleteAuthenticationProviderRequest; import biz.nynja.account.grpc.ErrorResponse.Cause; -import biz.nynja.account.models.CountryInfo; +import biz.nynja.account.grpc.UpdateAccountRequest; import biz.nynja.account.phone.InvalidPhoneNumberException; import biz.nynja.account.phone.PhoneNumberUtils; @@ -342,38 +354,19 @@ public class Validators { public static class PhoneNumberValidator { public boolean isPhoneNumberValid(String phoneNumber, String countryCode) { + boolean isValid = false; + + logger.debug("Checking validity of phone number {} and code {}.", phoneNumber, countryCode); + + PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); + Phonenumber.PhoneNumber pn; + try { + pn = phoneUtil.parse(phoneNumber, countryCode); + isValid = phoneUtil.isValidNumberForRegion(pn, countryCode); + } catch (NumberParseException e) { + isValid = false; + } - final int NATIONAL_NUMBER_MAX_LENGTH = 15; - - logger.debug("Checking phoneNumber: {} for country: {}", phoneNumber, countryCode); - CountryInfo countryInfo = PhoneNumberUtils.countryInfoMap.get(countryCode); - if (countryInfo == null) { - logger.debug("Country: {} not found!", countryCode); - return false; - } - - char[] digits = countryInfo.getCountryPhoneCode().toCharArray(); - StringBuilder builder = new StringBuilder(); - for (char digit : digits) { - builder.append("[" + digit + "]"); - } - String codePattern = builder.toString(); - - String phoneLength = null; - if (countryInfo.getPhoneFormat() != null) { - phoneLength = "{" + countryInfo.getPhoneFormat().replaceAll("\\s", "").length() + "}"; - } else { - phoneLength = "{0," + NATIONAL_NUMBER_MAX_LENGTH + "}"; - } - - final String PHONE_PATTERN = "((?:\\+?([0][0])?" + codePattern + ")?||([0][0]" + codePattern + ")?)(\\d" - + phoneLength + ")$"; - logger.debug("Generated phone pattern for country: {}, {}", countryCode, PHONE_PATTERN); - - Pattern pattern = Pattern.compile(PHONE_PATTERN); - Matcher matcher = pattern.matcher(phoneNumber); - - boolean isValid = matcher.matches(); logger.debug("PhoneNumber: {} for country: {} is valid: {}", phoneNumber, countryCode, isValid); return isValid; diff --git a/src/main/resources/countries.txt b/src/main/resources/countries.txt deleted file mode 100644 index 60d177a7e180abf4ee8ccd0bb19268187e2f0cf7..0000000000000000000000000000000000000000 --- a/src/main/resources/countries.txt +++ /dev/null @@ -1,236 +0,0 @@ -1876;JM;Jamaica;XXX XXXX -1869;KN;Saint Kitts & Nevis;XXX XXXX -1868;TT;Trinidad & Tobago;XXX XXXX -1784;VC;Saint Vincent & the Grenadines;XXX XXXX -1767;DM;Dominica;XXX XXXX -1758;LC;Saint Lucia;XXX XXXX -1721;SX;Sint Maarten;XXX XXXX -1684;AS;American Samoa;XXX XXXX -1671;GU;Guam;XXX XXXX -1670;MP;Northern Mariana Islands;XXX XXXX -1664;MS;Montserrat;XXX XXXX -1649;TC;Turks & Caicos Islands;XXX XXXX -1473;GD;Grenada;XXX XXXX -1441;BM;Bermuda;XXX XXXX -1345;KY;Cayman Islands;XXX XXXX -1340;VI;US Virgin Islands;XXX XXXX -1284;VG;British Virgin Islands;XXX XXXX -1268;AG;Antigua & Barbuda;XXX XXXX -1264;AI;Anguilla;XXX XXXX -1246;BB;Barbados;XXX XXXX -1242;BS;Bahamas;XXX XXXX -998;UZ;Uzbekistan;XX XXXXXXX -996;KG;Kyrgyzstan;XXX XXXXXX -995;GE;Georgia;XXX XXX XXX -994;AZ;Azerbaijan;XX XXX XXXX -993;TM;Turkmenistan;XX XXXXXX -992;TJ;Tajikistan;XX XXX XXXX -977;NP;Nepal;XX XXXX XXXX -976;MN;Mongolia;XX XX XXXX -975;BT;Bhutan;XX XXX XXX -974;QA;Qatar;XX XXX XXX -973;BH;Bahrain;XXXX XXXX -972;IL;Israel;XX XXX XXXX -971;AE;United Arab Emirates;XX XXX XXXX -970;PS;Palestine;XXX XX XXXX -968;OM;Oman;XXXX XXXX -967;YE;Yemen;XXX XXX XXX -966;SA;Saudi Arabia;XX XXX XXXX -965;KW;Kuwait;XXXX XXXX -964;IQ;Iraq;XXX XXX XXXX -963;SY;Syria;XXX XXX XXX -962;JO;Jordan;X XXXX XXXX -961;LB;Lebanon -960;MV;Maldives;XXX XXXX -886;TW;Taiwan;XXX XXX XXX -883;GO;International Networks -882;GO;International Networks -881;GO;Global Mobile Satellite -880;BD;Bangladesh -856;LA;Laos;XX XX XXX XXX -855;KH;Cambodia -853;MO;Macau;XXXX XXXX -852;HK;Hong Kong;X XXX XXXX -850;KP;North Korea -692;MH;Marshall Islands -691;FM;Micronesia -690;TK;Tokelau -689;PF;French Polynesia -688;TV;Tuvalu -687;NC;New Caledonia -686;KI;Kiribati -685;WS;Samoa -683;NU;Niue -682;CK;Cook Islands -681;WF;Wallis & Futuna -680;PW;Palau -679;FJ;Fiji -678;VU;Vanuatu -677;SB;Solomon Islands -676;TO;Tonga -675;PG;Papua New Guinea -674;NR;Nauru -673;BN;Brunei Darussalam;XXX XXXX -672;NF;Norfolk Island -670;TL;Timor-Leste -599;BQ;Bonaire, Sint Eustatius & Saba -599;CW;Curaçao -598;UY;Uruguay;X XXX XXXX -597;SR;Suriname;XXX XXXX -596;MQ;Martinique -595;PY;Paraguay;XXX XXX XXX -594;GF;French Guiana -593;EC;Ecuador;XX XXX XXXX -592;GY;Guyana -591;BO;Bolivia;X XXX XXXX -590;GP;Guadeloupe;XXX XX XX XX -509;HT;Haiti -508;PM;Saint Pierre & Miquelon -507;PA;Panama;XXXX XXXX -506;CR;Costa Rica;XXXX XXXX -505;NI;Nicaragua;XXXX XXXX -504;HN;Honduras;XXXX XXXX -503;SV;El Salvador;XXXX XXXX -502;GT;Guatemala;X XXX XXXX -501;BZ;Belize -500;FK;Falkland Islands -423;LI;Liechtenstein -421;SK;Slovakia;XXX XXX XXX -420;CZ;Czech Republic;XXX XXX XXX -389;MK;Macedonia;XX XXX XXX -387;BA;Bosnia & Herzegovina;XX XXX XXX -386;SI;Slovenia;XX XXX XXX -385;HR;Croatia -383;XK;Kosovo;XXXX XXXX -382;ME;Montenegro -381;RS;Serbia;XX XXX XXXX -380;UA;Ukraine;XX XXX XX XX -378;SM;San Marino;XXX XXX XXXX -377;MC;Monaco;XXXX XXXX -376;AD;Andorra;XX XX XX -375;BY;Belarus;XX XXX XXXX -374;AM;Armenia;XX XXX XXX -373;MD;Moldova;XX XXX XXX -372;EE;Estonia -371;LV;Latvia;XXX XXXXX -370;LT;Lithuania;XXX XXXXX -359;BG;Bulgaria -358;FI;Finland -357;CY;Cyprus;XXXX XXXX -356;MT;Malta;XX XX XX XX -355;AL;Albania;XX XXX XXXX -354;IS;Iceland;XXX XXXX -353;IE;Ireland;XX XXX XXXX -352;LU;Luxembourg -351;PT;Portugal;X XXXX XXXX -350;GI;Gibraltar;XXXX XXXX -299;GL;Greenland;XXX XXX -298;FO;Faroe Islands;XXX XXX -297;AW;Aruba;XXX XXXX -291;ER;Eritrea;X XXX XXX -290;SH;Saint Helena;XX XXX -269;KM;Comoros;XXX XXXX -268;SZ;Swaziland;XXXX XXXX -267;BW;Botswana;XX XXX XXX -266;LS;Lesotho;XX XXX XXX -265;MW;Malawi;77 XXX XXXX -264;NA;Namibia;XX XXX XXXX -263;ZW;Zimbabwe;XX XXX XXXX -262;RE;Réunion;XXX XXX XXX -261;MG;Madagascar;XX XX XXX XX -260;ZM;Zambia;XX XXX XXXX -258;MZ;Mozambique;XX XXX XXXX -257;BI;Burundi;XX XX XXXX -256;UG;Uganda;XX XXX XXXX -255;TZ;Tanzania;XX XXX XXXX -254;KE;Kenya;XXX XXX XXX -253;DJ;Djibouti;XX XX XX XX -252;SO;Somalia;XX XXX XXX -251;ET;Ethiopia;XX XXX XXXX -250;RW;Rwanda;XXX XXX XXX -249;SD;Sudan;XX XXX XXXX -248;SC;Seychelles;X XX XX XX -247;SH;Saint Helena;XXXX -246;IO;Diego Garcia;XXX XXXX -245;GW;Guinea-Bissau;XXX XXXX -244;AO;Angola;XXX XXX XXX -243;CD;Congo (Dem. Rep.);XX XXX XXXX -242;CG;Congo (Rep.);XX XXX XXXX -241;GA;Gabon;X XX XX XX -240;GQ;Equatorial Guinea;XXX XXX XXX -239;ST;São Tomé & Príncipe;XX XXXXX -238;CV;Cape Verde;XXX XXXX -237;CM;Cameroon;XXXX XXXX -236;CF;Central African Rep.;XX XX XX XX -235;TD;Chad;XX XX XX XX -234;NG;Nigeria -233;GH;Ghana -232;SL;Sierra Leone;XX XXX XXX -231;LR;Liberia -230;MU;Mauritius -229;BJ;Benin;XX XXX XXX -228;TG;Togo;XX XXX XXX -227;NE;Niger;XX XX XX XX -226;BF;Burkina Faso;XX XX XX XX -225;CI;Côte d`Ivoire;XX XXX XXX -224;GN;Guinea;XXX XXX XXX -223;ML;Mali;XXXX XXXX -222;MR;Mauritania;XXXX XXXX -221;SN;Senegal;XX XXX XXXX -220;GM;Gambia;XXX XXXX -218;LY;Libya;XX XXX XXXX -216;TN;Tunisia;XX XXX XXX -213;DZ;Algeria;XXX XX XX XX -212;MA;Morocco;XX XXX XXXX -211;SS;South Sudan;XX XXX XXXX -98;IR;Iran;XXX XXX XXXX -95;MM;Myanmar -94;LK;Sri Lanka;XX XXX XXXX -93;AF;Afghanistan;XXX XXX XXX -92;PK;Pakistan;XXX XXX XXXX -91;IN;India;XXXXX XXXXX -90;TR;Turkey;XXX XXX XXXX -86;CN;China;XXX XXXX XXXX -84;VN;Vietnam -82;KR;South Korea -81;JP;Japan;XX XXXX XXXX -66;TH;Thailand;X XXXX XXXX -65;SG;Singapore;XXXX XXXX -64;NZ;New Zealand -63;PH;Philippines;XXX XXX XXXX -62;ID;Indonesia -61;AU;Australia;XXX XXX XXX -60;MY;Malaysia -58;VE;Venezuela;XXX XXX XXXX -57;CO;Colombia;XXX XXX XXXX -56;CL;Chile;X XXXX XXXX -55;BR;Brazil;XX XXXXX XXXX -54;AR;Argentina -53;CU;Cuba;XXXX XXXX -52;MX;Mexico -51;PE;Peru;XXX XXX XXX -49;DE;Germany -48;PL;Poland;XX XXX XXXX -47;NO;Norway;XXXX XXXX -46;SE;Sweden;XX XXX XXXX -45;DK;Denmark;XXXX XXXX -44;GB;United Kingdom;XXXX XXXXXX -43;AT;Austria -42;YL;Y-land -41;CH;Switzerland;XX XXX XXXX -40;RO;Romania;XXX XXX XXX -39;IT;Italy -36;HU;Hungary;XXX XXX XXX -34;ES;Spain;XXX XXX XXX -33;FR;France;X XX XX XX XX -32;BE;Belgium;XXX XX XX XX -31;NL;Netherlands;X XX XX XX XX -30;GR;Greece;XXX XXX XXXX -27;ZA;South Africa;XX XXX XXXX -20;EG;Egypt;XX XXXX XXXX -7;KZ;Kazakhstan;XXX XXX XX XX -7;RU;Russian Federation;XXX XXX XXXX -1;PR;Puerto Rico;XXX XXX XXXX -1;DO;Dominican Rep.;XXX XXX XXXX -1;CA;Canada;XXX XXX XXXX -1;US;USA;XXX XXX XXXX \ No newline at end of file diff --git a/src/test/java/biz/nynja/account/components/PhoneNumberValidatorTests.java b/src/test/java/biz/nynja/account/components/PhoneNumberValidatorTests.java index 05928941946f327f1e67d67e1bdf7fc321cbe96d..56d72fb911b9a069cf6a4dc99bbd51346f61487e 100644 --- a/src/test/java/biz/nynja/account/components/PhoneNumberValidatorTests.java +++ b/src/test/java/biz/nynja/account/components/PhoneNumberValidatorTests.java @@ -6,13 +6,9 @@ package biz.nynja.account.components; import static biz.nynja.account.validation.Validators.phoneValidator; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import biz.nynja.account.phone.PhoneNumberNormalizer; -import biz.nynja.account.validation.Validators; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -21,6 +17,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; +import biz.nynja.account.phone.PhoneNumberNormalizer; import biz.nynja.account.repositories.AccountRepositoryAdditional; /** @@ -56,6 +53,16 @@ public class PhoneNumberValidatorTests { } + @Test + public void newInvalidPhoneNumberTest() { + + String phoneNumber = "+35901"; + String countryCode = "BG"; + boolean isValid = phoneValidator.isPhoneNumberValid(phoneNumber, countryCode); + assertNotEquals(String.format("Phone number: '%s' should be invalid for country '%s'", phoneNumber, countryCode), true, isValid); + + } + @Test public void validNormalizedPhoneNumberTest1() { String expectedPhoneNumber = "359887345234"; diff --git a/src/test/java/biz/nynja/account/components/ValidatorTests.java b/src/test/java/biz/nynja/account/components/ValidatorTests.java index 26171284e8927ca90ab8566077f86f875ca769db..ec44798e4027ee09947e19a0df052254a35e8830 100644 --- a/src/test/java/biz/nynja/account/components/ValidatorTests.java +++ b/src/test/java/biz/nynja/account/components/ValidatorTests.java @@ -4,27 +4,31 @@ package biz.nynja.account.components; -import static biz.nynja.account.validation.Validators.*; -import static org.junit.Assert.*; +import static biz.nynja.account.validation.Validators.account; +import static biz.nynja.account.validation.Validators.authenticationProvider; +import static biz.nynja.account.validation.Validators.pendingAccount; +import static biz.nynja.account.validation.Validators.util; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.NoSuchElementException; -import biz.nynja.account.validation.Validators; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import biz.nynja.account.grpc.AuthenticationType; import biz.nynja.account.grpc.CompletePendingAccountCreationRequest; import biz.nynja.account.grpc.CreatePendingAccountRequest; import biz.nynja.account.grpc.ErrorResponse.Cause; +import biz.nynja.account.phone.PhoneNumberUtils; import biz.nynja.account.repositories.AccountRepositoryAdditional; import biz.nynja.account.utils.Util; -import java.util.NoSuchElementException; - /** * Components unit tests. */ @@ -288,5 +292,17 @@ public class ValidatorTests { .setAuthenticationProvider("invalid.E-mail1.@domain_test.com1").build(); assertEquals(Cause.INVALID_EMAIL, pendingAccount.validateCreatePendingAccountRequest(request).get()); } + + @Test + public void testCountryCodeGetterValidNumber() { + String countryCode = PhoneNumberUtils.getCountrySelector("359888888888"); // Bulgaria + assertEquals("BG", countryCode); + + countryCode = PhoneNumberUtils.getCountrySelector("1888888888"); // United states + assertEquals("US", countryCode); + + countryCode = PhoneNumberUtils.getCountrySelector("380888888888"); // Ukrain + assertEquals("UA", countryCode); + } }