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 <prad...@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;