diff --git a/src/main/java/biz/nynja/account/phone/PhoneNumberNormalizer.java b/src/main/java/biz/nynja/account/phone/PhoneNumberNormalizer.java index 6c0998445a79ed4bb6f203b191970c852bbe9c9c..0b98c4a0e2be3ab2ebaf5902e7996ed7bc922bea 100644 --- a/src/main/java/biz/nynja/account/phone/PhoneNumberNormalizer.java +++ b/src/main/java/biz/nynja/account/phone/PhoneNumberNormalizer.java @@ -10,6 +10,7 @@ import org.springframework.stereotype.Service; import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.Phonenumber; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; import biz.nynja.account.grpc.AddContactInfoRequest; import biz.nynja.account.grpc.AuthProviderDetails; @@ -147,4 +148,28 @@ public class PhoneNumberNormalizer { } return country + ":" + normalizedPhoneNumber; } + + public String getNormalizedPhoneNumberWithoutSelector(String rawPhoneNumber) throws InvalidPhoneNumberException { + logger.info("libphone: New phone number normalization request received - phone number: {}", + rawPhoneNumber); + + String phone = rawPhoneNumber.replaceAll("[^\\d]", "").replaceAll("^0*", ""); + phone = "+" + phone; + + PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); + + String normalizedPhoneNumber = ""; + Phonenumber.PhoneNumber pn = new PhoneNumber(); + try { + pn = phoneUtil.parse(phone, ""); + normalizedPhoneNumber = Integer.toString(pn.getCountryCode()) + Long.toString(pn.getNationalNumber()); + logger.info("libphone: Normalized phone number: " + normalizedPhoneNumber); + } catch (NumberParseException e) { + logger.error("libphone: NumberParseException was thrown: {}", e.toString()); + logger.debug("libphone: NumberParseException was thrown: {}", e.getCause()); + throw new InvalidPhoneNumberException("Phone number with wrong format: " + rawPhoneNumber); + } + return normalizedPhoneNumber; + } + } diff --git a/src/main/java/biz/nynja/account/services/AccountServiceImpl.java b/src/main/java/biz/nynja/account/services/AccountServiceImpl.java index e443b9e53aef4582ef8b4805c942c0b9fc900226..f5bcaee78ce470e8bc58f7369430c3947036f73c 100644 --- a/src/main/java/biz/nynja/account/services/AccountServiceImpl.java +++ b/src/main/java/biz/nynja/account/services/AccountServiceImpl.java @@ -67,6 +67,7 @@ import biz.nynja.account.permissions.PerformPermissionCheck; import biz.nynja.account.permissions.PermissionsValidator; import biz.nynja.account.permissions.Permitted; import biz.nynja.account.permissions.RoleConstants; +import biz.nynja.account.phone.InvalidPhoneNumberException; import biz.nynja.account.phone.PhoneNumberNormalizer; import biz.nynja.account.repositories.AccountByProfileIdRepository; import biz.nynja.account.repositories.AccountByQrCodeRepository; @@ -222,19 +223,19 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas Cause.MISSING_PHONENUMBER, ""); return; } - if (!phoneValidator.isPhoneNumberValid(request.getPhoneNumber())) { - logAndBuildGrpcSearchResponse(responseObserver, SearchResponse.newBuilder(), - "Invalid phone number. Value: {}", request.getPhoneNumber(), Cause.INVALID_PHONENUMBER, - "Phone number parameter has invalid format."); - return; - } Optional account = Optional.empty(); try { - account = accountProvider.searchAccountByLoginOption(AuthenticationType.PHONE, request.getPhoneNumber()); + account = accountProvider.searchAccountByLoginOptionWithoutSelector(AuthenticationType.PHONE, request.getPhoneNumber()); } catch (IncorrectAccountCountException e) { logAndBuildGrpcSearchResponse(responseObserver, SearchResponse.newBuilder(), "Error while searching for phone: ", request.getPhoneNumber(), Cause.INTERNAL_SERVER_ERROR, ""); + return; + } catch (InvalidPhoneNumberException e) { + logAndBuildGrpcSearchResponse(responseObserver, SearchResponse.newBuilder(), + "Invalid phone number. Value: {}", request.getPhoneNumber(), Cause.INVALID_PHONENUMBER, + "Phone number parameter has invalid format."); + return; } if (!account.isPresent()) { diff --git a/src/main/java/biz/nynja/account/services/decomposition/AccountProvider.java b/src/main/java/biz/nynja/account/services/decomposition/AccountProvider.java index a062706fd22304beb2c5cadf72460bff6bb98478..3065030f9b1922f565ae69b4e4e3796d5dfe174c 100644 --- a/src/main/java/biz/nynja/account/services/decomposition/AccountProvider.java +++ b/src/main/java/biz/nynja/account/services/decomposition/AccountProvider.java @@ -26,6 +26,7 @@ import biz.nynja.account.models.AccountByProfileId; import biz.nynja.account.models.AccountByQrCode; import biz.nynja.account.models.AccountByUsername; import biz.nynja.account.models.AuthenticationProvider; +import biz.nynja.account.phone.InvalidPhoneNumberException; import biz.nynja.account.phone.PhoneNumberNormalizer; import biz.nynja.account.repositories.AccountByProfileIdRepository; import biz.nynja.account.repositories.AccountByQrCodeRepository; @@ -136,6 +137,22 @@ public class AccountProvider { return Optional.of(accountByProfileId.get().toAccount()); } + public Optional searchAccountByLoginOptionWithoutSelector(AuthenticationType type, String authenticationIdentifier) + throws IncorrectAccountCountException, InvalidPhoneNumberException { + if (type == AuthenticationType.PHONE) { + authenticationIdentifier = phoneNumberNormalizer.getNormalizedPhoneNumberWithoutSelector(authenticationIdentifier); + } + + Optional accountByProfileId = accountRepositoryAdditional.searchAccountByLoginOption( + AuthenticationProvider.createAuthenticationProviderFromStringsWithDefaultSearchableOption( + type.toString(), authenticationIdentifier)); + if (!accountByProfileId.isPresent()) { + return Optional.empty(); + } + + return Optional.of(accountByProfileId.get().toAccount()); + } + public Optional getAccountResponseByAuthenticationProvider(AuthenticationType type, String authenticationIdentifier) { Optional account = getAccountByAuthenticationProvider(type, authenticationIdentifier); diff --git a/src/main/java/biz/nynja/account/validation/Validators.java b/src/main/java/biz/nynja/account/validation/Validators.java index 3d589f3d4a0c2c92e1ae9cd877ede5ce344bec93..78d20805e2f08ca620c6fc7e53205741d416e59d 100644 --- a/src/main/java/biz/nynja/account/validation/Validators.java +++ b/src/main/java/biz/nynja/account/validation/Validators.java @@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory; import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.Phonenumber; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; import biz.nynja.account.grpc.AddAuthenticationProviderRequest; import biz.nynja.account.grpc.AuthProviderDetails; @@ -465,6 +466,7 @@ public class Validators { return true; } + } public static class Util { diff --git a/src/test/java/biz/nynja/account/services/AccountServiceTests.java b/src/test/java/biz/nynja/account/services/AccountServiceTests.java index 955277f747ad642b9e75a19407d50cf0e4fdcc9b..148df8dd1465d7bf09e2d816b99ff2bae34cad22 100644 --- a/src/test/java/biz/nynja/account/services/AccountServiceTests.java +++ b/src/test/java/biz/nynja/account/services/AccountServiceTests.java @@ -8,7 +8,9 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.LinkedList; @@ -104,6 +106,7 @@ import biz.nynja.account.services.decomposition.IncorrectAccountCountException; import biz.nynja.account.services.decomposition.ProfileProvider; import biz.nynja.account.utils.GrpcServerTestBase; import biz.nynja.account.utils.Util; +import biz.nynja.account.phone.InvalidPhoneNumberException; import io.grpc.Metadata; import io.grpc.stub.MetadataUtils; @@ -1546,7 +1549,7 @@ public class AccountServiceTests extends GrpcServerTestBase { Optional response = Optional.of(savedAccount); - given(accountProvider.searchAccountByLoginOption(AuthenticationType.PHONE, request.getPhoneNumber())) + given(accountProvider.searchAccountByLoginOptionWithoutSelector(AuthenticationType.PHONE, request.getPhoneNumber())) .willReturn(response); final SearchResponse reply = searchServiceBlockingStub.searchByPhoneNumber(request); @@ -1585,10 +1588,13 @@ public class AccountServiceTests extends GrpcServerTestBase { } @Test - public void testSearchByPhoneNumberInvalid() { + public void testSearchByPhoneNumberInvalid() throws InvalidPhoneNumberException, IncorrectAccountCountException { + Exception ex = new InvalidPhoneNumberException("Invalid phone number"); final GetByPhoneNumberRequest request = GetByPhoneNumberRequest.newBuilder() .setPhoneNumber(Util.S_INVALID_PHONENUMBER).build(); + given(accountProvider.searchAccountByLoginOptionWithoutSelector(AuthenticationType.PHONE, request.getPhoneNumber())).willThrow(ex); + final SearchResponse reply = searchServiceBlockingStub.searchByPhoneNumber(request); assertNotNull("Reply should not be null", reply);