/*
* 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] );
}
}