diff --git a/pom.xml b/pom.xml
index 7e8627c9eeb73329ba9122be087751bbd9542278..78278a19baf22aafc5e3622f40a6eba065a8e209 100644
--- a/pom.xml
+++ b/pom.xml
@@ -143,6 +143,12 @@
io.micrometer
micrometer-registry-prometheus
+
+
+ org.apache.commons
+ commons-lang3
+ 3.8.1
+
diff --git a/src/main/java/biz/nynja/account/components/PhoneNumberNormalizer.java b/src/main/java/biz/nynja/account/components/PhoneNumberNormalizer.java
new file mode 100644
index 0000000000000000000000000000000000000000..afac39dd5510c26f24319e8bbee08469b70399d7
--- /dev/null
+++ b/src/main/java/biz/nynja/account/components/PhoneNumberNormalizer.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2018 Nynja Inc. All rights reserved.
+ */
+package biz.nynja.account.components;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import biz.nynja.account.grpc.AddContactInfoRequest;
+import biz.nynja.account.grpc.ContactDetails;
+import biz.nynja.account.grpc.DeleteContactInfoRequest;
+
+@Service
+public class PhoneNumberNormalizer {
+
+ @Autowired
+ private Validator validator;
+
+ public AddContactInfoRequest normalizePhoneNumber(AddContactInfoRequest request) {
+ // Get the normalized phone number from libphone
+ ContactDetails newContactDetails = ContactDetails.newBuilder().setType(request.getContactInfo().getType())
+ .setValue(validator.getNormalizedPhoneNumber(request.getContactInfo().getValue()))
+ .setLabel(request.getContactInfo().getLabel()).build();
+ AddContactInfoRequest newRequest = AddContactInfoRequest.newBuilder().setAccountId(request.getAccountId())
+ .setContactInfo(newContactDetails).build();
+ request = newRequest;
+ return request;
+ }
+
+ public DeleteContactInfoRequest normalizePhoneNumber(DeleteContactInfoRequest request) {
+ // Get the normalized phone number from libphone
+ ContactDetails newContactDetails = ContactDetails.newBuilder().setType(request.getContactInfo().getType())
+ .setValue(validator.getNormalizedPhoneNumber(request.getContactInfo().getValue()))
+ .setLabel(request.getContactInfo().getLabel()).build();
+ DeleteContactInfoRequest newRequest = DeleteContactInfoRequest.newBuilder().setAccountId(request.getAccountId())
+ .setContactInfo(newContactDetails).build();
+ request = newRequest;
+ return request;
+ }
+}
diff --git a/src/main/java/biz/nynja/account/components/Validator.java b/src/main/java/biz/nynja/account/components/Validator.java
index 2da72ad4f34203cac4f70fd11a34076806631933..0703c1d2198c6614e0aab9d4655d7c17235e1495 100644
--- a/src/main/java/biz/nynja/account/components/Validator.java
+++ b/src/main/java/biz/nynja/account/components/Validator.java
@@ -8,11 +8,13 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
+import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
+import org.apache.commons.lang3.tuple.ImmutablePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
@@ -26,9 +28,11 @@ import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
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.DeleteAuthenticationProviderRequest;
+import biz.nynja.account.grpc.DeleteContactInfoRequest;
import biz.nynja.account.grpc.ErrorResponse.Cause;
import biz.nynja.account.grpc.UpdateAccountRequest;
import biz.nynja.account.grpc.UpdateProfileRequest;
@@ -238,32 +242,32 @@ public class Validator {
return null;
}
- public Cause validateContactInfo(ContactType type, String contactInfoValue) {
+ public Optional> validateContactInfo(ContactType type, String contactInfoValue) {
if (contactInfoValue == null || contactInfoValue.trim().isEmpty()) {
- return Cause.MISSING_CONTACT_INFO_IDENTIFIER;
+ return Optional.of(new ImmutablePair<>(Cause.MISSING_CONTACT_INFO_IDENTIFIER, "Missing contact info identifier"));
}
switch (type) {
case MISSING_CONTACT_TYPE:
- return Cause.MISSING_CONTACT_INFO_TYPE;
+ return Optional.of(new ImmutablePair<>(Cause.MISSING_CONTACT_INFO_TYPE, "Missing contact info type"));
case PHONE_CONTACT:
// We expect to receive phone number in the following format : ":"
String[] provider = contactInfoValue.split(":");
if (provider == null || provider.length != 2) {
- return Cause.PHONE_NUMBER_INVALID;
+ return Optional.of(new ImmutablePair<>(Cause.PHONE_NUMBER_INVALID, "Invalid phone number"));
}
if (!isPhoneNumberValid(provider[1], provider[0])) {
- return Cause.PHONE_NUMBER_INVALID;
+ return Optional.of(new ImmutablePair<>(Cause.PHONE_NUMBER_INVALID, "Invalid phone number"));
}
break;
case EMAIL_CONTACT:
if (!isEmailValid(contactInfoValue)) {
- return Cause.EMAIL_INVALID;
+ return Optional.of(new ImmutablePair<>(Cause.EMAIL_INVALID, "Invalid email"));
}
break;
default:
break;
}
- return null;
+ return Optional.empty();
}
public Cause validateCreatePendingAccountRequest(CreatePendingAccountRequest request) {
@@ -340,20 +344,21 @@ public class Validator {
request.getAuthenticationProvider().getAuthenticationProvider());
}
- public Cause checkAddContactInfoRequest(AddContactInfoRequest request) {
- if ((request.getAccountId() == null) || (request.getAccountId().isEmpty())) {
- return Cause.MISSING_ACCOUNT_ID;
+ public Optional> validateContactInfoRequest(String accountId, ContactDetails contactDetails) {
+ if ((accountId == null) || (accountId.isEmpty())) {
+ return Optional.of(new ImmutablePair<>(Cause.MISSING_ACCOUNT_ID, "Missing account id"));
}
- if (request.getContactInfo().getTypeValue() == 0) {
- return Cause.MISSING_CONTACT_INFO_TYPE;
+ if (contactDetails.getTypeValue() == 0) {
+ return Optional.of(new ImmutablePair<>(Cause.MISSING_CONTACT_INFO_TYPE, "Missing contact info type"));
+
}
- if (request.getContactInfo().getValue() == null || request.getContactInfo().getValue().isEmpty()) {
- return Cause.MISSING_CONTACT_INFO_IDENTIFIER;
+ if (contactDetails.getValue() == null || contactDetails.getValue().isEmpty()) {
+ return Optional.of(new ImmutablePair<>(Cause.MISSING_CONTACT_INFO_IDENTIFIER, "Missing contact info identifier"));
}
- if (!isValidUuid(request.getAccountId())) {
- return Cause.INVALID_ACCOUNT_ID;
+ if (!isValidUuid(accountId)) {
+ return Optional.of(new ImmutablePair<>(Cause.INVALID_ACCOUNT_ID, "Invalid account id"));
}
- return validateContactInfo(request.getContactInfo().getType(), request.getContactInfo().getValue());
+ return validateContactInfo(contactDetails.getType(), contactDetails.getValue());
}
public Cause validateDeleteAuthenticationProviderRequest(DeleteAuthenticationProviderRequest request) {
diff --git a/src/main/java/biz/nynja/account/models/ContactInfo.java b/src/main/java/biz/nynja/account/models/ContactInfo.java
index 982681d9f49ff756f339203d77bd7defcd9d9d1c..9fffa48da04b0e8905defe0ab83842efd6c983c5 100644
--- a/src/main/java/biz/nynja/account/models/ContactInfo.java
+++ b/src/main/java/biz/nynja/account/models/ContactInfo.java
@@ -99,7 +99,6 @@ public class ContactInfo {
if (contactType != null) {
builder.setType(contactType);
}
-
if (getValue() != null) {
builder.setValue(getValue());
}
diff --git a/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditional.java b/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditional.java
index 382adca051ce6bd76ddf501efc52eccaa5da2695..876f037bb6fb55ca60b9a3236a1470c96da16381 100644
--- a/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditional.java
+++ b/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditional.java
@@ -40,4 +40,6 @@ public interface AccountRepositoryAdditional {
boolean deleteAuthenticationProvider(Profile profile, AuthenticationProvider authProvider);
boolean addContactInfo(UUID accountId, ContactInfo contactInfo);
+
+ boolean deleteContactInfo(UUID accountId, ContactInfo contactInfo);
}
diff --git a/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java b/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java
index 8aa3bfc41f8eaedf010ed0cd7943c7e363ff92ce..d1051637087dcefe91d2293d757a89a737000952 100644
--- a/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java
+++ b/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java
@@ -544,6 +544,33 @@ public class AccountRepositoryAdditionalImpl implements AccountRepositoryAdditio
return false;
}
+ @Override
+ public boolean deleteContactInfo(UUID accountId, ContactInfo contactInfo) {
+ Account accountToUpdate = accountRepository.findByAccountId(accountId);
+ if (accountToUpdate == null) {
+ logger.error("Existing account with the provided id {} was not found.", accountId);
+ return false;
+ }
+ Set contactsInfoSet = accountToUpdate.getContactsInfo();
+ if (contactsInfoSet == null) {
+ logger.error("No existing contact info found for account {}.", accountId);
+ return false;
+ }
+ if (!contactsInfoSet.remove(contactInfo)) {
+ logger.error("Error removing contact info from account {}. Existing contact info: {} was not found.",
+ accountId, contactInfo.toString());
+ return false;
+ }
+ accountToUpdate.setContactsInfo(contactsInfoSet);
+ Long timeUpdated = Instant.now().toEpochMilli();
+ accountToUpdate.setLastUpdateTimestamp(timeUpdated);
+ WriteResult wr = cassandraTemplate.update(accountToUpdate, UpdateOptions.builder().ifExists(true).build());
+ if (wr != null && wr.wasApplied()) {
+ return true;
+ }
+ return false;
+ }
+
@Override
public boolean deleteAuthenticationProvider(Profile profile,
AuthenticationProvider authProvider) {
diff --git a/src/main/java/biz/nynja/account/services/AccountServiceImpl.java b/src/main/java/biz/nynja/account/services/AccountServiceImpl.java
index fe0bea37ad83d8bff728a08297d483fc9249c0bd..19fbaddc9904fc89ce51fbe5aff2d39fc517d56d 100644
--- a/src/main/java/biz/nynja/account/services/AccountServiceImpl.java
+++ b/src/main/java/biz/nynja/account/services/AccountServiceImpl.java
@@ -7,13 +7,16 @@ import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
+import java.util.Optional;
import java.util.UUID;
+import org.apache.commons.lang3.tuple.ImmutablePair;
import org.lognet.springboot.grpc.GRpcService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import biz.nynja.account.components.AccountServiceHelper;
+import biz.nynja.account.components.PhoneNumberNormalizer;
import biz.nynja.account.components.Validator;
import biz.nynja.account.grpc.AccountByAccountIdRequest;
import biz.nynja.account.grpc.AccountByAuthenticationProviderRequest;
@@ -35,6 +38,7 @@ import biz.nynja.account.grpc.CreatePendingAccountRequest;
import biz.nynja.account.grpc.CreatePendingAccountResponse;
import biz.nynja.account.grpc.DeleteAccountRequest;
import biz.nynja.account.grpc.DeleteAuthenticationProviderRequest;
+import biz.nynja.account.grpc.DeleteContactInfoRequest;
import biz.nynja.account.grpc.StatusResponse;
import biz.nynja.account.grpc.DeleteProfileRequest;
import biz.nynja.account.grpc.ErrorResponse;
@@ -101,6 +105,9 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Autowired
private AccountServiceHelper accountServiceHelper;
+ @Autowired
+ private PhoneNumberNormalizer phoneNumberNormalizer;
+
@Override
public void createAccount(CreateAccountRequest request, StreamObserver responseObserver) {
@@ -560,19 +567,16 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
StreamObserver responseObserver) {
logger.info("Adding contact info to account requested.");
logger.debug("Adding contact info to account requested: {}", request);
-
- Cause cause = validator.checkAddContactInfoRequest(request);
- if (cause != null) {
- responseObserver
- .onNext(StatusResponse.newBuilder().setError(ErrorResponse.newBuilder().setCause(cause)).build());
- responseObserver.onCompleted();
+ Optional> validationResult = validator
+ .validateContactInfoRequest(request.getAccountId(), request.getContactInfo());
+ if (validationResult.isPresent()) {
+ prepareErrorStatusResponse(responseObserver, validationResult.get().getKey(),
+ validationResult.get().getValue());
return;
}
-
if (request.getContactInfo().getType() == ContactType.PHONE_CONTACT) {
- request = normalizePhoneNumber(request);
+ request = phoneNumberNormalizer.normalizePhoneNumber(request);
}
-
boolean result = accountRepositoryAdditional.addContactInfo(UUID.fromString(request.getAccountId()),
ContactInfo.createContactInfoFromProto(request.getContactInfo()));
if (result) {
@@ -584,21 +588,38 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
}
logger.error("Contact info {}:{} was not added to account {}.", request.getContactInfo().getType().name(),
request.getContactInfo().getValue(), request.getAccountId());
- responseObserver.onNext(StatusResponse.newBuilder()
- .setError(ErrorResponse.newBuilder().setCause(Cause.ERROR_ADDING_CONTACT_INFO)).build());
- responseObserver.onCompleted();
+ prepareErrorStatusResponse(responseObserver, Cause.ERROR_ADDING_CONTACT_INFO, "Error adding contact info");
return;
}
- private AddContactInfoRequest normalizePhoneNumber(AddContactInfoRequest request) {
- // Get the normalized phone number from libphone
- ContactDetails newContactDetails = ContactDetails.newBuilder().setType(request.getContactInfo().getType())
- .setValue(validator.getNormalizedPhoneNumber(request.getContactInfo().getValue()))
- .setLabel(request.getContactInfo().getLabel()).build();
- AddContactInfoRequest newRequest = AddContactInfoRequest.newBuilder().setAccountId(request.getAccountId())
- .setContactInfo(newContactDetails).build();
- request = newRequest;
- return request;
+ @Override
+ public void deleteContactInfoFromAccount(DeleteContactInfoRequest request,
+ StreamObserver responseObserver) {
+ logger.info("Removing contact info from account requested.");
+ logger.debug("Removing contact info from account requested: {}", request);
+ Optional> validationResult = validator
+ .validateContactInfoRequest(request.getAccountId(), request.getContactInfo());
+ if (validationResult.isPresent()) {
+ prepareErrorStatusResponse(responseObserver, validationResult.get().getKey(),
+ validationResult.get().getValue());
+ return;
+ }
+ if (request.getContactInfo().getType() == ContactType.PHONE_CONTACT) {
+ request = phoneNumberNormalizer.normalizePhoneNumber(request);
+ }
+ boolean result = accountRepositoryAdditional.deleteContactInfo(UUID.fromString(request.getAccountId()),
+ ContactInfo.createContactInfoFromProto(request.getContactInfo()));
+ if (result) {
+ logger.info("Contact info {}:{} was removed from account {}.", request.getContactInfo().getType().name(),
+ request.getContactInfo().getValue(), request.getAccountId());
+ responseObserver.onNext(StatusResponse.newBuilder().setStatus("SUCCESS").build());
+ responseObserver.onCompleted();
+ return;
+ }
+ logger.error("Contact info {}:{} was not removed from account {}.", request.getContactInfo().getType().name(),
+ request.getContactInfo().getValue(), request.getAccountId());
+ prepareErrorStatusResponse(responseObserver, Cause.ERROR_REMOVING_CONTACT_INFO, "Error removing contact info");
+ return;
}
@Override
@@ -677,4 +698,11 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
responseObserver.onCompleted();
return;
}
-}
\ No newline at end of file
+
+ public void prepareErrorStatusResponse(StreamObserver responseObserver, Cause error,
+ String message) {
+ responseObserver.onNext(StatusResponse.newBuilder()
+ .setError(ErrorResponse.newBuilder().setCause(error).setMessage(message)).build());
+ responseObserver.onCompleted();
+ }
+}