
org.craftercms.profile.social.ProfileConnectionRepository Maven / Gradle / Ivy
The newest version!
package org.craftercms.profile.social;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.craftercms.commons.crypto.CryptoException;
import org.craftercms.commons.crypto.TextEncryptor;
import org.craftercms.profile.api.Profile;
import org.craftercms.profile.api.exceptions.ProfileException;
import org.craftercms.profile.api.services.ProfileService;
import org.craftercms.profile.social.exceptions.ProfileConnectionRepositoryException;
import org.craftercms.profile.social.utils.TenantResolver;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.ConnectionData;
import org.springframework.social.connect.ConnectionFactory;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.ConnectionKey;
import org.springframework.social.connect.ConnectionRepository;
import org.springframework.social.connect.NoSuchConnectionException;
import org.springframework.social.connect.NotConnectedException;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import static org.craftercms.profile.social.utils.ConnectionUtils.*;
/**
* Implementation of {@link org.springframework.social.connect.ConnectionRepository} that uses a profile to persist
* the connection information. If the profile is null while adding a connection, a new profile is created from the
* connection information.
*
* @author avasquez
*/
public class ProfileConnectionRepository implements ConnectionRepository {
protected ConnectionFactoryLocator connectionFactoryLocator;
protected Profile profile;
protected ProfileService profileService;
protected TenantResolver tenantResolver;
protected TextEncryptor encryptor;
public ProfileConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator, Profile profile,
ProfileService profileService, TextEncryptor encryptor) {
this.connectionFactoryLocator = connectionFactoryLocator;
this.profile = profile;
this.profileService = profileService;
this.encryptor = encryptor;
}
public ProfileConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator,
ProfileService profileService, TenantResolver tenantResolver,
TextEncryptor encryptor) {
this.connectionFactoryLocator = connectionFactoryLocator;
this.profileService = profileService;
this.tenantResolver = tenantResolver;
this.encryptor = encryptor;
}
public Profile getProfile() {
return profile;
}
@Override
public MultiValueMap> findAllConnections() {
if (profile == null) {
return new LinkedMultiValueMap<>();
}
MultiValueMap> allConnections = new LinkedMultiValueMap<>();
Map>> allConnectionData = getConnectionsAttribute(profile);
if (MapUtils.isNotEmpty(allConnectionData)) {
for (Map.Entry>> entry : allConnectionData.entrySet()) {
String providerId = entry.getKey();
for (Map connectionDataMap : entry.getValue()) {
ConnectionData connectionData;
try {
connectionData = mapToConnectionData(providerId, connectionDataMap, encryptor);
} catch (CryptoException e) {
throw new ProfileConnectionRepositoryException("Decryption error", e);
}
Connection> connection = createConnection(connectionData);
allConnections.add(providerId, connection);
}
}
}
return allConnections;
}
@Override
public List> findConnections(String providerId) {
if (profile == null) {
return Collections.emptyList();
}
List> connections = new ArrayList<>();
List connectionDataList;
try {
connectionDataList = getConnectionData(profile, providerId, encryptor);
} catch (CryptoException e) {
throw new ProfileConnectionRepositoryException("Decryption error", e);
}
if (CollectionUtils.isNotEmpty(connectionDataList)) {
for (ConnectionData connectionData : connectionDataList) {
connections.add(createConnection(connectionData));
}
}
return connections;
}
@Override
@SuppressWarnings("unchecked")
public List> findConnections(Class apiType) {
List> connections = findConnections(getProviderId(apiType));
return (List>) connections;
}
@Override
public MultiValueMap> findConnectionsToUsers(MultiValueMap providerUserIds) {
if (profile == null) {
return new LinkedMultiValueMap<>();
}
MultiValueMap> connectionsForUserIds = new LinkedMultiValueMap<>();
for (Map.Entry> entry : providerUserIds.entrySet()) {
String providerId = entry.getKey();
List connectionDataList;
try {
connectionDataList = getConnectionData(profile, providerId, encryptor);
} catch (CryptoException e) {
throw new ProfileConnectionRepositoryException("Decryption error", e);
}
for (String providerUserId : entry.getValue()) {
Connection> connection = findConnection(connectionDataList, providerUserId);
connectionsForUserIds.add(providerId, connection);
}
}
return connectionsForUserIds;
}
@Override
public Connection> getConnection(ConnectionKey connectionKey) {
if (profile == null) {
throw new NoSuchConnectionException(connectionKey);
}
String providerId = connectionKey.getProviderId();
List connectionDataList;
try {
connectionDataList = getConnectionData(profile, providerId, encryptor);
} catch (CryptoException e) {
throw new ProfileConnectionRepositoryException("Decryption error", e);
}
Connection> connection = findConnection(connectionDataList, connectionKey.getProviderUserId());
if (connection != null) {
return connection;
} else {
throw new NoSuchConnectionException(connectionKey);
}
}
@Override
@SuppressWarnings("unchecked")
public Connection getConnection(Class apiType, String providerUserId) {
return (Connection) getConnection(new ConnectionKey(getProviderId(apiType), providerUserId));
}
@Override
public Connection getPrimaryConnection(Class apiType) {
Connection connection = findPrimaryConnection(apiType);
if (connection != null) {
return connection;
} else {
throw new NotConnectedException(getProviderId(apiType));
}
}
@Override
@SuppressWarnings("unchecked")
public Connection findPrimaryConnection(Class apiType) {
if (profile == null) {
return null;
}
String providerId = getProviderId(apiType);
List> connections = findConnections(providerId);
if (CollectionUtils.isNotEmpty(connections)){
return (Connection) connections.get(0);
} else {
return null;
}
}
@Override
public void addConnection(Connection> connection) {
if (profile == null) {
profile = getProfileFromConnection(connection);
Profile existingProfile = findProfileByUsername(profile.getTenant(), profile.getUsername());
if (existingProfile != null) {
profile = existingProfile;
try {
addConnectionData(profile, connection.createData(), encryptor);
} catch (CryptoException e) {
throw new ProfileConnectionRepositoryException("Encryption error", e);
}
updateProfile();
} else {
createProfile();
}
} else {
try {
addConnectionData(profile, connection.createData(), encryptor);
} catch (CryptoException e) {
throw new ProfileConnectionRepositoryException("Encryption error", e);
}
updateProfile();
}
}
@Override
public void updateConnection(Connection> connection) {
if (profile == null) {
throw new IllegalStateException("Missing profile in connection repository");
}
try {
addConnectionData(profile, connection.createData(), encryptor);
} catch (CryptoException e) {
throw new ProfileConnectionRepositoryException("Encryption error", e);
}
updateProfile();
}
@Override
public void removeConnections(String providerId) {
if (profile != null) {
removeConnectionData(profile, providerId);
updateProfile();
}
}
@Override
public void removeConnection(ConnectionKey connectionKey) {
if (profile != null) {
String providerId = connectionKey.getProviderId();
String providerUserId = connectionKey.getProviderUserId();
removeConnectionData(providerId, providerUserId, profile);
updateProfile();
}
}
protected Connection> createConnection(ConnectionData data) {
ConnectionFactory> connectionFactory = connectionFactoryLocator.getConnectionFactory(data.getProviderId());
return connectionFactory.createConnection(data);
}
protected Connection> findConnection(List connectionDataList, String providerUserId) {
if (CollectionUtils.isNotEmpty(connectionDataList)) {
for (ConnectionData connectionData : connectionDataList) {
if (connectionData.getProviderUserId().equals(providerUserId)) {
return createConnection(connectionData);
}
}
}
return null;
}
protected Map>> getConnectionsAttribute(Profile profile) {
return profile.getAttribute(CONNECTIONS_ATTRIBUTE_NAME);
}
protected String getProviderId(Class apiType) {
return connectionFactoryLocator.getConnectionFactory(apiType).getProviderId();
}
protected void createProfile() {
String tenant = profile.getTenant();
boolean enabled = profile.isEnabled();
String username = profile.getUsername();
String email = profile.getEmail();
Map attributes = profile.getAttributes();
try {
profile = profileService.createProfile(tenant, username, null, email, enabled, null, attributes, null);
} catch (ProfileException e) {
throw new ProfileConnectionRepositoryException("Unable to create profile for user '" + username + "'", e);
}
}
protected Profile getProfileFromConnection(Connection> connection) {
Profile profile = new Profile();
profile.setTenant(tenantResolver.getCurrentTenant());
profile.setEnabled(true);
addProviderProfileInfo(profile, connection.fetchUserProfile());
try {
addConnectionData(profile, connection.createData(), encryptor);
} catch (CryptoException e) {
throw new ProfileConnectionRepositoryException("Encryption error", e);
}
return profile;
}
protected void updateProfile() {
try {
profile = profileService.updateAttributes(profile.getId().toString(), profile.getAttributes());
} catch (ProfileException e) {
throw new ProfileConnectionRepositoryException("Unable to update profile of user '" + profile
.getUsername() + "'", e);
}
}
protected Profile findProfileByUsername(String tenant, String username) {
try {
return profileService.getProfileByUsername(tenant, username);
} catch (ProfileException e) {
throw new ProfileConnectionRepositoryException("Unable to find profile for user '" + username +
" of tenant '" + tenant + "'", e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy