// Path: social-redis-spring-boot-starter/src/main/java/be/ordina/jworks/social/redis/connection/RedisUsersConnectionRepository.java
// public class RedisUsersConnectionRepository implements UsersConnectionRepository {
// 
//     private final ConnectionFactoryLocator connectionFactoryLocator;
//     private final TextEncryptor textEncryptor;
//     private final SocialRedisConnectionRepository socialRedisConnectionRepository;
// 
//     public RedisUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator, TextEncryptor textEncryptor, SocialRedisConnectionRepository socialRedisConnectionRepository) {
//         Assert.notNull(connectionFactoryLocator);
//         Assert.notNull(textEncryptor);
//         Assert.notNull(socialRedisConnectionRepository);
// 
//         this.connectionFactoryLocator = connectionFactoryLocator;
//         this.textEncryptor = textEncryptor;
//         this.socialRedisConnectionRepository = socialRedisConnectionRepository;
//     }
// 
//     public List<String> findUserIdsWithConnection(final Connection<?> connection) {
//         String providerId = connection.getKey().getProviderId();
//         String providerUserId = connection.getKey().getProviderUserId();
// 
//         Iterable<SocialRedisConnection> connections = socialRedisConnectionRepository.findByProviderIdAndProviderUserId(providerId, providerUserId);
// 
//         List<String> userIds = new ArrayList<String>();
//         for (SocialRedisConnection socialRedisConnection : connections) {
//             userIds.add(socialRedisConnection.getUserId());
//         }
// 
//         return userIds;
//     }
// 
//     public Set<String> findUserIdsConnectedTo(final String providerId, final Set<String> providerUserIds) {
//         Set<String> userIds = new HashSet<String>();
// 
//         for (String providerUserId : providerUserIds) {
//             for (SocialRedisConnection socialRedisConnection : socialRedisConnectionRepository.findByProviderIdAndProviderUserId(providerId, providerUserId)) {
//                 userIds.add(socialRedisConnection.getUserId());
//             }
//         }
// 
//         return userIds;
//     }
// 
//     public ConnectionRepository createConnectionRepository(final String userId) {
//         return new RedisConnectionRepository(connectionFactoryLocator, textEncryptor, socialRedisConnectionRepository, userId);
//     }
// }
// 
// Path: social-redis-spring-boot-starter/src/main/java/be/ordina/jworks/social/redis/connection/data/SocialRedisConnectionRepository.java
// @Repository
// public interface SocialRedisConnectionRepository extends CrudRepository<SocialRedisConnection, String> {
// 
//     Iterable<SocialRedisConnection> findByProviderId(final String providerId);
// 
//     Iterable<SocialRedisConnection> findByUserIdAndProviderId(final String userId, final String providerId);
// 
//     SocialRedisConnection findOneByUserIdAndProviderIdAndProviderUserId(String userId, String providerId, String providerUserId);
// 
//     // TODO: will be available once DATAKV-135 is finished
//     void deleteByUserIdAndProviderIdAndProviderUserId(final String userId, final String providerId, final String providerUserId);
// 
//     Iterable<SocialRedisConnection> findByUserId(final String userId);
// 
//     Iterable<SocialRedisConnection> findByProviderIdAndProviderUserId(final String providerId, final String providerUserId);
// }


import be.ordina.jworks.social.redis.connection.RedisUsersConnectionRepository;
import be.ordina.jworks.social.redis.connection.data.SocialRedisConnectionRepository;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.*;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.*;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.social.UserIdSource;
import org.springframework.social.config.annotation.EnableSocial;
import org.springframework.social.config.annotation.SocialConfigurerAdapter;
import org.springframework.social.connect.*;
import org.springframework.social.connect.web.GenericConnectionStatusView;
import org.springframework.social.connect.web.ProviderSignInController;
import org.springframework.social.connect.web.SignInAdapter;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
import org.springframework.social.twitter.connect.TwitterConnectionFactory;
import org.springframework.util.Assert;
import org.springframework.web.context.request.NativeWebRequest;
            return usersConnectionRepository.createConnectionRepository(getUserIdSource().getUserId());
        }

        @Bean(name = {"connect/twitterConnect", "connect/twitterConnected"})
        @ConditionalOnProperty(prefix = "spring.social", name = "auto-connection-views")
        public GenericConnectionStatusView twitterConnectView() {
            return new GenericConnectionStatusView("twitter", "Twitter");
        }

        @Bean
        @ConditionalOnMissingBean
        public ProviderSignInController providerSignInController(ConnectionFactoryLocator connectionFactoryLocator, UsersConnectionRepository usersConnectionRepository) {
            return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new SpringSecuritySignInAdapter());
        }

        private class SpringSecuritySignInAdapter implements SignInAdapter {
            public String signIn(String localUserId, Connection<?> connection, NativeWebRequest request) {
                SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(localUserId, null, null));
                return null;
            }
        }

        @Override
        protected ConnectionFactory<?> createConnectionFactory() {
            return new TwitterConnectionFactory(this.properties.getAppId(),
                    this.properties.getAppSecret());
        }

        @Override
        public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
