You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by pr...@apache.org on 2022/01/12 03:30:30 UTC

[ranger] branch master updated: RANGER-3576: service creation is failing intermittently due to DB unique key constraint violation

This is an automated email from the ASF dual-hosted git repository.

pradeep pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new 277f461  RANGER-3576: service creation is failing intermittently due to DB unique key constraint violation
277f461 is described below

commit 277f4610118c2cdb6ce9e2bf31e60f4d5b986c59
Author: pradeep <pr...@apache.org>
AuthorDate: Sun Jan 9 21:49:22 2022 +0530

    RANGER-3576: service creation is failing intermittently due to DB unique key constraint violation
---
 .../main/java/org/apache/ranger/biz/XUserMgr.java  | 183 +++++++++++----------
 .../java/org/apache/ranger/biz/TestXUserMgr.java   |  68 ++++----
 .../ranger/ugsyncutil/model/GroupUserInfo.java     |   2 +-
 3 files changed, 140 insertions(+), 113 deletions(-)

diff --git a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
index 0eb582c..853007b 100755
--- a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
@@ -35,6 +35,7 @@ import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.ranger.biz.ServiceDBStore.REMOVE_REF_TYPE;
 import org.apache.ranger.common.*;
+import org.apache.ranger.common.db.RangerTransactionSynchronizationAdapter;
 import org.apache.ranger.entity.XXGroupPermission;
 import org.apache.ranger.entity.XXModuleDef;
 import org.apache.ranger.entity.XXUserPermission;
