package ee.esutoniagodesu.security.social; import ee.esutoniagodesu.domain.ac.table.ExternalProvider; import ee.esutoniagodesu.domain.ac.table.User; import ee.esutoniagodesu.domain.ac.table.UserAccountExternal; import ee.esutoniagodesu.repository.domain.ac.UserRepository; import ee.esutoniagodesu.service.MailService; import ee.esutoniagodesu.service.UserService; import ee.esutoniagodesu.util.iso.ISO6391; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.social.ApiException; import org.springframework.social.connect.Connection; import org.springframework.social.connect.ConnectionKey; import org.springframework.social.connect.ConnectionSignUp; import org.springframework.social.connect.UserProfile; import org.springframework.transaction.annotation.Transactional; /** * An implementation of ConnectionSignUp that resolves the User login for a social * Connection by searching for an UserAccountExternal that matches the Connection. */ public class SocialConnectionSignUp implements ConnectionSignUp { private static final Logger log = LoggerFactory.getLogger(SocialConnectionSignUp.class); private final UserRepository userRepository; private final UserService userService; private final MailService mailService; public SocialConnectionSignUp(UserRepository userRepository, UserService userService, MailService mailService) { this.userRepository = userRepository; this.userService = userService; this.mailService = mailService; } private User retreiveSocialAsUser(Connection<?> con) { if (con == null) throw new IllegalStateException("No connection to social api"); // build a new User from the external provider's version of the User UserProfile profile = con.fetchUserProfile(); String firstName = profile.getFirstName(); String lastName = profile.getLastName(); String email = profile.getEmail(); // build the UserAccountExternal from the ConnectionKey String externalAccountProviderName = con.getKey().getProviderId(); ExternalProvider externalProvider = ExternalProvider.caseInsensitiveValueOf(externalAccountProviderName); String externalUserId = con.getKey().getProviderUserId(); // check that we got the information we needed if (StringUtils.isBlank(email)) throw new ApiException(externalAccountProviderName, "provider failed to return email"); User socialUser = new User(firstName, lastName, email, externalProvider, externalUserId); log.debug("Retrieved details from {} for user '{}'", externalAccountProviderName, externalUserId); return socialUser; } /** */ @Transactional @Override public String execute(Connection<?> connection) { ConnectionKey key = connection.getKey(); String providerName = key.getProviderId(); ExternalProvider externalProvider = ExternalProvider.caseInsensitiveValueOf(providerName); String externalId = key.getProviderUserId(); // try to find an internal user by the social ConnectionKey return userRepository.findOneByExternalAccount(externalProvider, externalId) .map(user -> { String uuid = user.getUuid(); log.debug("Returning existing internal User.uuid '{}' for external login '{}' from {}", uuid, externalId, externalProvider); return uuid; }).orElseGet(() -> { log.debug("No internal User found for external login '{}' from {}", externalId, externalProvider); User socialUser = retreiveSocialAsUser(connection); UserAccountExternal socialAccount = socialUser.getAccountExternals().iterator().next(); return userRepository.findOneByEmail(socialUser.getEmail()) .map(user -> { //kasutajal ei tohi olla sama external provideri juures teise id'ga kontot. for (UserAccountExternal p : user.getAccountExternals()) { if (p.getProvider().equals(socialAccount.getProvider())) { throw new IllegalStateException("There is another external login associated with this e-mail"); } } log.debug("Add social login to existing user"); userService.addExternalToUser(user, socialAccount); mailService.sendWelcomeEmail(user); return user.getUuid(); }) .orElseGet(() -> { log.debug("Create new user from social information"); //täiesti uus kasutaja socialUser.setLangKey(ISO6391.et); log.debug("Send socialUser to creation in userService, {}", socialUser); User user = UserService.createUserWithExternal(socialUser, userRepository); try { mailService.sendWelcomeEmail(user); } catch (Exception e) { log.error("sendWelcomeEmail", e); } return user.getUuid(); }); }); } }