Java tutorial
/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License, version 2 as published by the Free Software * Foundation. * * You should have received a copy of the GNU General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * * Copyright 2006 - 2013 Pentaho Corporation. All rights reserved. */ package org.pentaho.platform.security.userroledao.jackrabbit; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.Set; import javax.jcr.Credentials; import javax.jcr.NamespaceException; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.Value; import org.apache.commons.collections.map.LRUMap; import org.apache.jackrabbit.api.security.user.Authorizable; import org.apache.jackrabbit.api.security.user.AuthorizableExistsException; import org.apache.jackrabbit.api.security.user.Group; import org.apache.jackrabbit.api.security.user.User; import org.apache.jackrabbit.api.security.user.UserManager; import org.apache.jackrabbit.core.SessionImpl; import org.apache.jackrabbit.core.security.authentication.CryptedSimpleCredentials; import org.apache.jackrabbit.core.security.principal.PrincipalImpl; import org.apache.jackrabbit.core.security.user.UserManagerImpl; import org.apache.jackrabbit.spi.Name; import org.apache.jackrabbit.spi.NameFactory; import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl; import org.pentaho.platform.api.engine.security.userroledao.IPentahoRole; import org.pentaho.platform.api.engine.security.userroledao.IPentahoUser; import org.pentaho.platform.api.engine.security.userroledao.IUserRoleDao; import org.pentaho.platform.api.engine.security.userroledao.NotFoundException; import org.pentaho.platform.api.mt.ITenant; import org.pentaho.platform.api.mt.ITenantedPrincipleNameResolver; import org.pentaho.platform.api.repository2.unified.IRepositoryDefaultAclHandler; import org.pentaho.platform.api.repository2.unified.RepositoryFile; import org.pentaho.platform.api.repository2.unified.RepositoryFileAcl; import org.pentaho.platform.api.repository2.unified.RepositoryFileAcl.Builder; import org.pentaho.platform.api.repository2.unified.RepositoryFilePermission; import org.pentaho.platform.api.repository2.unified.RepositoryFileSid; import org.pentaho.platform.api.repository2.unified.RepositoryFileSid.Type; import org.pentaho.platform.engine.core.system.PentahoSessionHolder; import org.pentaho.platform.engine.core.system.PentahoSystem; import org.pentaho.platform.engine.core.system.TenantUtils; import org.pentaho.platform.repository2.unified.IRepositoryFileAclDao; import org.pentaho.platform.repository2.unified.IRepositoryFileDao; import org.pentaho.platform.repository2.unified.ServerRepositoryPaths; import org.pentaho.platform.repository2.unified.jcr.ILockHelper; import org.pentaho.platform.repository2.unified.jcr.IPathConversionHelper; import org.pentaho.platform.repository2.unified.jcr.JcrRepositoryFileAclUtils; import org.pentaho.platform.repository2.unified.jcr.JcrRepositoryFileUtils; import org.pentaho.platform.repository2.unified.jcr.JcrTenantUtils; import org.pentaho.platform.repository2.unified.jcr.PentahoJcrConstants; import org.pentaho.platform.security.userroledao.PentahoRole; import org.pentaho.platform.security.userroledao.PentahoUser; import org.pentaho.platform.security.userroledao.messages.Messages; import org.springframework.security.providers.dao.UserCache; import org.springframework.security.providers.dao.cache.NullUserCache; public abstract class AbstractJcrBackedUserRoleDao implements IUserRoleDao { NameFactory NF = NameFactoryImpl.getInstance(); Name P_PRINCIPAL_NAME = NF.create(Name.NS_REP_URI, "principalName"); //$NON-NLS-1$ protected ITenantedPrincipleNameResolver tenantedUserNameUtils; protected ITenantedPrincipleNameResolver tenantedRoleNameUtils; String pPrincipalName = "rep:principalName"; //$NON-NLS-1$ IRepositoryFileAclDao repositoryFileAclDao; IRepositoryFileDao repositoryFileDao; String defaultTenant; String authenticatedRoleName; String tenantAdminRoleName; String repositoryAdminUsername; IPathConversionHelper pathConversionHelper; IRepositoryDefaultAclHandler defaultAclHandler; ILockHelper lockHelper; List<String> systemRoles; List<String> extraRoles; HashMap<String, UserManagerImpl> userMgrMap = new HashMap<String, UserManagerImpl>(); private LRUMap userCache = new LRUMap(4096); private UserCache userDetailsCache = new NullUserCache(); public AbstractJcrBackedUserRoleDao(ITenantedPrincipleNameResolver userNameUtils, ITenantedPrincipleNameResolver roleNameUtils, String authenticatedRoleName, String tenantAdminRoleName, String repositoryAdminUsername, IRepositoryFileAclDao repositoryFileAclDao, IRepositoryFileDao repositoryFileDao, final IPathConversionHelper pathConversionHelper, final ILockHelper lockHelper, final IRepositoryDefaultAclHandler defaultAclHandler, final List<String> systemRoles, final List<String> extraRoles, UserCache userDetailsCache) throws NamespaceException { this.tenantedUserNameUtils = userNameUtils; this.tenantedRoleNameUtils = roleNameUtils; this.authenticatedRoleName = authenticatedRoleName; this.tenantAdminRoleName = tenantAdminRoleName; this.repositoryAdminUsername = repositoryAdminUsername; this.repositoryFileAclDao = repositoryFileAclDao; this.repositoryFileDao = repositoryFileDao; this.pathConversionHelper = pathConversionHelper; this.lockHelper = lockHelper; this.defaultAclHandler = defaultAclHandler; this.systemRoles = systemRoles; this.extraRoles = extraRoles; this.userDetailsCache = userDetailsCache; } public void setRoleMembers(Session session, final ITenant theTenant, final String roleName, final String[] memberUserNames) throws RepositoryException, NotFoundException { List<IPentahoUser> currentRoleMembers = getRoleMembers(session, theTenant, roleName); String[] usersToBeRemoved = findRemovedUsers(currentRoleMembers, memberUserNames); // If we are unassigning a user or users from the Administrator role, we need to check if this is a logged in user // or a user designated as a system user. If it is then we // will display a message to the user. if ((oneOfUserIsMySelf(usersToBeRemoved) || oneOfUserIsDefaultAdminUser(usersToBeRemoved)) && tenantAdminRoleName.equals(roleName)) { throw new RepositoryException(Messages.getInstance().getString( "AbstractJcrBackedUserRoleDao.ERROR_0009_USER_REMOVE_FAILED_YOURSELF_OR_DEFAULT_ADMIN_USER")); } // If this is the last user from the Administrator role, we will not let the user remove. if (tenantAdminRoleName.equals(roleName) && (currentRoleMembers != null && currentRoleMembers.size() > 0) && memberUserNames.length == 0) { throw new RepositoryException(Messages.getInstance() .getString("AbstractJcrBackedUserRoleDao.ERROR_0001_LAST_ADMIN_ROLE", tenantAdminRoleName)); } Group jackrabbitGroup = getJackrabbitGroup(theTenant, roleName, session); if ((jackrabbitGroup == null) || !TenantUtils.isAccessibleTenant( theTenant == null ? tenantedRoleNameUtils.getTenant(jackrabbitGroup.getID()) : theTenant)) { throw new NotFoundException( Messages.getInstance().getString("AbstractJcrBackedUserRoleDao.ERROR_0002_ROLE_NOT_FOUND")); } HashMap<String, User> currentlyAssignedUsers = new HashMap<String, User>(); Iterator<Authorizable> currentMembers = jackrabbitGroup.getMembers(); while (currentMembers.hasNext()) { Authorizable member = currentMembers.next(); if (member instanceof User) { currentlyAssignedUsers.put(member.getID(), (User) member); } } HashMap<String, User> finalCollectionOfAssignedUsers = new HashMap<String, User>(); if (memberUserNames != null) { ITenant tenant = theTenant == null ? JcrTenantUtils.getTenant(roleName, false) : theTenant; for (String user : memberUserNames) { User jackrabbitUser = getJackrabbitUser(tenant, user, session); if (jackrabbitUser != null) { finalCollectionOfAssignedUsers.put(getTenantedUserNameUtils().getPrincipleId(tenant, user), jackrabbitUser); } } } ArrayList<String> usersToRemove = new ArrayList<String>(currentlyAssignedUsers.keySet()); usersToRemove.removeAll(finalCollectionOfAssignedUsers.keySet()); ArrayList<String> usersToAdd = new ArrayList<String>(finalCollectionOfAssignedUsers.keySet()); usersToAdd.removeAll(currentlyAssignedUsers.keySet()); for (String userId : usersToRemove) { jackrabbitGroup.removeMember(currentlyAssignedUsers.get(userId)); purgeUserFromCache(userId); } for (String userId : usersToAdd) { jackrabbitGroup.addMember(finalCollectionOfAssignedUsers.get(userId)); // Purge the UserDetails cache purgeUserFromCache(userId); } } private void setUserRolesForNewUser(Session session, final ITenant theTenant, final String userName, final String[] roles) throws RepositoryException, NotFoundException { Set<String> roleSet = new HashSet<String>(); if (roles != null) { roleSet.addAll(Arrays.asList(roles)); } roleSet.add(authenticatedRoleName); User jackrabbitUser = getJackrabbitUser(theTenant, userName, session); if ((jackrabbitUser == null) || !TenantUtils.isAccessibleTenant( theTenant == null ? tenantedUserNameUtils.getTenant(jackrabbitUser.getID()) : theTenant)) { throw new NotFoundException( Messages.getInstance().getString("AbstractJcrBackedUserRoleDao.ERROR_0003_USER_NOT_FOUND")); } HashMap<String, Group> finalCollectionOfAssignedGroups = new HashMap<String, Group>(); ITenant tenant = theTenant == null ? JcrTenantUtils.getTenant(userName, true) : theTenant; for (String role : roleSet) { Group jackrabbitGroup = getJackrabbitGroup(tenant, role, session); if (jackrabbitGroup != null) { finalCollectionOfAssignedGroups.put(tenantedRoleNameUtils.getPrincipleId(tenant, role), jackrabbitGroup); } } ArrayList<String> groupsToAdd = new ArrayList<String>(finalCollectionOfAssignedGroups.keySet()); for (String groupId : groupsToAdd) { finalCollectionOfAssignedGroups.get(groupId).addMember(jackrabbitUser); // Purge the UserDetails cache purgeUserFromCache(userName); } } private void purgeUserFromCache(String userName) { userDetailsCache.removeUserFromCache(getTenantedUserNameUtils().getPrincipleName(userName)); } private boolean oneOfUserIsMySelf(String[] users) { for (int i = 0; i < users.length; i++) { if (isMyself(users[i])) { return true; } } return false; } private boolean oneOfUserIsDefaultAdminUser(String[] users) { for (int i = 0; i < users.length; i++) { if (isDefaultAdminUser(users[i])) { return true; } } return false; } private boolean isMyself(String userName) { return PentahoSessionHolder.getSession().getName().equals(userName); } private boolean isDefaultAdminUser(String userName) { String defaultAdminUser = PentahoSystem.get(String.class, "singleTenantAdminUserName", PentahoSessionHolder.getSession()); if (defaultAdminUser != null) { return defaultAdminUser.equals(userName); } return false; } private boolean adminRoleExist(String[] newRoles) { return Arrays.asList(newRoles).contains(tenantAdminRoleName); } public void setUserRoles(Session session, final ITenant theTenant, final String userName, final String[] roles) throws RepositoryException, NotFoundException { if ((isMyself(userName) || isDefaultAdminUser(userName)) && !adminRoleExist(roles)) { throw new RepositoryException(Messages.getInstance() .getString("AbstractJcrBackedUserRoleDao.ERROR_0005_YOURSELF_OR_DEFAULT_ADMIN_USER")); } Set<String> roleSet = new HashSet<String>(); if (roles != null) { roleSet.addAll(Arrays.asList(roles)); } roleSet.add(authenticatedRoleName); User jackrabbitUser = getJackrabbitUser(theTenant, userName, session); if ((jackrabbitUser == null) || !TenantUtils.isAccessibleTenant( theTenant == null ? tenantedUserNameUtils.getTenant(jackrabbitUser.getID()) : theTenant)) { throw new NotFoundException( Messages.getInstance().getString("AbstractJcrBackedUserRoleDao.ERROR_0003_USER_NOT_FOUND")); } HashMap<String, Group> currentlyAssignedGroups = new HashMap<String, Group>(); Iterator<Group> currentGroups = jackrabbitUser.memberOf(); while (currentGroups.hasNext()) { Group currentGroup = currentGroups.next(); currentlyAssignedGroups.put(currentGroup.getID(), currentGroup); } HashMap<String, Group> finalCollectionOfAssignedGroups = new HashMap<String, Group>(); ITenant tenant = theTenant == null ? JcrTenantUtils.getTenant(userName, true) : theTenant; for (String role : roleSet) { Group jackrabbitGroup = getJackrabbitGroup(tenant, role, session); if (jackrabbitGroup != null) { finalCollectionOfAssignedGroups.put(tenantedRoleNameUtils.getPrincipleId(tenant, role), jackrabbitGroup); } } ArrayList<String> groupsToRemove = new ArrayList<String>(currentlyAssignedGroups.keySet()); groupsToRemove.removeAll(finalCollectionOfAssignedGroups.keySet()); ArrayList<String> groupsToAdd = new ArrayList<String>(finalCollectionOfAssignedGroups.keySet()); groupsToAdd.removeAll(currentlyAssignedGroups.keySet()); for (String groupId : groupsToRemove) { currentlyAssignedGroups.get(groupId).removeMember(jackrabbitUser); } for (String groupId : groupsToAdd) { finalCollectionOfAssignedGroups.get(groupId).addMember(jackrabbitUser); } // Purge the UserDetails cache purgeUserFromCache(userName); } public IPentahoRole createRole(Session session, final ITenant theTenant, final String roleName, final String description, final String[] memberUserNames) throws AuthorizableExistsException, RepositoryException { ITenant tenant = theTenant; String role = roleName; if (tenant == null) { tenant = JcrTenantUtils.getTenant(roleName, false); role = JcrTenantUtils.getPrincipalName(roleName, false); } if (tenant == null || tenant.getId() == null) { tenant = JcrTenantUtils.getCurrentTenant(); } if (!TenantUtils.isAccessibleTenant(tenant)) { throw new NotFoundException(Messages.getInstance() .getString("AbstractJcrBackedUserRoleDao.ERROR_0006_TENANT_NOT_FOUND", theTenant.getId())); } String roleId = tenantedRoleNameUtils.getPrincipleId(tenant, role); UserManager tenantUserMgr = getUserManager(tenant, session); // Intermediate path will always be an empty string. The path is already provided while creating a user manager tenantUserMgr.createGroup(new PrincipalImpl(roleId), ""); //$NON-NLS-1$ setRoleMembers(session, tenant, role, memberUserNames); setRoleDescription(session, tenant, role, description); return getRole(session, theTenant, roleName); } public IPentahoUser createUser(Session session, final ITenant theTenant, final String userName, final String password, final String description, final String[] roles) throws AuthorizableExistsException, RepositoryException { ITenant tenant = theTenant; String user = userName; if (tenant == null) { tenant = JcrTenantUtils.getTenant(userName, true); user = JcrTenantUtils.getPrincipalName(userName, true); } if (tenant == null || tenant.getId() == null) { tenant = JcrTenantUtils.getCurrentTenant(); } if (!TenantUtils.isAccessibleTenant(tenant)) { throw new NotFoundException(Messages.getInstance() .getString("AbstractJcrBackedUserRoleDao.ERROR_0006_TENANT_NOT_FOUND", theTenant.getId())); } String userId = tenantedUserNameUtils.getPrincipleId(tenant, user); UserManager tenantUserMgr = getUserManager(tenant, session); tenantUserMgr.createUser(userId, password, new PrincipalImpl(userId), ""); //$NON-NLS-1$ session.save(); /** * This call is absolutely necessary. setUserRolesForNewUser will never inspect what roles this user is a part of. * Since this is a new user it will not be a part of new roles **/ setUserRolesForNewUser(session, tenant, user, roles); setUserDescription(session, tenant, user, description); session.save(); createUserHomeFolder(tenant, user, session); session.save(); this.userDetailsCache.removeUserFromCache(userName); return getUser(session, tenant, userName); } public void deleteRole(Session session, final IPentahoRole role) throws NotFoundException, RepositoryException { if (canDeleteRole(session, role)) { final List<IPentahoUser> roleMembers = this.getRoleMembers(session, role.getTenant(), role.getName()); Group jackrabbitGroup = getJackrabbitGroup(role.getTenant(), role.getName(), session); if (jackrabbitGroup != null && TenantUtils.isAccessibleTenant(tenantedRoleNameUtils.getTenant(jackrabbitGroup.getID()))) { jackrabbitGroup.remove(); } else { throw new NotFoundException(""); //$NON-NLS-1$ } for (IPentahoUser roleMember : roleMembers) { purgeUserFromCache(roleMember.getUsername()); } } else { throw new RepositoryException(Messages.getInstance() .getString("AbstractJcrBackedUserRoleDao.ERROR_0007_ATTEMPTED_SYSTEM_ROLE_DELETE")); } } public void deleteUser(Session session, final IPentahoUser user) throws NotFoundException, RepositoryException { if (canDeleteUser(session, user)) { User jackrabbitUser = getJackrabbitUser(user.getTenant(), user.getUsername(), session); if (jackrabbitUser != null && TenantUtils.isAccessibleTenant(tenantedUserNameUtils.getTenant(jackrabbitUser.getID()))) { // [BISERVER-9215] Adding new user with same user name as a previously deleted user, defaults to all // previous // roles Iterator<Group> currentGroups = jackrabbitUser.memberOf(); while (currentGroups.hasNext()) { currentGroups.next().removeMember(jackrabbitUser); } purgeUserFromCache(user.getUsername()); // [BISERVER-9215] jackrabbitUser.remove(); } else { throw new NotFoundException(""); //$NON-NLS-1$ } } else { throw new RepositoryException(Messages.getInstance().getString( "AbstractJcrBackedUserRoleDao.ERROR_0004_LAST_USER_NEEDED_IN_ROLE", tenantAdminRoleName)); } } public List<IPentahoRole> getRoles(Session session) throws RepositoryException { return getRoles(session, JcrTenantUtils.getCurrentTenant()); } private IPentahoUser convertToPentahoUser(User jackrabbitUser) throws RepositoryException { if (userCache.containsKey(jackrabbitUser.getID())) { return (IPentahoUser) userCache.get(jackrabbitUser.getID()); } IPentahoUser pentahoUser = null; Value[] propertyValues = null; String description = null; try { propertyValues = jackrabbitUser.getProperty("description"); //$NON-NLS-1$ description = propertyValues.length > 0 ? propertyValues[0].getString() : null; } catch (Exception ex) { // CHECKSTYLES IGNORE } Credentials credentials = jackrabbitUser.getCredentials(); String password = null; if (credentials instanceof CryptedSimpleCredentials) { password = new String(((CryptedSimpleCredentials) credentials).getPassword()); } pentahoUser = new PentahoUser(tenantedUserNameUtils.getTenant(jackrabbitUser.getID()), tenantedUserNameUtils.getPrincipleName(jackrabbitUser.getID()), password, description, !jackrabbitUser.isDisabled()); userCache.put(jackrabbitUser.getID(), pentahoUser); return pentahoUser; } private IPentahoRole convertToPentahoRole(Group jackrabbitGroup) throws RepositoryException { IPentahoRole role = null; Value[] propertyValues = null; String description = null; try { propertyValues = jackrabbitGroup.getProperty("description"); //$NON-NLS-1$ description = propertyValues.length > 0 ? propertyValues[0].getString() : null; } catch (Exception ex) { // CHECKSTYLES IGNORE } role = new PentahoRole(tenantedRoleNameUtils.getTenant(jackrabbitGroup.getID()), tenantedRoleNameUtils.getPrincipleName(jackrabbitGroup.getID()), description); return role; } public List<IPentahoUser> getUsers(Session session) throws RepositoryException { return getUsers(session, JcrTenantUtils.getCurrentTenant()); } public void setRoleDescription(Session session, final ITenant theTenant, final String roleName, final String description) throws NotFoundException, RepositoryException { Group jackrabbitGroup = getJackrabbitGroup(theTenant, roleName, session); if (jackrabbitGroup != null && TenantUtils.isAccessibleTenant( theTenant == null ? tenantedRoleNameUtils.getTenant(jackrabbitGroup.getID()) : theTenant)) { if (description == null) { jackrabbitGroup.removeProperty("description"); //$NON-NLS-1$ } else { jackrabbitGroup.setProperty("description", session.getValueFactory().createValue(description)); //$NON-NLS-1$ } } else { throw new NotFoundException( Messages.getInstance().getString("AbstractJcrBackedUserRoleDao.ERROR_0002_ROLE_NOT_FOUND")); } } public void setUserDescription(Session session, final ITenant theTenant, final String userName, final String description) throws NotFoundException, RepositoryException { User jackrabbitUser = getJackrabbitUser(theTenant, userName, session); if ((jackrabbitUser == null) || !TenantUtils.isAccessibleTenant( theTenant == null ? tenantedUserNameUtils.getTenant(jackrabbitUser.getID()) : theTenant)) { throw new NotFoundException( Messages.getInstance().getString("AbstractJcrBackedUserRoleDao.ERROR_0003_USER_NOT_FOUND")); } if (description == null) { jackrabbitUser.removeProperty("description"); //$NON-NLS-1$ } else { jackrabbitUser.setProperty("description", session.getValueFactory().createValue(description)); //$NON-NLS-1$ } } public void setPassword(Session session, final ITenant theTenant, final String userName, final String password) throws NotFoundException, RepositoryException { User jackrabbitUser = getJackrabbitUser(theTenant, userName, session); if ((jackrabbitUser == null) || !TenantUtils.isAccessibleTenant( theTenant == null ? tenantedUserNameUtils.getTenant(jackrabbitUser.getID()) : theTenant)) { throw new NotFoundException( Messages.getInstance().getString("AbstractJcrBackedUserRoleDao.ERROR_0003_USER_NOT_FOUND")); } jackrabbitUser.changePassword(password); /** * BISERVER-9906 Clear cache after changing password */ purgeUserFromCache(userName); userCache.remove(jackrabbitUser.getID()); } public ITenantedPrincipleNameResolver getTenantedUserNameUtils() { return tenantedUserNameUtils; } public ITenantedPrincipleNameResolver getTenantedRoleNameUtils() { return tenantedRoleNameUtils; } public List<IPentahoRole> getRoles(Session session, ITenant tenant) throws RepositoryException, NamespaceException { return getRoles(session, tenant, false); } public List<IPentahoRole> getRoles(Session session, ITenant theTenant, boolean includeSubtenants) throws RepositoryException { ArrayList<IPentahoRole> roles = new ArrayList<IPentahoRole>(); if (theTenant == null || theTenant.getId() == null) { theTenant = JcrTenantUtils.getTenant(); } if (TenantUtils.isAccessibleTenant(theTenant)) { UserManager userMgr = getUserManager(theTenant, session); pPrincipalName = ((SessionImpl) session).getJCRName(P_PRINCIPAL_NAME); Iterator<Authorizable> it = userMgr.findAuthorizables(pPrincipalName, null, UserManager.SEARCH_TYPE_GROUP); while (it.hasNext()) { Group group = (Group) it.next(); IPentahoRole pentahoRole = convertToPentahoRole(group); // Exclude the system role from the list of roles to be returned back if (!extraRoles.contains(pentahoRole.getName())) { if (includeSubtenants) { roles.add(pentahoRole); } else { if (pentahoRole.getTenant() != null && pentahoRole.getTenant().equals(theTenant)) { roles.add(pentahoRole); } } } } } return roles; } public List<IPentahoUser> getUsers(Session session, ITenant tenant) throws RepositoryException { return getUsers(session, tenant, false); } public List<IPentahoUser> getUsers(Session session, ITenant theTenant, boolean includeSubtenants) throws RepositoryException { ArrayList<IPentahoUser> users = new ArrayList<IPentahoUser>(); if (theTenant == null || theTenant.getId() == null) { theTenant = JcrTenantUtils.getTenant(); } if (TenantUtils.isAccessibleTenant(theTenant)) { UserManager userMgr = getUserManager(theTenant, session); pPrincipalName = ((SessionImpl) session).getJCRName(P_PRINCIPAL_NAME); Iterator<Authorizable> it = userMgr.findAuthorizables(pPrincipalName, null, UserManager.SEARCH_TYPE_USER); while (it.hasNext()) { User user = (User) it.next(); IPentahoUser pentahoUser = convertToPentahoUser(user); if (includeSubtenants) { users.add(pentahoUser); } else { if (pentahoUser.getTenant() != null && pentahoUser.getTenant().equals(theTenant)) { users.add(pentahoUser); } } } } return users; } public IPentahoRole getRole(Session session, final ITenant tenant, final String name) throws RepositoryException { Group jackrabbitGroup = getJackrabbitGroup(tenant, name, session); return jackrabbitGroup != null && TenantUtils.isAccessibleTenant( tenant == null ? tenantedRoleNameUtils.getTenant(jackrabbitGroup.getID()) : tenant) ? convertToPentahoRole(jackrabbitGroup) : null; } private UserManagerImpl getUserManager(ITenant theTenant, Session session) throws RepositoryException { Properties tenantProperties = new Properties(); tenantProperties.put(UserManagerImpl.PARAM_USERS_PATH, UserManagerImpl.USERS_PATH + theTenant.getRootFolderAbsolutePath()); tenantProperties.put(UserManagerImpl.PARAM_GROUPS_PATH, UserManagerImpl.GROUPS_PATH + theTenant.getRootFolderAbsolutePath()); return new UserManagerImpl((SessionImpl) session, session.getUserID(), tenantProperties); } public IPentahoUser getUser(Session session, final ITenant tenant, final String name) throws RepositoryException { User jackrabbitUser = getJackrabbitUser(tenant, name, session); return jackrabbitUser != null && TenantUtils.isAccessibleTenant( tenant == null ? tenantedUserNameUtils.getTenant(jackrabbitUser.getID()) : tenant) ? convertToPentahoUser(jackrabbitUser) : null; } private Group getJackrabbitGroup(ITenant theTenant, String name, Session session) throws RepositoryException { Group jackrabbitGroup = null; String roleId = name; String roleName = name; ITenant tenant = theTenant; if (tenant == null) { tenant = JcrTenantUtils.getTenant(roleName, false); roleName = JcrTenantUtils.getPrincipalName(roleName, false); } if (tenant == null || tenant.getId() == null) { tenant = JcrTenantUtils.getCurrentTenant(); } if (tenant == null || tenant.getId() == null) { tenant = JcrTenantUtils.getDefaultTenant(); } roleId = tenantedRoleNameUtils.getPrincipleId(tenant, roleName); UserManager userMgr = getUserManager(tenant, session); Authorizable authorizable = userMgr.getAuthorizable(roleId); if (authorizable instanceof Group) { jackrabbitGroup = (Group) authorizable; } return jackrabbitGroup; } private User getJackrabbitUser(ITenant theTenant, String name, Session session) throws RepositoryException { User jackrabbitUser = null; String userId = name; String userName = name; ITenant tenant = theTenant; if (tenant == null) { tenant = JcrTenantUtils.getTenant(userName, true); userName = JcrTenantUtils.getPrincipalName(userName, true); } if (tenant == null || tenant.getId() == null) { tenant = JcrTenantUtils.getCurrentTenant(); } if (tenant == null || tenant.getId() == null) { tenant = JcrTenantUtils.getDefaultTenant(); } if (tenant != null) { userId = tenantedUserNameUtils.getPrincipleId(tenant, userName); UserManager userMgr = getUserManager(tenant, session); Authorizable authorizable = userMgr.getAuthorizable(userId); if (authorizable instanceof User) { jackrabbitUser = (User) authorizable; } } return jackrabbitUser; } protected boolean tenantExists(String tenantName) { return tenantName != null && tenantName.trim().length() > 0; } public List<IPentahoUser> getRoleMembers(Session session, final ITenant theTenant, final String roleName) throws RepositoryException { List<IPentahoUser> users = new ArrayList<IPentahoUser>(); Group jackrabbitGroup = getJackrabbitGroup(theTenant, roleName, session); if ((jackrabbitGroup != null) && TenantUtils.isAccessibleTenant( theTenant == null ? tenantedRoleNameUtils.getTenant(jackrabbitGroup.getID()) : theTenant)) { Iterator<Authorizable> authorizables = jackrabbitGroup.getMembers(); while (authorizables.hasNext()) { Authorizable authorizable = authorizables.next(); if (authorizable instanceof User) { users.add(convertToPentahoUser((User) authorizable)); } } } return users; } public List<IPentahoRole> getUserRoles(Session session, final ITenant theTenant, final String userName) throws RepositoryException { ArrayList<IPentahoRole> roles = new ArrayList<IPentahoRole>(); User jackrabbitUser = getJackrabbitUser(theTenant, userName, session); if ((jackrabbitUser != null) && TenantUtils.isAccessibleTenant( theTenant == null ? tenantedUserNameUtils.getTenant(jackrabbitUser.getID()) : theTenant)) { Iterator<Group> groups = jackrabbitUser.memberOf(); while (groups.hasNext()) { IPentahoRole role = convertToPentahoRole(groups.next()); // Exclude the extra role from the list of roles to be returned back if (!extraRoles.contains(role.getName())) { roles.add(role); } } } return roles; } private RepositoryFile createUserHomeFolder(ITenant theTenant, String username, Session session) throws RepositoryException { Builder aclsForUserHomeFolder = null; Builder aclsForTenantHomeFolder = null; if (theTenant == null) { theTenant = JcrTenantUtils.getTenant(username, true); username = JcrTenantUtils.getPrincipalName(username, true); } if (theTenant == null || theTenant.getId() == null) { theTenant = JcrTenantUtils.getCurrentTenant(); } if (theTenant == null || theTenant.getId() == null) { theTenant = JcrTenantUtils.getDefaultTenant(); } RepositoryFile userHomeFolder = null; String userId = tenantedUserNameUtils.getPrincipleId(theTenant, username); final RepositoryFileSid userSid = new RepositoryFileSid(userId); RepositoryFile tenantHomeFolder = null; RepositoryFile tenantRootFolder = null; RepositoryFileSid ownerSid = null; // Get the Tenant Root folder. If the Tenant Root folder does not exist then exit. tenantRootFolder = JcrRepositoryFileUtils.getFileByAbsolutePath(session, ServerRepositoryPaths.getTenantRootFolderPath(theTenant), pathConversionHelper, lockHelper, false, null); if (tenantRootFolder != null) { // Try to see if Tenant Home folder exist tenantHomeFolder = JcrRepositoryFileUtils.getFileByAbsolutePath(session, ServerRepositoryPaths.getTenantHomeFolderPath(theTenant), pathConversionHelper, lockHelper, false, null); if (tenantHomeFolder == null) { String ownerId = tenantedUserNameUtils.getPrincipleId(theTenant, username); ownerSid = new RepositoryFileSid(ownerId, Type.USER); String tenantAuthenticatedRoleId = tenantedRoleNameUtils.getPrincipleId(theTenant, authenticatedRoleName); RepositoryFileSid tenantAuthenticatedRoleSid = new RepositoryFileSid(tenantAuthenticatedRoleId, Type.ROLE); aclsForTenantHomeFolder = new RepositoryFileAcl.Builder(userSid).ace(tenantAuthenticatedRoleSid, EnumSet.of(RepositoryFilePermission.READ)); aclsForUserHomeFolder = new RepositoryFileAcl.Builder(userSid).ace(ownerSid, EnumSet.of(RepositoryFilePermission.ALL)); tenantHomeFolder = internalCreateFolder(session, tenantRootFolder.getId(), new RepositoryFile.Builder(ServerRepositoryPaths.getTenantHomeFolderName()).folder(true) .title(Messages.getInstance() .getString("AbstractJcrBackedUserRoleDao.usersFolderDisplayName")) .build(), aclsForTenantHomeFolder.build(), "tenant home folder"); //$NON-NLS-1$ } else { String ownerId = tenantedUserNameUtils.getPrincipleId(theTenant, username); ownerSid = new RepositoryFileSid(ownerId, Type.USER); aclsForUserHomeFolder = new RepositoryFileAcl.Builder(userSid).ace(ownerSid, EnumSet.of(RepositoryFilePermission.ALL)); } // now check if user's home folder exist userHomeFolder = JcrRepositoryFileUtils.getFileByAbsolutePath(session, ServerRepositoryPaths.getUserHomeFolderPath(theTenant, username), pathConversionHelper, lockHelper, false, null); if (userHomeFolder == null) { userHomeFolder = internalCreateFolder(session, tenantHomeFolder.getId(), new RepositoryFile.Builder(username).folder(true).build(), aclsForUserHomeFolder.build(), "user home folder"); //$NON-NLS-1$ } } return userHomeFolder; } private RepositoryFile internalCreateFolder(final Session session, final Serializable parentFolderId, final RepositoryFile folder, final RepositoryFileAcl acl, final String versionMessage) throws RepositoryException { PentahoJcrConstants pentahoJcrConstants = new PentahoJcrConstants(session); JcrRepositoryFileUtils.checkoutNearestVersionableFileIfNecessary(session, pentahoJcrConstants, parentFolderId); Node folderNode = JcrRepositoryFileUtils.createFolderNode(session, pentahoJcrConstants, parentFolderId, folder); // we must create the acl during checkout JcrRepositoryFileAclUtils.createAcl(session, pentahoJcrConstants, folderNode.getIdentifier(), acl == null ? defaultAclHandler.createDefaultAcl(folder) : acl); session.save(); if (folder.isVersioned()) { JcrRepositoryFileUtils.checkinNearestVersionableNodeIfNecessary(session, pentahoJcrConstants, folderNode, versionMessage); } JcrRepositoryFileUtils.checkinNearestVersionableFileIfNecessary(session, pentahoJcrConstants, parentFolderId, Messages.getInstance().getString("JcrRepositoryFileDao.USER_0001_VER_COMMENT_ADD_FOLDER", folder.getName(), (parentFolderId == null ? "root" : parentFolderId.toString()))); //$NON-NLS-1$ //$NON-NLS-2$ return JcrRepositoryFileUtils.nodeToFile(session, pentahoJcrConstants, pathConversionHelper, lockHelper, folderNode); } /** * Checks to see if the removal of the received roles and users would cause the system to have no login associated * with the Admin role. This check is to be made before any changes take place * * @return Error message if invalid or null if ok * @throws RepositoryException */ private boolean canDeleteUser(Session session, final IPentahoUser user) throws RepositoryException { boolean userHasAdminRole = false; List<IPentahoRole> roles = getUserRoles(null, user.getUsername()); for (IPentahoRole role : roles) { if (tenantAdminRoleName.equals(role.getName())) { userHasAdminRole = true; break; } } if ((isMyself(user.getUsername()) || isDefaultAdminUser(user.getUsername())) && userHasAdminRole) { throw new RepositoryException(Messages.getInstance().getString( "AbstractJcrBackedUserRoleDao.ERROR_0008_UNABLE_TO_DELETE_USER_IS_YOURSELF_OR_DEFAULT_ADMIN_USER")); } if (userHasAdminRole) { List<IPentahoUser> usersWithAdminRole = getRoleMembers(session, null, tenantAdminRoleName); if (usersWithAdminRole == null) { throw new RepositoryException(Messages.getInstance().getString( "AbstractJcrBackedUserRoleDao.ERROR_0004_LAST_USER_NEEDED_IN_ROLE", tenantAdminRoleName)); } if (usersWithAdminRole.size() > 1) { return true; } else if (usersWithAdminRole.size() == 1) { return false; } else { throw new RepositoryException(Messages.getInstance().getString( "AbstractJcrBackedUserRoleDao.ERROR_0004_LAST_USER_NEEDED_IN_ROLE", tenantAdminRoleName)); } } return true; } private boolean canDeleteRole(Session session, final IPentahoRole role) { return !(role != null && systemRoles.contains(role.getName())); } private String[] findRemovedUsers(List<IPentahoUser> savedUsers, String[] toBeSaved) { List<String> usersToBeRemoved = new ArrayList<String>(); List<String> toBeSavedUsers = Arrays.asList(toBeSaved); for (int i = 0; i < savedUsers.size(); i++) { if (toBeSavedUsers != null && toBeSaved.length > 0) { if (!toBeSavedUsers.contains(savedUsers.get(i).getUsername())) { usersToBeRemoved.add(savedUsers.get(i).getUsername()); } } else { usersToBeRemoved.add(savedUsers.get(i).getUsername()); } } return usersToBeRemoved.toArray(new String[0]); } }