/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.core.security.userstore.connector.remote; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.locks.Lock; import org.springframework.util.Assert; import com.google.common.base.Preconditions; import com.enonic.cms.framework.util.GenericConcurrencyLock; import com.enonic.cms.api.plugin.ext.auth.AuthenticationResult; import com.enonic.cms.api.plugin.ext.userstore.RemoteGroup; import com.enonic.cms.api.plugin.ext.userstore.RemotePrincipal; import com.enonic.cms.api.plugin.ext.userstore.RemoteUser; import com.enonic.cms.api.plugin.ext.userstore.RemoteUserStore; import com.enonic.cms.api.plugin.ext.userstore.UserFieldType; import com.enonic.cms.api.plugin.ext.userstore.UserFields; import com.enonic.cms.api.plugin.ext.userstore.UserStoreConfig; import com.enonic.cms.core.security.InvalidCredentialsException; import com.enonic.cms.core.security.group.DeleteGroupCommand; import com.enonic.cms.core.security.group.GroupEntity; import com.enonic.cms.core.security.group.GroupKey; import com.enonic.cms.core.security.group.GroupType; import com.enonic.cms.core.security.group.StoreNewGroupCommand; import com.enonic.cms.core.security.group.UpdateGroupCommand; import com.enonic.cms.core.security.user.DeleteUserCommand; import com.enonic.cms.core.security.user.DisplayNameResolver; import com.enonic.cms.core.security.user.ReadOnlyUserFieldValidator; import com.enonic.cms.core.security.user.StoreNewUserCommand; import com.enonic.cms.core.security.user.UpdateUserCommand; import com.enonic.cms.core.security.user.User; import com.enonic.cms.core.security.user.UserEntity; import com.enonic.cms.core.security.user.UserImpl; import com.enonic.cms.core.security.user.UserKey; import com.enonic.cms.core.security.user.UserNotFoundException; import com.enonic.cms.core.security.userstore.UserStoreConnectorPolicyBrokenException; import com.enonic.cms.core.security.userstore.UserStoreEntity; import com.enonic.cms.core.security.userstore.UserStoreKey; import com.enonic.cms.core.security.userstore.connector.AbstractBaseUserStoreConnector; import com.enonic.cms.core.security.userstore.connector.AuthenticationChain; import com.enonic.cms.core.security.userstore.connector.GroupAlreadyExistsException; import com.enonic.cms.core.security.userstore.connector.UserAlreadyExistsException; import com.enonic.cms.core.security.userstore.connector.config.UserStoreConnectorConfig; import com.enonic.cms.core.security.userstore.connector.synchronize.status.SynchronizeStatus; import com.enonic.cms.core.time.TimeService; public class RemoteUserStoreConnector extends AbstractBaseUserStoreConnector { private static GenericConcurrencyLock<String> concurrencyLock = GenericConcurrencyLock.create(); private RemoteUserStore remoteUserStorePlugin; private TimeService timeService; private UserStoreConnectorConfig connectorConfig; private UserStoreConfig userStoreConfig; public RemoteUserStoreConnector( final UserStoreKey userStoreKey, final String userStoreName, final String connectorName ) { super( userStoreKey, userStoreName, connectorName ); } public boolean canCreateUser() { return connectorConfig.canCreateUser(); } public boolean canUpdateUser() { return connectorConfig.canUpdateUser(); } public boolean canUpdateUserPassword() { return connectorConfig.canUpdateUserPassword(); } public boolean canDeleteUser() { return connectorConfig.canDeleteUser(); } public boolean canCreateGroup() { return connectorConfig.canCreateGroup(); } public boolean canReadGroup() { return connectorConfig.canReadGroup(); } public boolean canUpdateGroup() { return connectorConfig.canUpdateGroup(); } public boolean canDeleteGroup() { return connectorConfig.canDeleteGroup(); } public UserKey storeNewUser( final StoreNewUserCommand command ) { if ( !connectorConfig.canCreateUser() ) { throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to create user without 'create' policy" ); } Assert.isTrue( command.getUserStoreKey().equals( userStoreKey ) ); ensureValidUserName( command ); RemoteUser remoteUser = new RemoteUser( command.getUsername() ); remoteUser.setEmail( command.getEmail() ); final UserFields remoteUserFields = command.getUserFields().getRemoteFields( userStoreConfig ); remoteUser.getUserFields().addAll( remoteUserFields.getAll() ); final boolean success = remoteUserStorePlugin.addPrincipal( remoteUser ); if ( !success ) { throw new UserAlreadyExistsException( userStoreName, command.getUsername() ); } remoteUserStorePlugin.changePassword( command.getUsername(), command.getPassword() ); remoteUser = getRemoteUser( command.getUsername() ); command.setSyncValue( remoteUser.getSync() ); if ( connectorConfig.groupsStoredRemote() ) { addMembershipsRemote( remoteUser, command.getMemberships() ); } return storeNewUserLocally( command, new DisplayNameResolver( getUserStore().getConfig() ) ); } protected boolean isUsernameUnique( final String userName ) { final UserEntity localUser = getLocalUserWithUsername( userName ); final RemoteUser remoteUser = getRemoteUser( userName ); return localUser == null && remoteUser == null; } public void updateUser( final UpdateUserCommand command ) { final UserEntity userToUpdate = userDao.findSingleBySpecification( command.getSpecification() ); if ( userToUpdate == null ) { throw new UserNotFoundException( command.getSpecification() ); } final RemoteUser remoteUser = getRemoteUser( userToUpdate.getName() ); if ( remoteUser == null ) { throw new RuntimeException( "User not found in remote userstore '" + userStoreName + "' from specification: " + command.getSpecification().toString() ); } if ( !connectorConfig.canUpdateUser() && commandContainsChangedRemoteFields( command, remoteUser ) ) { // Trying to update remote fields: throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to update user without 'update' policy" ); } new ReadOnlyUserFieldValidator( getUserStore().getConfig() ).validate( command.getUserFields().getChangedUserFields( remoteUser.getUserFields().getConfiguredFieldsOnly( userStoreConfig ), command.isUpdateStrategy() ) ); new UserPolicyValidator( connectorConfig, getUserStore() ).validateFieldsForUpdate( command, remoteUser ); if ( connectorConfig.canUpdateUser() ) { updateUserModifiableValues( command, remoteUser ); final boolean success = remoteUserStorePlugin.updatePrincipal( remoteUser ); if ( !success ) { throw new RuntimeException( "User does not exists: " + command.getSpecification().getName() ); } } if ( connectorConfig.canUpdateGroup() && connectorConfig.groupsStoredRemote() && command.syncMemberships() ) { updateMembershipsRemote( userToUpdate, remoteUser, command.getMemberships() ); } resetRemoteFieldsInCommand( command, remoteUser ); updateUserLocally( command ); } private boolean commandContainsChangedRemoteFields( final UpdateUserCommand command, final RemoteUser remoteUser ) { final UserFields remoteFieldsInCommand = command.getUserFields().getConfiguredFieldsOnly( userStoreConfig ).getRemoteFields( userStoreConfig ).emptiesToNull(); final UserFields configuredFieldsOnlyInRemoteUser = remoteUser.getUserFields().getConfiguredFieldsOnly( userStoreConfig ); return !remoteFieldsInCommand.existingFieldsEquals( configuredFieldsOnlyInRemoteUser ); } private void resetRemoteFieldsInCommand( final UpdateUserCommand command, final RemoteUser remoteUser ) { final UserFields commandUserFields = command.getUserFields(); // remove remote fields from update command commandUserFields.retain( userStoreConfig.getLocalOnlyUserFieldTypes() ); // get remote fields values from remote user final UserFields remoteFields = remoteUser.getUserFields().getConfiguredFieldsOnly( userStoreConfig ); remoteFields.retain( userStoreConfig.getRemoteOnlyUserFieldTypes() ); // merge remote fields with local fields from command commandUserFields.addAll( remoteFields.getAll() ); command.setUserFields( commandUserFields ); } private void updateUserModifiableValues( final UpdateUserCommand command, final RemoteUser remoteUser ) { final String email = command.getEmail(); if ( email != null || command.isUpdateStrategy() ) { remoteUser.setEmail( email ); } final UserFields givenRemoteUserFields = command.getUserFields().getRemoteFields( userStoreConfig ); final UserFields remoteUserFields = remoteUser.getUserFields(); if ( command.isUpdateStrategy() ) { remoteUserFields.clear(); } // Remove address field on "target" when address field is set : JVS, ok but why? if ( givenRemoteUserFields.hasField( UserFieldType.ADDRESS ) ) { remoteUserFields.remove( UserFieldType.ADDRESS ); } remoteUserFields.addAll( givenRemoteUserFields.getAll() ); } public void deleteUser( final DeleteUserCommand command ) { if ( !connectorConfig.canDeleteUser() ) { throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to delete user without 'delete' policy" ); } final UserEntity userToDelete = userDao.findSingleBySpecification( command.getSpecification() ); remoteUserStorePlugin.removePrincipal( new RemoteUser( userToDelete.getName() ) ); deleteUserLocally( command ); } public GroupKey storeNewGroup( final StoreNewGroupCommand command ) { if ( !connectorConfig.canCreateGroup() ) { throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to create group without 'create' policy" ); } Assert.isTrue( command.getUserStoreKey().equals( userStoreKey ) ); if ( connectorConfig.groupsStoredRemote() ) { RemoteGroup remoteGroup = new RemoteGroup( command.getName() ); final boolean success = remoteUserStorePlugin.addPrincipal( remoteGroup ); if ( !success ) { throw new GroupAlreadyExistsException( userStoreName, command.getName() ); } remoteGroup = getRemoteGroup( command.getName() ); command.setSyncValue( remoteGroup.getSync() ); final List<GroupKey> members = command.getMembers(); if ( members != null && members.size() > 0 ) { addMembersRemote( remoteGroup, members ); } } return storeNewGroupLocally( command ); } public void updateGroup( final UpdateGroupCommand command ) { if ( !connectorConfig.canUpdateGroup() ) { throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to update group without 'update' policy" ); } if ( connectorConfig.groupsStoredRemote() ) { final GroupEntity groupToUpdate = groupDao.findByKey( command.getGroupKey() ); Preconditions.checkNotNull( command.getName(), "missing name in command" ); Preconditions.checkNotNull( groupToUpdate, "group does not exist: " + command.getGroupKey() ); if ( !command.getName().equals( groupToUpdate.getName() ) ) { throw new IllegalArgumentException( "Changing names of a groups in remote user stores is not supported: " + groupToUpdate.getQualifiedName().toString() ); } final RemoteGroup remoteGroup = getRemoteGroup( command.getName() ); if ( command.getMembers() != null ) { updateMembersRemote( groupToUpdate, remoteGroup, command.getMembers() ); } } updateGroupLocally( command ); } private List<RemotePrincipal> toPrincipalList( final RemotePrincipal... principals ) { final ArrayList<RemotePrincipal> list = new ArrayList<RemotePrincipal>(); list.addAll( Arrays.asList( principals ) ); return list; } public void addMembershipToGroup( final GroupEntity groupToAdd, final GroupEntity groupToAddTo ) { if ( !connectorConfig.canUpdateGroup() ) { throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to add membership to group without 'update' policy" ); } if ( connectorConfig.groupsStoredRemote() ) { if ( groupToAdd.isOfType( GroupType.USER, false ) ) { addMembersToRemoteGroup( groupToAddTo.getName(), toPrincipalList( new RemoteUser( groupToAdd.getUser().getName() ) ) ); } else { addMembersToRemoteGroup( groupToAddTo.getName(), toPrincipalList( new RemoteGroup( groupToAdd.getName() ) ) ); } } addMembershipToGroupLocally( groupToAdd, groupToAddTo ); } public void removeMembershipFromGroup( final GroupEntity groupToRemove, final GroupEntity groupToRemoveFrom ) { if ( !connectorConfig.canUpdateGroup() ) { throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to remove membership from group without 'update' policy" ); } if ( connectorConfig.groupsStoredRemote() ) { if ( groupToRemove.isOfType( GroupType.USER, false ) ) { removeMembersFromRemoteGroup( groupToRemoveFrom.getName(), toPrincipalList( new RemoteUser( groupToRemove.getUser().getName() ) ) ); } else { removeMembersFromRemoteGroup( groupToRemoveFrom.getName(), toPrincipalList( new RemoteGroup( groupToRemove.getName() ) ) ); } } removeMembershipFromGroupLocally( groupToRemove, groupToRemoveFrom ); } public void deleteGroup( final DeleteGroupCommand command ) { if ( !connectorConfig.canDeleteGroup() ) { throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to delete group without 'delete' policy" ); } if ( connectorConfig.groupsStoredRemote() ) { final GroupEntity groupToDelete = groupDao.findSingleBySpecification( command.getSpecification() ); remoteUserStorePlugin.removePrincipal( new RemoteGroup( groupToDelete.getName() ) ); } deleteGroupLocally( command ); } private boolean verifyPassword( final String uid, final String password, final AuthenticationChain authChain ) { final AuthenticationResult result = authChain.authenticate( getUserStoreName(), uid, password ); if ( result == AuthenticationResult.CONTINUE ) { return this.remoteUserStorePlugin.authenticate( uid, password ); } return result == AuthenticationResult.OK; } public String authenticateUser( final String uid, final String password, final AuthenticationChain authChain ) { if ( !verifyPassword( uid, password, authChain ) ) { throw new InvalidCredentialsException( uid ); } return getRemoteUser( uid ).getSync(); } public void changePassword( final String uid, final String newPassword ) { if ( !connectorConfig.canUpdateUserPassword() ) { throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to change password without 'updatePassword' policy" ); } final boolean success = remoteUserStorePlugin.changePassword( uid, newPassword ); if ( !success ) { throw new RuntimeException( "Changed password failed" ); } } public synchronized void synchronizeUsers( final SynchronizeStatus status, final List<RemoteUser> remoteUsers, final boolean syncMemberships, final MemberCache memberCache ) { doSynchronizeUsers( status, remoteUsers, true, syncMemberships, memberCache ); } public synchronized void synchronizeUserMemberships( final SynchronizeStatus status, final RemoteUser remoteUser, final MemberCache memberCache ) { final List<RemoteUser> remoteUsers = new ArrayList<RemoteUser>( 1 ); remoteUsers.add( remoteUser ); doSynchronizeUsers( status, remoteUsers, false, true, memberCache ); } private void doSynchronizeUsers( final SynchronizeStatus status, final List<RemoteUser> remoteUsers, final boolean syncUser, final boolean syncMemberships, final MemberCache memberCache ) { final UserStoreEntity userStore = userStoreDao.findByKey( userStoreKey ); final boolean doSyncMemberships = connectorConfig.groupsStoredRemote() && syncMemberships; final UsersSynchronizer synchronizer = new UsersSynchronizer( status, userStore, syncUser, doSyncMemberships ); synchronizer.setUserStorer( userStorerFactory.create( userStore.getKey() ) ); synchronizer.setGroupStorer( groupStorerFactory.create( userStore.getKey() ) ); synchronizer.setGroupDao( groupDao ); synchronizer.setUserDao( userDao ); synchronizer.setRemoteUserStorePlugin( remoteUserStorePlugin ); synchronizer.setTimeService( timeService ); synchronizer.setConnectorConfig( connectorConfig ); synchronizer.setStatusCollector( status ); synchronizer.synchronizeUsers( remoteUsers, memberCache ); } public void synchronizeUser( final String uid ) { final Lock locker = concurrencyLock.getLock( uid ); try { locker.lock(); final UserStoreEntity userStore = userStoreDao.findByKey( userStoreKey ); final boolean syncMemberships = connectorConfig.groupsStoredRemote(); final UserSynchronizer synchronizer = new UserSynchronizer( userStore, syncMemberships ); synchronizer.setUserStorer( userStorerFactory.create( userStore.getKey() ) ); synchronizer.setGroupStorer( groupStorerFactory.create( userStore.getKey() ) ); synchronizer.setGroupDao( groupDao ); synchronizer.setUserDao( userDao ); synchronizer.setRemoteUserStorePlugin( remoteUserStorePlugin ); synchronizer.setTimeService( timeService ); synchronizer.setConnectorConfig( connectorConfig ); synchronizer.synchronizeUser( uid ); } finally { locker.unlock(); } } public synchronized void synchronizeGroup( final GroupEntity group, final boolean syncMemberships, final boolean syncMembers ) { if ( !connectorConfig.canReadGroup() ) { throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to synchronize group without 'read' policy" ); } final UserStoreEntity userStore = userStoreDao.findByKey( userStoreKey ); final GroupSynchronizer synchronizer = new GroupSynchronizer( userStore, syncMemberships, syncMembers ); synchronizer.setRemoteUserStorePlugin( remoteUserStorePlugin ); synchronizer.setUserDao( userDao ); synchronizer.setGroupDao( groupDao ); synchronizer.synchronize( group, new MemberCache() ); } public synchronized void synchronizeGroups( final SynchronizeStatus status, final List<RemoteGroup> remoteGroups, final boolean syncMemberships, final boolean syncMembers, final MemberCache memberCache ) { if ( !connectorConfig.canReadGroup() ) { throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to synchronize groups without 'read' policy" ); } doSynchronizeGroups( status, remoteGroups, true, syncMemberships, syncMembers, memberCache ); } public synchronized void synchronizeGroupMemberships( final SynchronizeStatus status, final RemoteGroup remoteGroup, final MemberCache memberCache ) { if ( !connectorConfig.canReadGroup() ) { throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to synchronize groups without 'read' policy" ); } final List<RemoteGroup> remoteGroups = new ArrayList<RemoteGroup>( 1 ); remoteGroups.add( remoteGroup ); doSynchronizeGroups( status, remoteGroups, false, true, false, memberCache ); } private void doSynchronizeGroups( final SynchronizeStatus status, final List<RemoteGroup> remoteGroups, final boolean syncGroup, final boolean syncMemberships, final boolean syncMembers, final MemberCache memberCache ) { final UserStoreEntity userStore = userStoreDao.findByKey( userStoreKey ); final GroupsSynchronizer synchronizer = new GroupsSynchronizer( status, userStore, syncGroup, syncMemberships, syncMembers ); synchronizer.setRemoteUserStorePlugin( remoteUserStorePlugin ); synchronizer.setUserDao( userDao ); synchronizer.setGroupDao( groupDao ); synchronizer.setGroupStorer( groupStorerFactory.create( userStoreKey ) ); synchronizer.synchronize( remoteGroups, memberCache ); } private void addMembershipsRemote( final RemoteUser remoteUser, final Collection<GroupKey> requestedMembershipKeys ) { final Set<GroupEntity> membershipsToAdd = getMembershipsToAddRemote( requestedMembershipKeys ); final boolean hasMembershipsChanges = membershipsToAdd.size() > 0; if ( hasMembershipsChanges && !connectorConfig.canUpdateGroup() ) { throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to add/remove a user's memberships without group 'update' policy" ); } for ( final GroupEntity membershipToAdd : membershipsToAdd ) { addMembersToRemoteGroup( membershipToAdd.getName(), toPrincipalList( remoteUser ) ); } } private void addMembersRemote( final RemoteGroup remoteGroup, final Collection<GroupKey> requestedMemberKeys ) { final List<RemotePrincipal> members = getMembersToAddRemote( requestedMemberKeys ); remoteUserStorePlugin.addMembers( remoteGroup, members ); } private void updateMembershipsRemote( final UserEntity userToUpdate, final RemoteUser remoteUser, final Collection<GroupKey> requestedMembershipKeys ) { final Set<GroupEntity> membershipsToRemove = getMembershipsToRemoveRemote( userToUpdate, requestedMembershipKeys ); final Set<GroupEntity> membershipsToAdd = getMembershipsToAddRemote( userToUpdate, requestedMembershipKeys ); final boolean hasMembershipsChanges = membershipsToRemove.size() > 0 || membershipsToAdd.size() > 0; if ( hasMembershipsChanges && !connectorConfig.canUpdateGroup() ) { throw new UserStoreConnectorPolicyBrokenException( userStoreName, connectorName, "Trying to add/remove a user's memberships without group 'update' policy" ); } for ( final GroupEntity membershipToAdd : membershipsToAdd ) { addMembersToRemoteGroup( membershipToAdd.getName(), toPrincipalList( remoteUser ) ); } for ( final GroupEntity membershipToRemove : membershipsToRemove ) { removeMembersFromRemoteGroup( membershipToRemove.getName(), toPrincipalList( remoteUser ) ); } } private void updateMembersRemote( final GroupEntity groupToUpdate, final RemoteGroup remoteGroup, final Collection<GroupEntity> requestedMembers ) { final List<RemotePrincipal> membersToRemove = getMembersToRemoveRemote( groupToUpdate, requestedMembers ); remoteUserStorePlugin.removeMembers( remoteGroup, membersToRemove ); final List<RemotePrincipal> membersToAdd = getMembersToAddRemote( groupToUpdate, requestedMembers ); remoteUserStorePlugin.addMembers( remoteGroup, membersToAdd ); } private void addMembersToRemoteGroup( final String groupName, final List<RemotePrincipal> members ) { final RemoteGroup remoteGroup = getRemoteGroup( groupName ); remoteUserStorePlugin.addMembers( remoteGroup, members ); } private void removeMembersFromRemoteGroup( final String groupName, final List<RemotePrincipal> members ) { final RemoteGroup remoteGroup = getRemoteGroup( groupName ); remoteUserStorePlugin.removeMembers( remoteGroup, members ); } private Set<GroupEntity> getMembershipsToAddRemote( final Collection<GroupKey> requestedMembershipKeys ) { final Set<GroupEntity> membershipsToAdd = new HashSet<GroupEntity>(); for ( final GroupKey membershipKey : requestedMembershipKeys ) { final GroupEntity membership = groupDao.findByKey( membershipKey ); if ( membership.getType() == GroupType.USERSTORE_GROUP ) { verifyCorrectUserstore( membership ); membershipsToAdd.add( membership ); } } return membershipsToAdd; } private Set<GroupEntity> getMembershipsToAddRemote( final UserEntity userToUpdate, final Collection<GroupKey> requestedMembershipKeys ) { final Set<GroupEntity> membershipsToAdd = new HashSet<GroupEntity>(); final Set<GroupEntity> currentMemberships = userToUpdate.getDirectMemberships(); for ( final GroupKey requestedMembershipKey : requestedMembershipKeys ) { final GroupEntity requestedMembership = groupDao.findByKey( requestedMembershipKey ); if ( requestedMembership.getType() == GroupType.USERSTORE_GROUP && !currentMemberships.contains( requestedMembership ) ) { verifyCorrectUserstore( requestedMembership ); membershipsToAdd.add( requestedMembership ); } } return membershipsToAdd; } private Set<GroupEntity> getMembershipsToRemoveRemote( final UserEntity userToUpdate, final Collection<GroupKey> requestedMembershipKeys ) { final Set<GroupEntity> membershipsToRemove = new HashSet<GroupEntity>(); final Set<GroupEntity> currentMemberships = userToUpdate.getDirectMemberships(); for ( final GroupEntity currentMembership : currentMemberships ) { if ( currentMembership.getType() == GroupType.USERSTORE_GROUP && !requestedMembershipKeys.contains( currentMembership.getGroupKey() ) ) { verifyCorrectUserstore( currentMembership ); membershipsToRemove.add( currentMembership ); } } return membershipsToRemove; } private List<RemotePrincipal> getMembersToAddRemote( final Collection<GroupKey> requestedMemberKeys ) { final List<RemotePrincipal> membersToAdd = new ArrayList<RemotePrincipal>(); for ( final GroupKey requestedMemberKey : requestedMemberKeys ) { final GroupEntity requestedMember = groupDao.findByKey( requestedMemberKey ); if ( requestedMember.getType() == GroupType.USERSTORE_GROUP ) { verifyCorrectUserstore( requestedMember ); membersToAdd.add( new RemoteGroup( requestedMember.getName() ) ); } if ( requestedMember.getType() == GroupType.USER ) { verifyCorrectUserstore( requestedMember ); final UserEntity user = requestedMember.getUser(); verifyCorrectUserstore( user ); membersToAdd.add( new RemoteUser( user.getName() ) ); } } return membersToAdd; } private List<RemotePrincipal> getMembersToAddRemote( final GroupEntity groupToUpdate, final Collection<GroupEntity> requestedMembers ) { final List<RemotePrincipal> membersToAdd = new ArrayList<RemotePrincipal>(); final Set<GroupEntity> currentMembers = groupToUpdate.getMembers( false ); for ( final GroupEntity requestedMember : requestedMembers ) { if ( requestedMember.getType() == GroupType.USERSTORE_GROUP && !currentMembers.contains( requestedMember ) ) { verifyCorrectUserstore( requestedMember ); membersToAdd.add( new RemoteGroup( requestedMember.getName() ) ); } if ( requestedMember.getType() == GroupType.USER && !currentMembers.contains( requestedMember ) ) { verifyCorrectUserstore( requestedMember ); final UserEntity user = requestedMember.getUser(); verifyCorrectUserstore( user ); membersToAdd.add( new RemoteUser( user.getName() ) ); } } return membersToAdd; } private List<RemotePrincipal> getMembersToRemoveRemote( final GroupEntity groupToUpdate, final Collection<GroupEntity> requestedMembers ) { final List<RemotePrincipal> membersToRemove = new ArrayList<RemotePrincipal>(); final Set<GroupEntity> currentMembers = groupToUpdate.getMembers( false ); for ( final GroupEntity currentMember : currentMembers ) { if ( currentMember.getType() == GroupType.USERSTORE_GROUP && !requestedMembers.contains( currentMember ) ) { verifyCorrectUserstore( currentMember ); membersToRemove.add( new RemoteGroup( currentMember.getName() ) ); } if ( currentMember.getType() == GroupType.USER && !requestedMembers.contains( currentMember ) ) { verifyCorrectUserstore( currentMember ); final UserEntity user = currentMember.getUser(); verifyCorrectUserstore( user ); membersToRemove.add( new RemoteUser( user.getName() ) ); } } return membersToRemove; } private RemoteGroup getRemoteGroup( final String groupName ) { final RemoteGroup remoteGroup = remoteUserStorePlugin.getGroup( groupName ); if ( remoteGroup == null ) { throw new IllegalArgumentException( "Group does not exists in remote user store '" + userStoreName + "': " + groupName ); } return remoteGroup; } private void verifyCorrectUserstore( final UserEntity user ) { if ( !userStoreKey.equals( user.getUserStoreKey() ) ) { throw new IllegalArgumentException( "Illegal userstore. Cannot add user " + user.getQualifiedName() + " to userstore " + userStoreName ); } } private void verifyCorrectUserstore( final GroupEntity group ) { if ( !userStoreKey.equals( group.getUserStoreKey() ) ) { throw new IllegalArgumentException( "Illegal userstore. Cannot add group " + group.getQualifiedName() + " to userstore " + userStoreName ); } } private RemoteUser getRemoteUser( String uid ) { return remoteUserStorePlugin.getUser( uid ); } public User getUserByEntity( final UserEntity userEntity ) { return UserImpl.createFrom( userEntity ); } public List<RemoteUser> getAllUsers() { return remoteUserStorePlugin.getAllUsers(); } public List<RemoteGroup> getAllGroups() { return remoteUserStorePlugin.getAllGroups(); } public void setRemoteUserStorePlugin( final RemoteUserStore value ) { remoteUserStorePlugin = value; } public void setTimeService( final TimeService value ) { timeService = value; } public void setConnectorConfig( final UserStoreConnectorConfig value ) { connectorConfig = value; } public void setUserStoreConfig( final UserStoreConfig value ) { userStoreConfig = value; } }