// Path: social-redis-spring-boot-starter/src/main/java/be/ordina/jworks/social/redis/connection/RedisUsersConnectionRepository.java
// public class RedisUsersConnectionRepository implements UsersConnectionRepository {
// 
//     private final ConnectionFactoryLocator connectionFactoryLocator;
//     private final TextEncryptor textEncryptor;
//     private final SocialRedisConnectionRepository socialRedisConnectionRepository;
// 
//     public RedisUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator, TextEncryptor textEncryptor, SocialRedisConnectionRepository socialRedisConnectionRepository) {
//         Assert.notNull(connectionFactoryLocator);
//         Assert.notNull(textEncryptor);
//         Assert.notNull(socialRedisConnectionRepository);
// 
//         this.connectionFactoryLocator = connectionFactoryLocator;
//         this.textEncryptor = textEncryptor;
//         this.socialRedisConnectionRepository = socialRedisConnectionRepository;
//     }
// 
//     public List<String> findUserIdsWithConnection(final Connection<?> connection) {
//         String providerId = connection.getKey().getProviderId();
//         String providerUserId = connection.getKey().getProviderUserId();
// 
//         Iterable<SocialRedisConnection> connections = socialRedisConnectionRepository.findByProviderIdAndProviderUserId(providerId, providerUserId);
// 
//         List<String> userIds = new ArrayList<String>();
//         for (SocialRedisConnection socialRedisConnection : connections) {
//             userIds.add(socialRedisConnection.getUserId());
//         }
// 
//         return userIds;
//     }
// 
//     public Set<String> findUserIdsConnectedTo(final String providerId, final Set<String> providerUserIds) {
//         Set<String> userIds = new HashSet<String>();
// 
//         for (String providerUserId : providerUserIds) {
//             for (SocialRedisConnection socialRedisConnection : socialRedisConnectionRepository.findByProviderIdAndProviderUserId(providerId, providerUserId)) {
//                 userIds.add(socialRedisConnection.getUserId());
//             }
//         }
// 
//         return userIds;
//     }
// 
//     public ConnectionRepository createConnectionRepository(final String userId) {
//         return new RedisConnectionRepository(connectionFactoryLocator, textEncryptor, socialRedisConnectionRepository, userId);
//     }
// }
// 
// Path: social-redis-spring-boot-starter/src/main/java/be/ordina/jworks/social/redis/connection/data/SocialRedisConnectionRepository.java
// @Repository
// public interface SocialRedisConnectionRepository extends CrudRepository<SocialRedisConnection, String> {
// 
//     Iterable<SocialRedisConnection> findByProviderId(final String providerId);
// 
//     Iterable<SocialRedisConnection> findByUserIdAndProviderId(final String userId, final String providerId);
// 
//     SocialRedisConnection findOneByUserIdAndProviderIdAndProviderUserId(String userId, String providerId, String providerUserId);
// 
//     // TODO: will be available once DATAKV-135 is finished
//     void deleteByUserIdAndProviderIdAndProviderUserId(final String userId, final String providerId, final String providerUserId);
// 
//     Iterable<SocialRedisConnection> findByUserId(final String userId);
// 
//     Iterable<SocialRedisConnection> findByProviderIdAndProviderUserId(final String providerId, final String providerUserId);
// }


// Path: social-redis-spring-boot-starter/src/main/java/org/springframework/boot/autoconfigure/social/TwitterRedisAutoConfiguration.java
import be.ordina.jworks.social.redis.connection.RedisUsersConnectionRepository;
import be.ordina.jworks.social.redis.connection.data.SocialRedisConnectionRepository;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.*;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.*;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.social.UserIdSource;
import org.springframework.social.config.annotation.EnableSocial;
import org.springframework.social.config.annotation.SocialConfigurerAdapter;
import org.springframework.social.connect.*;
import org.springframework.social.connect.web.GenericConnectionStatusView;
import org.springframework.social.connect.web.ProviderSignInController;
import org.springframework.social.connect.web.SignInAdapter;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
import org.springframework.social.twitter.connect.TwitterConnectionFactory;
import org.springframework.util.Assert;
import org.springframework.web.context.request.NativeWebRequest;

            return usersConnectionRepository.createConnectionRepository(getUserIdSource().getUserId());
        }

        @Bean(name = {"connect/twitterConnect", "connect/twitterConnected"})
        @ConditionalOnProperty(prefix = "spring.social", name = "auto-connection-views")
        public GenericConnectionStatusView twitterConnectView() {
            return new GenericConnectionStatusView("twitter", "Twitter");
        }

        @Bean
        @ConditionalOnMissingBean
        public ProviderSignInController providerSignInController(ConnectionFactoryLocator connectionFactoryLocator, UsersConnectionRepository usersConnectionRepository) {
            return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new SpringSecuritySignInAdapter());
        }

        private class SpringSecuritySignInAdapter implements SignInAdapter {
            public String signIn(String localUserId, Connection<?> connection, NativeWebRequest request) {
                SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(localUserId, null, null));
                return null;
            }
        }

        @Override
        protected ConnectionFactory<?> createConnectionFactory() {
            return new TwitterConnectionFactory(this.properties.getAppId(),
                    this.properties.getAppSecret());
        }

        @Override
        public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
            return new RedisUsersConnectionRepository(connectionFactoryLocator, Encryptors.noOpText(), socialRedisConnectionRepository);