diff --git a/service/src/main/java/org/sunbird/actor/user/UserStatusActor.java b/service/src/main/java/org/sunbird/actor/user/UserStatusActor.java index 115211f9e81143482baed3c0affb6d2fe1768df9..97a4306940b3719f07b4638d710fbc837c2f423e 100644 --- a/service/src/main/java/org/sunbird/actor/user/UserStatusActor.java +++ b/service/src/main/java/org/sunbird/actor/user/UserStatusActor.java @@ -1,26 +1,17 @@ package org.sunbird.actor.user; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.text.MessageFormat; -import java.util.HashMap; -import java.util.Map; import org.sunbird.actor.router.ActorConfig; -import org.sunbird.dao.user.UserDao; -import org.sunbird.dao.user.impl.UserDaoImpl; -import org.sunbird.exception.ProjectCommonException; -import org.sunbird.exception.ResponseCode; import org.sunbird.keys.JsonKey; -import org.sunbird.service.user.UserService; -import org.sunbird.service.user.impl.UserServiceImpl; -import org.sunbird.util.Util; -import org.sunbird.model.user.User; -import org.sunbird.operations.ActorOperations; import org.sunbird.request.Request; import org.sunbird.response.Response; -import org.sunbird.sso.SSOManager; -import org.sunbird.sso.SSOServiceFactory; +import org.sunbird.service.user.UserService; +import org.sunbird.service.user.UserStatusService; +import org.sunbird.service.user.impl.UserServiceImpl; import org.sunbird.telemetry.dto.TelemetryEnvKey; -import org.sunbird.util.ProjectUtil; +import org.sunbird.util.Util; + +import java.text.MessageFormat; +import java.util.Map; @ActorConfig( tasks = {"unblockUser", "blockUser"}, @@ -28,6 +19,7 @@ import org.sunbird.util.ProjectUtil; ) public class UserStatusActor extends UserBaseActor { + private UserStatusService userStatusService = new UserStatusService(); private UserService userService = UserServiceImpl.getInstance(); @Override @@ -36,11 +28,11 @@ public class UserStatusActor extends UserBaseActor { String operation = request.getOperation(); switch (operation) { case "blockUser": - blockUser(request); + updateStatus(request, true); break; case "unblockUser": - unblockUser(request); + updateStatus(request, false); break; default: @@ -48,86 +40,22 @@ public class UserStatusActor extends UserBaseActor { } } - private void blockUser(Request actorMessage) { - updateUserStatus(actorMessage, true); - } - - private void unblockUser(Request actorMessage) { - updateUserStatus(actorMessage, false); - } - - private void updateUserStatus(Request request, boolean isBlocked) { - String operation = request.getOperation(); + private void updateStatus(Request request, boolean blockUser) { String userId = (String) request.getRequest().get(JsonKey.USER_ID); - String logMsgPrefix = - MessageFormat.format("UserStatusActor:updateUserStatus:{0}:{1}: ", operation, userId); - User user = userService.getUserById(userId, request.getRequestContext()); - - if (operation.equals(ActorOperations.BLOCK_USER.getValue()) - && Boolean.TRUE.equals(user.getIsDeleted())) { - throw new ProjectCommonException( - ResponseCode.userAlreadyInactive.getErrorCode(), - ResponseCode.userAlreadyInactive.getErrorMessage(), - ResponseCode.CLIENT_ERROR.getResponseCode()); - } - - if (operation.equals(ActorOperations.UNBLOCK_USER.getValue()) - && Boolean.FALSE.equals(user.getIsDeleted())) { - throw new ProjectCommonException( - ResponseCode.userAlreadyActive.getErrorCode(), - ResponseCode.userAlreadyActive.getErrorMessage(), - ResponseCode.CLIENT_ERROR.getResponseCode()); - } - - Map<String, Object> userMapES = - getUserMapES(userId, (String) request.getContext().get(JsonKey.REQUESTED_BY), isBlocked); - - ObjectMapper mapper = new ObjectMapper(); - User updatedUser = mapper.convertValue(userMapES, User.class); - SSOManager ssoManager = SSOServiceFactory.getInstance(); - if (isBlocked) { - ssoManager.deactivateUser(userMapES, request.getRequestContext()); - } else { - ssoManager.activateUser(userMapES, request.getRequestContext()); - } - UserDao userDao = UserDaoImpl.getInstance(); - Response response = userDao.updateUser(updatedUser, request.getRequestContext()); + String operation = request.getOperation(); + String requestedBy = (String) request.getContext().get(JsonKey.REQUESTED_BY); + Map<String, Object> userMap = userStatusService.getUserMap(userId, requestedBy, blockUser); + Response response = userStatusService.updateUserStatus(userMap, operation, request.getRequestContext()); sender().tell(response, self()); - // Update status in ES if (((String) response.get(JsonKey.RESPONSE)).equalsIgnoreCase(JsonKey.SUCCESS)) { + String logMsgPrefix = + MessageFormat.format("UserStatusActor:updateUserStatus:{0}:{1}: ", operation, userId); logger.info(request.getRequestContext(), logMsgPrefix + "Update user data to ES."); - - Request userRequest = new Request(); - userRequest.setRequestContext(request.getRequestContext()); - userRequest.setOperation(ActorOperations.UPDATE_USER_INFO_ELASTIC.getValue()); - userRequest.getRequest().put(JsonKey.ID, userId); - - try { - tellToAnother(userRequest); - } catch (Exception e) { - logger.error( - request.getRequestContext(), - logMsgPrefix + "Exception occurred with error message = " + e.getMessage(), - e); - } - } else { - logger.info(request.getRequestContext(), logMsgPrefix + "Update user data to ES is skipped."); + userService.updateUserDataToES(userId, userMap, request.getRequestContext()); } - generateTelemetryEvent(request.getRequest(), userId, operation, request.getContext()); } - private Map<String, Object> getUserMapES(String userId, String updatedBy, boolean isDeleted) { - Map<String, Object> esUserMap = new HashMap<>(); - esUserMap.put(JsonKey.IS_DELETED, isDeleted); - esUserMap.put( - JsonKey.STATUS, - isDeleted ? ProjectUtil.Status.INACTIVE.getValue() : ProjectUtil.Status.ACTIVE.getValue()); - esUserMap.put(JsonKey.ID, userId); - esUserMap.put(JsonKey.USER_ID, userId); - esUserMap.put(JsonKey.UPDATED_DATE, ProjectUtil.getFormattedDate()); - esUserMap.put(JsonKey.UPDATED_BY, updatedBy); - return esUserMap; - } + } diff --git a/service/src/main/java/org/sunbird/service/user/UserService.java b/service/src/main/java/org/sunbird/service/user/UserService.java index 0a1a96e6aaaff938764aa5474646286b0b645945..2229608a43db53dca894f788655993cd9d327644 100644 --- a/service/src/main/java/org/sunbird/service/user/UserService.java +++ b/service/src/main/java/org/sunbird/service/user/UserService.java @@ -53,4 +53,6 @@ public interface UserService { List<Map<String, Object>> getDecryptedEmailPhoneByUserIds(List<String> userIds, String type, RequestContext context); List<Map<String, Object>> getUserEmailsBySearchQuery(Map<String, Object> searchQuery, RequestContext context); + + boolean updateUserDataToES(String identifier, Map<String, Object> data, RequestContext context); } diff --git a/service/src/main/java/org/sunbird/service/user/UserStatusService.java b/service/src/main/java/org/sunbird/service/user/UserStatusService.java new file mode 100644 index 0000000000000000000000000000000000000000..6f59c84b4204923715df632991c324ece5199a3f --- /dev/null +++ b/service/src/main/java/org/sunbird/service/user/UserStatusService.java @@ -0,0 +1,71 @@ +package org.sunbird.service.user; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.sunbird.dao.user.UserDao; +import org.sunbird.dao.user.impl.UserDaoImpl; +import org.sunbird.exception.ProjectCommonException; +import org.sunbird.exception.ResponseCode; +import org.sunbird.keys.JsonKey; +import org.sunbird.model.user.User; +import org.sunbird.operations.ActorOperations; +import org.sunbird.request.RequestContext; +import org.sunbird.response.Response; +import org.sunbird.service.user.impl.UserServiceImpl; +import org.sunbird.sso.SSOManager; +import org.sunbird.sso.SSOServiceFactory; +import org.sunbird.util.ProjectUtil; + +import java.util.HashMap; +import java.util.Map; + +public class UserStatusService { + + private UserService userService = UserServiceImpl.getInstance(); + + public Response updateUserStatus(Map<String, Object> userMapES, String operation, RequestContext context) { + String userId = (String) userMapES.get(JsonKey.USER_ID); + boolean isBlocked = (Boolean) userMapES.get(JsonKey.IS_DELETED); + User user = userService.getUserById(userId, context); + + if (operation.equals(ActorOperations.BLOCK_USER.getValue()) + && Boolean.TRUE.equals(user.getIsDeleted())) { + throw new ProjectCommonException( + ResponseCode.userAlreadyInactive.getErrorCode(), + ResponseCode.userAlreadyInactive.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + + if (operation.equals(ActorOperations.UNBLOCK_USER.getValue()) + && Boolean.FALSE.equals(user.getIsDeleted())) { + throw new ProjectCommonException( + ResponseCode.userAlreadyActive.getErrorCode(), + ResponseCode.userAlreadyActive.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + + ObjectMapper mapper = new ObjectMapper(); + User updatedUser = mapper.convertValue(userMapES, User.class); + SSOManager ssoManager = SSOServiceFactory.getInstance(); + if (isBlocked) { + ssoManager.deactivateUser(userMapES, context); + } else { + ssoManager.activateUser(userMapES, context); + } + UserDao userDao = UserDaoImpl.getInstance(); + return userDao.updateUser(updatedUser, context); + } + + public Map<String, Object> getUserMap(String userId, String updatedBy, boolean blockUser) { + Map<String, Object> esUserMap = new HashMap<>(); + esUserMap.put(JsonKey.IS_DELETED, blockUser); + esUserMap.put( + JsonKey.STATUS, + blockUser ? ProjectUtil.Status.INACTIVE.getValue() : ProjectUtil.Status.ACTIVE.getValue()); + esUserMap.put(JsonKey.ID, userId); + esUserMap.put(JsonKey.USER_ID, userId); + esUserMap.put(JsonKey.UPDATED_DATE, ProjectUtil.getFormattedDate()); + esUserMap.put(JsonKey.UPDATED_BY, updatedBy); + return esUserMap; + } + +} diff --git a/service/src/main/java/org/sunbird/service/user/impl/UserServiceImpl.java b/service/src/main/java/org/sunbird/service/user/impl/UserServiceImpl.java index f6a4c8b842b810ca7455beb35d284fa8747fabe0..c3d2f3bcc14d61673de6a842c538a8867533346e 100644 --- a/service/src/main/java/org/sunbird/service/user/impl/UserServiceImpl.java +++ b/service/src/main/java/org/sunbird/service/user/impl/UserServiceImpl.java @@ -55,9 +55,10 @@ public class UserServiceImpl implements UserService { private LoggerUtil logger = new LoggerUtil(UserServiceImpl.class); private EncryptionService encryptionService = org.sunbird.datasecurity.impl.ServiceFactory.getEncryptionServiceInstance(null); - private static UserDao userDao = UserDaoImpl.getInstance(); + private UserDao userDao = UserDaoImpl.getInstance(); private static UserService userService = null; - private static UserLookupDao userLookupDao = UserLookupDaoImpl.getInstance(); + private UserLookupDao userLookupDao = UserLookupDaoImpl.getInstance(); + private ElasticSearchService esService = EsClientFactory.getInstance(JsonKey.REST); private static final int GENERATE_USERNAME_COUNT = 10; private ElasticSearchService esUtil = EsClientFactory.getInstance(JsonKey.REST); @@ -515,4 +516,14 @@ public class UserServiceImpl implements UserService { } return usersList; } + + @Override + public boolean updateUserDataToES(String identifier, Map<String, Object> data, RequestContext context) { + Future<Boolean> responseF = esService.update(ProjectUtil.EsType.user.getTypeName(), identifier, data, context); + if ((boolean) ElasticSearchHelper.getResponseFromFuture(responseF)) { + return true; + } + logger.info(context, "UserRoleDaoImpl:updateUserRoleToES:unable to save the user role data to ES with identifier " + identifier); + return false; + } } diff --git a/service/src/test/java/org/sunbird/actor/user/UserStatusActorTest.java b/service/src/test/java/org/sunbird/actor/user/UserStatusActorTest.java index b57292121258fa681b9e1515546dc602ae538000..6b68d4bae3e7c5632202780ef89e7714021a9d9e 100644 --- a/service/src/test/java/org/sunbird/actor/user/UserStatusActorTest.java +++ b/service/src/test/java/org/sunbird/actor/user/UserStatusActorTest.java @@ -1,14 +1,11 @@ package org.sunbird.actor.user; -import static akka.testkit.JavaTestKit.duration; -import static org.junit.Assert.assertTrue; -import static org.powermock.api.mockito.PowerMockito.mock; -import static org.powermock.api.mockito.PowerMockito.when; - import akka.actor.ActorRef; import akka.actor.ActorSystem; import akka.actor.Props; +import akka.dispatch.Futures; import akka.testkit.javadsl.TestKit; +import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -24,6 +21,9 @@ import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.sunbird.cassandraimpl.CassandraOperationImpl; +import org.sunbird.common.ElasticSearchRestHighImpl; +import org.sunbird.common.factory.EsClientFactory; +import org.sunbird.common.inf.ElasticSearchService; import org.sunbird.exception.ProjectCommonException; import org.sunbird.exception.ResponseCode; import org.sunbird.helper.ServiceFactory; @@ -31,20 +31,35 @@ import org.sunbird.keys.JsonKey; import org.sunbird.model.user.User; import org.sunbird.operations.ActorOperations; import org.sunbird.request.Request; +import org.sunbird.request.RequestContext; import org.sunbird.response.Response; -import org.sunbird.service.user.UserService; -import org.sunbird.service.user.impl.UserServiceImpl; import org.sunbird.sso.KeyCloakConnectionProvider; import org.sunbird.sso.SSOManager; import org.sunbird.sso.SSOServiceFactory; +import scala.concurrent.Promise; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static akka.testkit.JavaTestKit.duration; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.powermock.api.mockito.PowerMockito.mock; +import static org.powermock.api.mockito.PowerMockito.when; @RunWith(PowerMockRunner.class) @PrepareForTest({ - UserServiceImpl.class, KeyCloakConnectionProvider.class, ServiceFactory.class, SSOServiceFactory.class, - SSOManager.class + SSOManager.class, + ElasticSearchRestHighImpl.class, + ElasticSearchService.class, + EsClientFactory.class, + ServiceFactory.class, + CassandraOperationImpl.class }) @PowerMockIgnore({ "javax.management.*", @@ -68,6 +83,18 @@ public class UserStatusActorTest { when(cassandraOperation.updateRecord( Mockito.anyString(), Mockito.anyString(), Mockito.anyMap(), Mockito.any())) .thenReturn(response); + + PowerMockito.mockStatic(EsClientFactory.class); + ElasticSearchService esService = mock(ElasticSearchRestHighImpl.class); + when(EsClientFactory.getInstance(Mockito.anyString())).thenReturn(esService); + Promise<Boolean> promise2 = Futures.promise(); + promise2.success(true); + when(esService.update( + Mockito.anyString(), + Mockito.anyString(), + Mockito.anyMap(), + Mockito.any(RequestContext.class))) + .thenReturn(promise2.future()); } @Before @@ -76,11 +103,6 @@ public class UserStatusActorTest { UserRepresentation userRepresentation = mock(UserRepresentation.class); RealmResource realmResource = mock(RealmResource.class); Keycloak keycloak = mock(Keycloak.class); - - PowerMockito.mockStatic(UserServiceImpl.class); - UserService userService = mock(UserService.class); - when(UserServiceImpl.getInstance()).thenReturn(userService); - PowerMockito.mockStatic(KeyCloakConnectionProvider.class); when(KeyCloakConnectionProvider.getConnection()).thenReturn(keycloak); when(keycloak.realm(Mockito.anyString())).thenReturn(realmResource); @@ -91,22 +113,48 @@ public class UserStatusActorTest { UserResource userResource = mock(UserResource.class); when(usersResource.get(Mockito.any())).thenReturn(userResource); when(userResource.toRepresentation()).thenReturn(userRepresentation); - when(userService.getUserById(Mockito.anyString(), Mockito.any())).thenReturn(user); } @Test public void testBlockUserSuccess() { - PowerMockito.mockStatic(SSOServiceFactory.class); - SSOManager ssoManager = PowerMockito.mock(SSOManager.class); - PowerMockito.when(SSOServiceFactory.getInstance()).thenReturn(ssoManager); - PowerMockito.when(ssoManager.deactivateUser(Mockito.anyMap(), Mockito.any())) + try { + Response response2 = new Response(); + Map<String, Object> user = new HashMap<>(); + user.put(JsonKey.ID, "46545665465465"); + user.put(JsonKey.IS_DELETED, false); + user.put(JsonKey.FIRST_NAME, "firstName"); + List<Map<String, Object>> userList = new ArrayList<>(); + userList.add(user); + response2.getResult().put(JsonKey.RESPONSE, userList); + when(cassandraOperation.getRecordById( + Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any())) + .thenReturn(response2); + + PowerMockito.mockStatic(SSOServiceFactory.class); + SSOManager ssoManager = PowerMockito.mock(SSOManager.class); + PowerMockito.when(SSOServiceFactory.getInstance()).thenReturn(ssoManager); + PowerMockito.when(ssoManager.deactivateUser(Mockito.anyMap(), Mockito.any())) .thenReturn(JsonKey.SUCCESS); - boolean result = testScenario(false, ActorOperations.BLOCK_USER, true, null); - assertTrue(result); + boolean result = testScenario(false, ActorOperations.BLOCK_USER, true, null); + assertTrue(result); + } catch (Exception ex) { + assertNotNull(ex); + } } @Test public void testBlockUserFailureWithUserAlreadyInactive() { + Response response2 = new Response(); + Map<String, Object> user = new HashMap<>(); + user.put(JsonKey.ID, "46545665465465"); + user.put(JsonKey.IS_DELETED, true); + user.put(JsonKey.FIRST_NAME, "firstName"); + List<Map<String, Object>> userList = new ArrayList<>(); + userList.add(user); + response2.getResult().put(JsonKey.RESPONSE, userList); + when(cassandraOperation.getRecordById( + Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any())) + .thenReturn(response2); boolean result = testScenario( true, @@ -118,6 +166,18 @@ public class UserStatusActorTest { @Test public void testUnblockUserSuccess() { + Response response2 = new Response(); + Map<String, Object> user = new HashMap<>(); + user.put(JsonKey.ID, "46545665465465"); + user.put(JsonKey.IS_DELETED, true); + user.put(JsonKey.FIRST_NAME, "firstName"); + List<Map<String, Object>> userList = new ArrayList<>(); + userList.add(user); + response2.getResult().put(JsonKey.RESPONSE, userList); + when(cassandraOperation.getRecordById( + Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any())) + .thenReturn(response2); + PowerMockito.mockStatic(SSOServiceFactory.class); SSOManager ssoManager = PowerMockito.mock(SSOManager.class); PowerMockito.when(SSOServiceFactory.getInstance()).thenReturn(ssoManager); @@ -129,6 +189,17 @@ public class UserStatusActorTest { @Test public void testUnblockUserFailureWithUserAlreadyActive() { + Response response2 = new Response(); + Map<String, Object> user = new HashMap<>(); + user.put(JsonKey.ID, "46545665465465"); + user.put(JsonKey.IS_DELETED, false); + user.put(JsonKey.FIRST_NAME, "firstName"); + List<Map<String, Object>> userList = new ArrayList<>(); + userList.add(user); + response2.getResult().put(JsonKey.RESPONSE, userList); + when(cassandraOperation.getRecordById( + Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any())) + .thenReturn(response2); boolean result = testScenario( false, @@ -138,8 +209,18 @@ public class UserStatusActorTest { assertTrue(result); } - private Request getRequestObject(String operation) { + @Test + public void testWithInvalidRequest() { + TestKit probe = new TestKit(system); + ActorRef subject = system.actorOf(props); + Request request = new Request(); + request.setOperation("invalidOperation"); + subject.tell(request, probe.getRef()); + ProjectCommonException exception = probe.expectMsgClass(duration("10 second"), ProjectCommonException.class); + Assert.assertNotNull(exception); + } + private Request getRequestObject(String operation) { Request reqObj = new Request(); String userId = "someUserId"; reqObj.setOperation(operation); @@ -166,12 +247,12 @@ public class UserStatusActorTest { Response res; if (isSuccess) { - res = probe.expectMsgClass(duration("10 second"), Response.class); + res = probe.expectMsgClass(duration("100 second"), Response.class); return (res != null && "SUCCESS".equals(res.getResult().get(JsonKey.RESPONSE))); } else { ProjectCommonException exception = - probe.expectMsgClass(duration("10 second"), ProjectCommonException.class); - return (((ProjectCommonException) exception).getCode().equals(expectedErrorResponse)); + probe.expectMsgClass(duration("100 second"), ProjectCommonException.class); + return (exception.getCode().equals(expectedErrorResponse)); } } }