@@ -160,6 +161,9 @@ public class XUserMgr extends XUserMgrBase {
 	StringUtil stringUtil;
 
 	@Autowired
+	RangerTransactionSynchronizationAdapter transactionSynchronizationAdapter;
+
+	@Autowired
 	@Qualifier(value = "transactionManager")
 	PlatformTransactionManager txManager;
 
@@ -2513,94 +2517,19 @@ public class XUserMgr extends XUserMgrBase {
 			throw restErrorUtil.createRESTException("Please provide a valid username.",MessageEnums.INVALID_INPUT_DATA);
 		}
 
-		VXUser vXUser = null;
-		VXPortalUser vXPortalUser=null;
 		XXUser xxUser = daoManager.getXXUser().findByUserName(userName);
-		XXPortalUser xXPortalUser = daoManager.getXXPortalUser().findByLoginId(userName);
-		String actualPassword = "";
-		if(xxUser!=null){
-			vXUser = xUserService.populateViewBean(xxUser);
-			return vXUser;
+		if (xxUser == null) {
+			transactionSynchronizationAdapter.executeOnTransactionCommit(new ExternalUserCreator(userName));
 		}
-		if(xxUser==null){
-			vXUser=new VXUser();
-			vXUser.setName(userName);
-			vXUser.setUserSource(RangerCommonEnums.USER_EXTERNAL);
-			vXUser.setDescription(vXUser.getName());
-			actualPassword = vXUser.getPassword();
-		}
-		if(xXPortalUser==null){
-            int noOfRetries = 0;
-			do {
-			    try {
-                    TransactionTemplate txTemplate = new TransactionTemplate(txManager);
-                    txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
-                    noOfRetries++;
-					final VXUser vxUserFinal = vXUser;
-                    xXPortalUser = txTemplate.execute(new TransactionCallback<XXPortalUser>() {
-                        @Override
-                        public XXPortalUser doInTransaction(TransactionStatus status) {
-                            XXPortalUser ret = daoManager.getXXPortalUser().findByLoginId(userName);
-                            if (ret == null) {
-								if (logger.isDebugEnabled()) {
-									logger.debug("createServiceConfigUser(): Couldn't find " + userName + " and hence creating user in x_portal_user table");
-								}
-								VXPortalUser vXPortalUser=new VXPortalUser();
-								vXPortalUser.setLoginId(userName);
-								vXPortalUser.setEmailAddress(vxUserFinal.getEmailAddress());
-								vXPortalUser.setFirstName(vxUserFinal.getFirstName());
-								vXPortalUser.setLastName(vxUserFinal.getLastName());
-								vXPortalUser.setPassword(vxUserFinal.getPassword());
-								vXPortalUser.setUserSource(RangerCommonEnums.USER_EXTERNAL);
-								ArrayList<String> roleList = new ArrayList<String>();
-								roleList.add(RangerConstants.ROLE_USER);
-								vXPortalUser.setUserRoleList(roleList);
-								ret = userMgr.mapVXPortalUserToXXPortalUser(vXPortalUser);
-                                ret = userMgr.createUser(ret, RangerCommonEnums.STATUS_ENABLED, roleList);
-                                if (logger.isDebugEnabled()) {
-                                        logger.debug("createServiceConfigUser(): Successfully created user in x_portal_user table " + ret.getLoginId());
-                                }
-                            }
-                           return ret;
-                        }
-                    });
-                } catch (Exception excp) {
-                    logger.warn("createServiceConfigUser(): Failed to update x_portal_user table and retry count =  " + noOfRetries);
-                    xXPortalUser = null;
-                }
-            } while (noOfRetries < MAX_DB_TRANSACTION_RETRIES && (xXPortalUser == null));
-		}
-		VXUser createdXUser=null;
-		if (xxUser == null && vXUser != null) {
-			try {
-				createdXUser = xUserService.createResource(vXUser);
-			} catch (Exception ex) {
-				logger.error("Error creating user: " + vXUser.getName(), ex);
-			}
-		}
-		if(createdXUser!=null){
-			try{
-				logger.info("User created: "+createdXUser.getName());
-				createdXUser.setPassword(actualPassword);
-				List<XXTrxLog> trxLogList = xUserService.getTransactionLog(createdXUser, "create");
-				String hiddenPassword = PropertiesUtil.getProperty("ranger.password.hidden", "*****");
-				createdXUser.setPassword(hiddenPassword);
-				xaBizUtil.createTrxLog(trxLogList);
-				if(xXPortalUser!=null){
-					vXPortalUser=userMgr.mapXXPortalUserToVXPortalUserForDefaultAccount(xXPortalUser);
-					assignPermissionToUser(vXPortalUser, true);
-				}
-			}catch(Exception ex){
-				logger.error("Error while assigning permissions to user: "+createdXUser.getName(),ex);
-			}
-		}else{
-			xxUser = daoManager.getXXUser().findByUserName(userName);
-			if(xxUser!=null){
-				createdXUser = xUserService.populateViewBean(xxUser);
-			}
+
+		xxUser = daoManager.getXXUser().findByUserName(userName);
+		VXUser vXUser = null;
+		if (xxUser != null) {
+			vXUser = xUserService.populateViewBean(xxUser);
 		}
-		return createdXUser;
+		return vXUser;
 	}
+
 	protected void validatePassword(VXUser vXUser) {
 		if (vXUser.getPassword() != null && !vXUser.getPassword().isEmpty()) {
 			boolean checkPassword = false;
@@ -3216,4 +3145,90 @@ public class XUserMgr extends XUserMgrBase {
 		vXUserList = xUserService.lookupXUsers(searchCriteria, vXUserList);
 		return vXUserList;
 	}
+
+	private class ExternalUserCreator implements Runnable {
+		private String userName;
+
+		ExternalUserCreator(String user) {
+			this.userName = user;
+		}
+
+		@Override
+		public void run() {
+			createExternalUser();
+		}
+
+		private void createExternalUser() {
+			if (logger.isDebugEnabled()) {
+				logger.debug("==> ExternalUserCreator.createExternalUser(username=" + userName);
+			}
+
+			XXPortalUser xXPortalUser = daoManager.getXXPortalUser().findByLoginId(userName);
+			if (xXPortalUser == null) {
+				if (logger.isDebugEnabled()) {
+					logger.debug("createExternalUser(): Couldn't find " + userName+ " and hence creating user in x_portal_user table");
+				}
+				VXPortalUser vXPortalUser = new VXPortalUser();
+				vXPortalUser.setLoginId(userName);
+				vXPortalUser.setUserSource(RangerCommonEnums.USER_EXTERNAL);
+				ArrayList<String> roleList = new ArrayList<String>();
+				roleList.add(RangerConstants.ROLE_USER);
+				vXPortalUser.setUserRoleList(roleList);
+				xXPortalUser = userMgr.mapVXPortalUserToXXPortalUser(vXPortalUser);
+				try {
+					xXPortalUser = userMgr.createUser(xXPortalUser, RangerCommonEnums.STATUS_ENABLED, roleList);
+					if (logger.isDebugEnabled()) {
+						logger.debug("createExternalUser(): Successfully created user in x_portal_user table " + xXPortalUser.getLoginId());
+					}
+				} catch (Exception ex) {
+					throw new RuntimeException("Failed to create user " + userName + " in x_portal_user table. retrying", ex);
+				}
+			}
+
+			VXUser createdXUser = null;
+			String actualPassword = "";
+			XXUser xXUser = daoManager.getXXUser().findByUserName(userName);
+			if (xXPortalUser != null && xXUser == null) {
+				VXUser vXUser = new VXUser();
+				vXUser.setName(userName);
+				vXUser.setUserSource(RangerCommonEnums.USER_EXTERNAL);
+				vXUser.setDescription(vXUser.getName());
+				actualPassword = vXUser.getPassword();
+				try {
+					createdXUser = xUserService.createResource(vXUser);
+					if (logger.isDebugEnabled()) {
+						logger.debug("createExternalUser(): Successfully created user in x_user table " + vXUser.getName());
+					}
+				} catch (Exception ex) {
+					throw new RuntimeException("Failed to create user " + userName + " in x_user table. retrying", ex);
+				}
+			}
+
+			if (createdXUser != null) {
+				logger.info("User created: " + createdXUser.getName());
+				try {
+					createdXUser.setPassword(actualPassword);
+					List<XXTrxLog> trxLogList = xUserService.getTransactionLog(createdXUser, "create");
+					String hiddenPassword = PropertiesUtil.getProperty("ranger.password.hidden", "*****");
+					createdXUser.setPassword(hiddenPassword);
+					xaBizUtil.createTrxLog(trxLogList);
+				} catch (Exception ex) {
+					throw new RuntimeException("Error while creating trx logs for user: " + createdXUser.getName(), ex);
+				}
+
+				try {
+					if (xXPortalUser != null) {
+						VXPortalUser createdXPortalUser = userMgr.mapXXPortalUserToVXPortalUserForDefaultAccount(xXPortalUser);
+						assignPermissionToUser(createdXPortalUser, true);
+					}
+				} catch (Exception ex) {
+					throw new RuntimeException("Error while assigning permissions to user: " + createdXUser.getName(), ex);
+				}
+			}
+
+			if (logger.isDebugEnabled()) {
+				logger.debug("<== ExternalUserCreator.createExternalUser(username=" + userName);
+			}
+		}
+	}
 }
diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java
index 945bba4..bee65bb 100644
--- a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java
+++ b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java
@@ -37,6 +37,7 @@ import org.apache.ranger.common.RangerConstants;
 import org.apache.ranger.common.SearchCriteria;
 import org.apache.ranger.common.StringUtil;
 import org.apache.ranger.common.UserSessionBase;
+import org.apache.ranger.common.db.RangerTransactionSynchronizationAdapter;
 import org.apache.ranger.db.RangerDaoManager;
 import org.apache.ranger.db.XXAuditMapDao;
 import org.apache.ranger.db.XXAuthSessionDao;
@@ -226,6 +227,10 @@ public class TestXUserMgr {
 
 	@Mock
 	XUgsyncAuditInfoService xUgsyncAuditInfoService;
+
+	@Mock
+	RangerTransactionSynchronizationAdapter transactionSynchronizationAdapter;
+
 	@Rule
 	public ExpectedException thrown = ExpectedException.none();
 
@@ -2108,36 +2113,40 @@ public class TestXUserMgr {
 	@Test
 	public void test49createServiceConfigUser() {
 		XXUserDao xxUserDao = Mockito.mock(XXUserDao.class);
-		XXPortalUserDao userDao = Mockito.mock(XXPortalUserDao.class);
-		XXModuleDefDao xXModuleDefDao = Mockito.mock(XXModuleDefDao.class);
 		VXUser vxUser = vxUser();
 		XXUser xXUser = xxUser(vxUser);
 		VXPortalUser userProfile = userProfile();
-		XXPortalUser xXPortalUser = xxPortalUser(userProfile);
 		Collection<String> userRoleList =getRoleList();
 		VXUserPermission vXUserPermission=vxUserPermission();
 		XXUserPermission xUserPermissionObj = xxUserPermission();
 		xUserPermissionObj.setModuleId(vXUserPermission.getModuleId());
 		xUserPermissionObj.setUserId(vXUserPermission.getUserId());
-		List<XXModuleDef> xXModuleDefs = xxModuleDefs();
 		Mockito.when(daoManager.getXXUser()).thenReturn(xxUserDao);
 		Mockito.when(xxUserDao.findByUserName(vxUser.getName())).thenReturn(xXUser);
-		Mockito.when(daoManager.getXXPortalUser()).thenReturn(userDao);
-		Mockito.when(userDao.findByLoginId(vxUser.getName())).thenReturn(xXPortalUser);
 		Mockito.when(xUserService.populateViewBean(xXUser)).thenReturn(vxUser);
 		VXUser serviceConfigUser=xUserMgr.createServiceConfigUser(vxUser.getName());
 		Assert.assertNotNull(serviceConfigUser);
 		Assert.assertEquals(xXUser.getName(), serviceConfigUser.getName());
 		Mockito.when(daoManager.getXXUser()).thenReturn(xxUserDao);
-		Mockito.when(xxUserDao.findByUserName(vxUser.getName())).thenReturn(null);
-		Mockito.when(daoManager.getXXPortalUser()).thenReturn(userDao);
-		Mockito.when(userDao.findByLoginId(vxUser.getName())).thenReturn(null);
-		Mockito.when(userDao.findByLoginId(vxUser.getName())).thenReturn(null);
-		Mockito.when(xUserService.createResource((VXUser) Mockito.any())).thenReturn(vxUser);
+		Mockito.when(xxUserDao.findByUserName(vxUser.getName())).thenReturn(null, xXUser);
 		Mockito.when(daoManager.getXXUser()).thenReturn(xxUserDao);
 		UserSessionBase userSession = Mockito.mock(UserSessionBase.class);
 		Set<UserSessionBase> userSessions = new HashSet<UserSessionBase>();
 		userSessions.add(userSession);
+
+		userProfile.setUserRoleList(userRoleList);
+		List<XXUserPermission> xUserPermissionsList = new ArrayList<XXUserPermission>();
+		XXUserPermission xUserPermissionObj2 = new XXUserPermission();
+		xUserPermissionObj2.setAddedByUserId(userId);
+		xUserPermissionObj2.setCreateTime(new Date());
+		xUserPermissionObj2.setId(userId);
+		xUserPermissionObj2.setIsAllowed(1);
+		xUserPermissionObj2.setModuleId(1L);
+		xUserPermissionObj2.setUpdatedByUserId(userId);
+		xUserPermissionObj2.setUpdateTime(new Date());
+		xUserPermissionObj2.setUserId(userId);
+		xUserPermissionsList.add(xUserPermissionObj2);
+
 		serviceConfigUser=xUserMgr.createServiceConfigUser(vxUser.getName());
 		Assert.assertNotNull(serviceConfigUser);
 		Assert.assertEquals(xXUser.getName(), serviceConfigUser.getName());
@@ -3306,29 +3315,20 @@ public class TestXUserMgr {
 	@Test
 	public void test99createServiceConfigUser() {
 		XXUserDao xxUserDao = Mockito.mock(XXUserDao.class);
-		XXPortalUserDao userDao = Mockito.mock(XXPortalUserDao.class);
 		VXUser vxUser = vxUser();
 		XXUser xXUser = xxUser(vxUser);
-		VXPortalUser userProfile = userProfile();
-		XXPortalUser xXPortalUser = xxPortalUser(userProfile);
-		Collection<String> userRoleList =getRoleList();
 		VXUserPermission vXUserPermission=vxUserPermission();
 		XXUserPermission xUserPermissionObj = xxUserPermission();
 		xUserPermissionObj.setModuleId(vXUserPermission.getModuleId());
 		xUserPermissionObj.setUserId(vXUserPermission.getUserId());
 		Mockito.when(daoManager.getXXUser()).thenReturn(xxUserDao);
 		Mockito.when(xxUserDao.findByUserName(vxUser.getName())).thenReturn(xXUser);
-		Mockito.when(daoManager.getXXPortalUser()).thenReturn(userDao);
-		Mockito.when(userDao.findByLoginId(vxUser.getName())).thenReturn(xXPortalUser);
 		Mockito.when(xUserService.populateViewBean(xXUser)).thenReturn(vxUser);
 		VXUser serviceConfigUser=xUserMgr.createServiceConfigUser(vxUser.getName());
 		Assert.assertNotNull(serviceConfigUser);
 		Assert.assertEquals(xXUser.getName(), serviceConfigUser.getName());
 		Mockito.when(daoManager.getXXUser()).thenReturn(xxUserDao);
 		Mockito.when(xxUserDao.findByUserName(vxUser.getName())).thenReturn(null);
-		Mockito.when(daoManager.getXXPortalUser()).thenReturn(userDao);
-		Mockito.when(userDao.findByLoginId(vxUser.getName())).thenReturn(null);
-		Mockito.when(xUserService.createResource((VXUser) Mockito.any())).thenReturn(null);
 		Mockito.when(daoManager.getXXUser()).thenReturn(xxUserDao);
 		UserSessionBase userSession = Mockito.mock(UserSessionBase.class);
 		Set<UserSessionBase> userSessions = new HashSet<UserSessionBase>();
@@ -4624,8 +4624,6 @@ public class TestXUserMgr {
 	public void test130UpdateXUser() {
 		destroySession();
 		setup();
-		destroySession();
-		setup();
 		VXUser vxUser = vxUser();
 		Mockito.when(restErrorUtil.createRESTException("Please provide a valid username.",MessageEnums.INVALID_INPUT_DATA)).thenThrow(new WebApplicationException());
 		thrown.expect(WebApplicationException.class);
@@ -4646,16 +4644,30 @@ public class TestXUserMgr {
 	public void test132CreateExternalUser() {
 		destroySession();
 		setup();
-		setup();
+		ArrayList<String> roleList = new ArrayList<String>();
+		roleList.add(RangerConstants.ROLE_USER);
+		VXPortalUser vXPortalUser = userProfile();
 		XXUserDao xxUserDao = Mockito.mock(XXUserDao.class);
 		VXUser vXUser = vxUser();
 		VXUser createdXUser = vxUser();
+		XXUser xXUser = xxUser(vXUser);
 		Mockito.when(daoManager.getXXUser()).thenReturn(xxUserDao);
-		Mockito.when(xxUserDao.findByUserName(vXUser.getName())).thenReturn(null);
-		XXPortalUserDao xXPortalUserDao = Mockito.mock(XXPortalUserDao.class);
-		Mockito.when(daoManager.getXXPortalUser()).thenReturn(xXPortalUserDao);
-		Mockito.when(xXPortalUserDao.findByLoginId(vXUser.getName().trim())).thenReturn(null);
-		Mockito.when(xUserService.createResource((VXUser) Mockito.any())).thenReturn(createdXUser);
+		Mockito.when(xxUserDao.findByUserName(vXUser.getName())).thenReturn(null, xXUser);
+		Mockito.when(xUserService.populateViewBean(xXUser)).thenReturn(vXUser);
+
+		vXPortalUser.setUserRoleList(roleList);
+		List<XXUserPermission> xUserPermissionsList = new ArrayList<XXUserPermission>();
+		XXUserPermission xUserPermissionObj = new XXUserPermission();
+		xUserPermissionObj.setAddedByUserId(userId);
+		xUserPermissionObj.setCreateTime(new Date());
+		xUserPermissionObj.setId(userId);
+		xUserPermissionObj.setIsAllowed(1);
+		xUserPermissionObj.setModuleId(1L);
+		xUserPermissionObj.setUpdatedByUserId(userId);
+		xUserPermissionObj.setUpdateTime(new Date());
+		xUserPermissionObj.setUserId(userId);
+		xUserPermissionsList.add(xUserPermissionObj);
+
 		createdXUser = xUserMgr.createExternalUser(vXUser.getName());
 		Assert.assertNotNull(createdXUser);
 		Assert.assertEquals(createdXUser.getName(), vXUser.getName());
diff --git a/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/model/GroupUserInfo.java b/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/model/GroupUserInfo.java
index ffb6625..aaa0a84 100644
--- a/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/model/GroupUserInfo.java
+++ b/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/model/GroupUserInfo.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.ranger.ugsyncutil.model;;
+package org.apache.ranger.ugsyncutil.model;
 
 import java.util.Set;