/** * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wso2.carbon.bpmn.core.integration; import org.activiti.engine.ActivitiObjectNotFoundException; import org.activiti.engine.identity.Group; import org.activiti.engine.identity.User; import org.activiti.engine.identity.UserQuery; import org.activiti.engine.impl.Page; import org.activiti.engine.impl.UserQueryImpl; import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; import org.activiti.engine.impl.persistence.entity.GroupEntity; import org.activiti.engine.impl.persistence.entity.IdentityInfoEntity; import org.activiti.engine.impl.persistence.entity.UserEntity; import org.activiti.engine.impl.persistence.entity.UserEntityManager; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.bpmn.core.BPMNConstants; import org.wso2.carbon.bpmn.core.BPMNServerHolder; import org.wso2.carbon.bpmn.core.exception.BPMNAuthenticationException; import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.registry.core.config.RegistryContext; import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.stratos.common.beans.TenantInfoBean; import org.wso2.carbon.tenant.mgt.services.TenantMgtAdminService; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.UserStoreManager; import org.wso2.carbon.user.core.claim.Claim; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.tenant.TenantManager; import org.wso2.carbon.user.mgt.UserAdmin; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import java.util.ArrayList; import java.util.List; import java.util.Map; public class BPSUserIdentityManager extends UserEntityManager { private static Log log = LogFactory.getLog(BPSUserIdentityManager.class); private TenantMgtAdminService tenantMgtAdminService; private UserAdmin userAdmin; private RegistryService registryService; //list of Claim URIs private static final String ID_CLAIM_URI = "urn:scim:schemas:core:1.0:id"; private static final String FIRST_NAME_CLAIM_URI = "http://axschema.org/namePerson/first"; private static final String LAST_NAME_CLAIM_URI = "http://wso2.org/claims/lastname"; private static final String FULL_NAME_CLAIM_URI = "http://wso2.org/claims/fullname"; private static final String EMAIL_CLAIM_URI = "http://wso2.org/claims/emailaddress"; private static final String ROLE_CLAIM_URI = "http://wso2.org/claims/role"; public BPSUserIdentityManager() { this.tenantMgtAdminService = new TenantMgtAdminService(); this.userAdmin = new UserAdmin(); this.registryService = BPMNServerHolder.getInstance().getRegistryService(); } @Override public User createNewUser(String userId) { String msg = "Invoked UserIdentityManager method is not implemented in BPSUserIdentityManager."; throw new UnsupportedOperationException(msg); } @Override public void insertUser(User user) { String msg = "Invoked UserIdentityManager method is not implemented in BPSUserIdentityManager."; throw new UnsupportedOperationException(msg); } @Override public UserEntity findUserById(String userId) { try { UserStoreManager userStoreManager = registryService.getUserRealm(getTenantIdFromUserId(userId)).getUserStoreManager(); if (userStoreManager.isExistingUser(userId)) { UserEntity userEntity = new UserEntity(userId); String firstName = userStoreManager.getUserClaimValue(userId, FIRST_NAME_CLAIM_URI, null); userEntity.setFirstName(firstName); String lastName = userStoreManager.getUserClaimValue(userId, LAST_NAME_CLAIM_URI, null); userEntity.setLastName(lastName); String email = userStoreManager.getUserClaimValue(userId, EMAIL_CLAIM_URI, null); userEntity.setEmail(email); return userEntity; } else { log.error("No user exist with userId:" + userId); return null; } } catch (Exception e) { log.error("Error retrieving user info by id for: " + userId, e); return null; } } @Override public void deleteUser(String userId) { String msg = "Invoked UserIdentityManager method is not implemented in BPSUserIdentityManager."; throw new UnsupportedOperationException(msg); } @Override public List<User> findUserByQueryCriteria(UserQueryImpl userQuery, Page page) { //get current tenant id int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); try { List<Claim> claimList = transformQueryToClaim(userQuery); if (claimList.size() > 0) { //todo: need to add support to search by query String msg = "Invoked UserIdentityManager method is not implemented in BPSUserIdentityManager."; throw new UnsupportedOperationException(msg); } else { //return all users String[] userList = registryService.getUserRealm(tenantId).getUserStoreManager().listUsers("*", -1); return pageUserList(page, userList, tenantId); } } catch (org.wso2.carbon.user.core.UserStoreException e) { log.error("error getting user list", e); return new ArrayList<>(); } catch (RegistryException e) { log.error("error getting user list", e); return new ArrayList<>(); } } private List<User> generateFinalUserList(List<String[]> resultUserList) { List<String> mergedList = new ArrayList<>(); //first result list is considered as merged list first for (String user : resultUserList.get(0)) { mergedList.add(user); } for (int i = 1; i < resultUserList.size(); i++) { List<String> newList = new ArrayList<>(); for (String user : resultUserList.get(i)) { if (mergedList.contains(user)) { newList.add(user); } } //make new list the merged list mergedList = newList; } List<User> result = new ArrayList<>(); //prepare User list for (String userName : mergedList) { result.add(new UserEntity(userName)); } return result; } private List<User> pageUserList(Page page, String[] users, int tenantId) throws RegistryException, org.wso2.carbon.user.core.UserStoreException { List<User> userList = new ArrayList<>(); int resultLength = users.length; int max; if (page != null) { if (page.getFirstResult() > resultLength) { //no more result left, sending empty list return new ArrayList<>(); } if (page.getMaxResults() > resultLength) { max = resultLength; } else { max = page.getMaxResults(); } for (int i = page.getFirstResult(); i < max; i++) { userList.add(new UserEntity(users[i])); } } else { for (int i = 0; i < resultLength; i++) { userList.add(new UserEntity(users[i])); } } return userList; } private List<Claim> transformQueryToClaim(UserQueryImpl userQuery) { List<Claim> claimList = new ArrayList<Claim>(); if (userQuery.getEmail() != null) { Claim claim = new Claim(); claim.setClaimUri(EMAIL_CLAIM_URI); claim.setValue(userQuery.getEmail()); claimList.add(claim); } if (userQuery.getEmailLike() != null) { Claim claim = new Claim(); claim.setClaimUri(EMAIL_CLAIM_URI); claim.setValue("*" + userQuery.getEmailLike() + "*"); claimList.add(claim); } if (userQuery.getFirstName() != null) { Claim claim = new Claim(); claim.setClaimUri(FIRST_NAME_CLAIM_URI); claim.setValue(userQuery.getFirstName()); claimList.add(claim); } if (userQuery.getFirstNameLike() != null) { Claim claim = new Claim(); claim.setClaimUri(FIRST_NAME_CLAIM_URI); claim.setValue("*" + userQuery.getFirstNameLike() + "*"); claimList.add(claim); } if (userQuery.getFullNameLike() != null) { Claim claim = new Claim(); claim.setClaimUri(FULL_NAME_CLAIM_URI); claim.setValue("*" + userQuery.getFullNameLike() + "*"); claimList.add(claim); } if (userQuery.getGroupId() != null) { Claim claim = new Claim(); claim.setClaimUri(ROLE_CLAIM_URI); claim.setValue(userQuery.getGroupId()); claimList.add(claim); } if (userQuery.getId() != null) { Claim claim = new Claim(); claim.setClaimUri(ID_CLAIM_URI); claim.setValue(userQuery.getId()); claimList.add(claim); } if (userQuery.getLastName() != null) { Claim claim = new Claim(); claim.setClaimUri(LAST_NAME_CLAIM_URI); claim.setValue(userQuery.getLastName()); claimList.add(claim); } if (userQuery.getLastNameLike() != null) { Claim claim = new Claim(); claim.setClaimUri(LAST_NAME_CLAIM_URI); claim.setValue("*" + userQuery.getLastNameLike() + "*"); claimList.add(claim); } return claimList; } @Override public long findUserCountByQueryCriteria(UserQueryImpl userQuery) { return findUserByQueryCriteria(userQuery, null).size(); } @Override public List<Group> findGroupsByUser(String userId) { List<Group> groups = new ArrayList<Group>(); try { String[] userNameTokens = userId.split("@"); int tenantId = BPMNConstants.SUPER_TENANT_ID; if (userNameTokens.length > 1) { TenantInfoBean tenantInfoBean = tenantMgtAdminService .getTenant(userNameTokens[userNameTokens.length - 1]); if (tenantInfoBean != null) { tenantId = tenantInfoBean.getTenantId(); } else { log.error("Could not retrieve tenant ID for tenant domain : " + userNameTokens[userNameTokens.length - 1]); return new ArrayList<Group>(); } } String[] roles = registryService.getUserRealm(tenantId).getUserStoreManager().getRoleListOfUser(userId); for (String role : roles) { Group group = new GroupEntity(role); groups.add(group); } } catch (UserStoreException e) { String msg = "Failed to get roles of the user: " + userId + ". Returning an empty roles list."; log.error(msg, e); }catch (Exception e) { log.error("error retrieving user tenant info", e); } return groups; } @Override public UserQuery createNewUserQuery() { return new UserQueryImpl(((ProcessEngineConfigurationImpl)BPMNServerHolder.getInstance().getEngine().getProcessEngineConfiguration()).getCommandExecutor()); } @Override public IdentityInfoEntity findUserInfoByUserIdAndKey(String userId, String key) { String msg = "Invoked UserIdentityManager method is not implemented in BPSUserIdentityManager."; throw new UnsupportedOperationException(msg); } @Override public List<String> findUserInfoKeysByUserIdAndType(String userId, String type) { String msg = "Invoked UserIdentityManager method is not implemented in BPSUserIdentityManager."; throw new UnsupportedOperationException(msg); } @Override public Boolean checkPassword(String userId, String password) { String tenantDomain = MultitenantUtils.getTenantDomain(userId); String tenantAwareUserName = MultitenantUtils.getTenantAwareUsername(userId); String userNameWithTenantDomain = tenantAwareUserName + "@" + tenantDomain; RealmService realmService = RegistryContext.getBaseInstance().getRealmService(); TenantManager mgr = realmService.getTenantManager(); int tenantId = 0; try { tenantId = mgr.getTenantId(tenantDomain); } catch (UserStoreException e) { throw new BPMNAuthenticationException( "Identity exception thrown while getting tenant ID for user : " + userNameWithTenantDomain, e); } // tenantId == -1, means an invalid tenant. if (tenantId == -1) { if (log.isDebugEnabled()) { log.debug("Basic authentication request with an invalid tenant : " + userNameWithTenantDomain); } return false; } org.wso2.carbon.user.api.UserStoreManager userStoreManager = null; boolean authStatus = false; try { userStoreManager = realmService.getTenantUserRealm(tenantId).getUserStoreManager(); authStatus = userStoreManager.authenticate(tenantAwareUserName, password); } catch (UserStoreException e) { throw new BPMNAuthenticationException( "User store exception thrown while authenticating user : " + userNameWithTenantDomain, e); } /* IdentityService identityService = BPMNOSGIService.getIdentityService(); authStatus = identityService.checkPassword(userName, password);*/ if (log.isDebugEnabled()) { log.debug("Basic authentication request completed. " + "Username : " + userNameWithTenantDomain + ", Authentication State : " + authStatus); } return authStatus; } private int getTenantIdFromUserId(String userId) throws Exception { String[] userNameTokens = userId.split("@"); int tenantId = BPMNConstants.SUPER_TENANT_ID; if (userNameTokens.length > 1) { TenantInfoBean tenantInfoBean = tenantMgtAdminService.getTenant(userNameTokens[userNameTokens.length - 1]); if (tenantInfoBean != null) { tenantId = tenantInfoBean.getTenantId(); } else { throw new Exception("Error retrieving tenant id from userId :" + userId); } } return tenantId; } @Override public List<User> findPotentialStarterUsers(String processDefId) { String msg = "Invoked UserIdentityManager method is not implemented in BPSUserIdentityManager."; throw new UnsupportedOperationException(msg); } @Override public List<User> findUsersByNativeQuery(Map<String, Object> parameterMap, int firstResult, int maxResults) { String msg = "Invoked UserIdentityManager method is not implemented in BPSUserIdentityManager."; throw new UnsupportedOperationException(msg); } @Override public long findUserCountByNativeQuery(Map<String, Object> parameterMap) { String msg = "Invoked UserIdentityManager method is not implemented in BPSUserIdentityManager."; throw new UnsupportedOperationException(msg); } }