package ee.esutoniagodesu.config;
import ee.esutoniagodesu.repository.domain.ac.UserRepository;
import ee.esutoniagodesu.security.SecurityUtils;
import ee.esutoniagodesu.security.social.SimpleSignInAdapter;
import ee.esutoniagodesu.security.social.SimpleSocialUserDetailsService;
import ee.esutoniagodesu.security.social.SocialConnectionSignUp;
import ee.esutoniagodesu.service.MailService;
import ee.esutoniagodesu.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.core.env.Environment;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.security.crypto.encrypt.TextEncryptor;
import org.springframework.social.UserIdSource;
import org.springframework.social.config.annotation.ConnectionFactoryConfigurer;
import org.springframework.social.config.annotation.EnableSocial;
import org.springframework.social.config.annotation.SocialConfigurerAdapter;
import org.springframework.social.connect.*;
import org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository;
import org.springframework.social.connect.mem.InMemoryUsersConnectionRepository;
import org.springframework.social.connect.web.ConnectController;
import org.springframework.social.connect.web.ProviderSignInController;
import org.springframework.social.connect.web.ReconnectFilter;
import org.springframework.social.connect.web.SignInAdapter;
import org.springframework.social.facebook.api.Facebook;
import org.springframework.social.facebook.connect.FacebookConnectionFactory;
import org.springframework.social.facebook.web.DisconnectController;
import org.springframework.social.google.api.Google;
import org.springframework.social.google.connect.GoogleConnectionFactory;
import org.springframework.social.security.AuthenticationNameUserIdSource;
import org.springframework.social.security.SocialAuthenticationServiceRegistry;
import org.springframework.social.security.SocialUserDetailsService;
import org.springframework.social.security.SpringSocialConfigurer;
import javax.inject.Inject;
import javax.sql.DataSource;
@Configuration
@EnableSocial
public class SocialConfig extends SocialConfigurerAdapter {
private static final Logger log = LoggerFactory.getLogger(SocialConfig.class);
@Inject
private DataSource dataSource;
@Inject
private Environment env;
@Bean
public SocialUserDetailsService socialUserDetailsService(UserRepository userRepository) {
log.debug("New instance of " + SocialUserDetailsService.class);
return new SimpleSocialUserDetailsService(userRepository);
}
private FacebookConnectionFactory facebookConnectionFactory() {
log.debug("New instance of " + FacebookConnectionFactory.class);
String key = env.getProperty("spring.social.facebook.clientId");
String secret = env.getProperty("spring.social.facebook.clientSecret");
FacebookConnectionFactory result = new FacebookConnectionFactory(key, secret);
result.setScope("public_profile,email");
return result;
}
private GoogleConnectionFactory googleConnectionFactory() {
log.debug("New instance of " + GoogleConnectionFactory.class);
String key = env.getProperty("spring.social.google.clientId");
String secret = env.getProperty("spring.social.google.clientSecret");
GoogleConnectionFactory result = new GoogleConnectionFactory(key, secret);
result.setScope("https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email");
return result;
}
public void addConnectionFactories(ConnectionFactoryConfigurer configurer, Environment environment) {
addConnectionFactories(configurer);
}
private ConnectionFactoryConfigurer addConnectionFactories(ConnectionFactoryConfigurer registry) {
registry.addConnectionFactory(facebookConnectionFactory());
registry.addConnectionFactory(googleConnectionFactory());
return registry;
}
private ConnectionFactoryLocator connectionFactoryLocator() {
log.debug("New instance of " + ConnectionFactoryLocator.class);
SocialAuthenticationServiceRegistry registry = new SocialAuthenticationServiceRegistry();
registry.addConnectionFactory(facebookConnectionFactory());
registry.addConnectionFactory(googleConnectionFactory());
return registry;
}
private static TextEncryptor textEncryptor() {
log.debug("New instance of " + TextEncryptor.class);
return Encryptors.noOpText();
}
@Bean
public UsersConnectionRepository usersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator, ConnectionSignUp connectionSignUp) {
return memoryCR(connectionFactoryLocator, connectionSignUp);
}
@Bean
public ConnectionSignUp connectionSignUp(UserRepository userRepository, UserService userService, MailService mailService) {
log.debug("New instance of " + ConnectionSignUp.class);
return new SocialConnectionSignUp(userRepository, userService, mailService);
}
private UsersConnectionRepository jdbcCR(ConnectionFactoryLocator connectionFactoryLocator, ConnectionSignUp connectionSignUp) {
JdbcUsersConnectionRepository repository = new JdbcUsersConnectionRepository(
dataSource, connectionFactoryLocator, textEncryptor());
repository.setTablePrefix("ac.");
repository.setConnectionSignUp(connectionSignUp);
return repository;
}
private UsersConnectionRepository memoryCR(ConnectionFactoryLocator connectionFactoryLocator, ConnectionSignUp connectionSignUp) {
InMemoryUsersConnectionRepository repository = new InMemoryUsersConnectionRepository(connectionFactoryLocator);
repository.setConnectionSignUp(connectionSignUp);
return repository;
}
@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public ConnectionRepository connectionRepository(UsersConnectionRepository usersConnectionRepository) {
String uuid = SecurityUtils.getUserUuid();
return usersConnectionRepository.createConnectionRepository(uuid);
}
public UserIdSource getUserIdSource() {
log.debug("New instance of " + AuthenticationNameUserIdSource.class);
return new AuthenticationNameUserIdSource();
}
@Bean
public ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator,
ConnectionRepository connectionRepository) {
log.debug("New instance of " + ConnectController.class);
ConnectController controller = new ConnectController(connectionFactoryLocator, connectionRepository);
controller.setApplicationUrl(env.getProperty("app.url"));
return controller;
}
@Bean
public DisconnectController disconnectController(UsersConnectionRepository usersConnectionRepository) {
log.debug("New instance of " + DisconnectController.class);
return new DisconnectController(usersConnectionRepository, env.getProperty("spring.social.facebook.clientSecret"));
}
@Bean
public ReconnectFilter apiExceptionHandler(UsersConnectionRepository usersConnectionRepository, UserIdSource userIdSource) {
log.debug("New instance of " + ReconnectFilter.class);
return new ReconnectFilter(usersConnectionRepository, userIdSource);
}
@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public Facebook facebook(ConnectionRepository repository) {
log.debug("Connection from " + Facebook.class);
Connection<Facebook> connection = repository.findPrimaryConnection(Facebook.class);
return connection != null ? connection.getApi() : null;
}
@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public Google google(ConnectionRepository repository) {
log.debug("Connection from " + Google.class);
Connection<Google> connection = repository.findPrimaryConnection(Google.class);
return connection != null ? connection.getApi() : null;
}
@Bean
public SpringSocialConfigurer springSocialConfigurer() {
log.debug("New instance of " + SpringSocialConfigurer.class);
return new SpringSocialConfigurer()
.postLoginUrl("/#/")
.alwaysUsePostLoginUrl(true);
}
@Bean
public SignInAdapter signInAdapter(SocialUserDetailsService socialUserDetailsService) {
log.debug("New instance of " + ConnectionSignUp.class);
return new SimpleSignInAdapter(socialUserDetailsService);
}
@Bean
public ProviderSignInController providerSignInController(ConnectionFactoryLocator connectionFactoryLocator,
UsersConnectionRepository usersConnectionRepository,
SignInAdapter signInAdapter) {
log.debug("New instance of " + ProviderSignInController.class);
return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, signInAdapter);
}
}