package com.ulisesbocchio.jasyptspringboot.configuration;
import com.ulisesbocchio.jasyptspringboot.EncryptablePropertyDetector;
import com.ulisesbocchio.jasyptspringboot.EncryptablePropertyResolver;
import com.ulisesbocchio.jasyptspringboot.EncryptablePropertySource;
import com.ulisesbocchio.jasyptspringboot.annotation.ConditionalOnMissingBean;
import com.ulisesbocchio.jasyptspringboot.detector.DefaultPropertyDetector;
import com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor;
import com.ulisesbocchio.jasyptspringboot.resolver.DefaultLazyPropertyResolver;
import org.jasypt.encryption.StringEncryptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
/**
* @author Ulises Bocchio
*/
@Configuration
public class EncryptablePropertyResolverConfiguration {
private static final String ENCRYPTOR_BEAN_PLACEHOLDER = "${jasypt.encryptor.bean:jasyptStringEncryptor}";
private static final String DETECTOR_BEAN_PLACEHOLDER = "${jasypt.encryptor.property.detector-bean:encryptablePropertyDetector}";
public static final String RESOLVER_BEAN_PLACEHOLDER = "${jasypt.encryptor.property.resolver-bean:encryptablePropertyResolver}";
private static final Logger LOG = LoggerFactory.getLogger(EncryptablePropertyResolverConfiguration.class);
@Bean
public static BeanNamePlaceholderRegistryPostProcessor beanNamePlaceholderRegistryPostProcessor(ConfigurableEnvironment environment) {
return new BeanNamePlaceholderRegistryPostProcessor(environment);
}
@Bean
public EnvCopy envCopy(ConfigurableEnvironment environment) {
return new EnvCopy(environment);
}
@ConditionalOnMissingBean
@Bean(name = ENCRYPTOR_BEAN_PLACEHOLDER)
public StringEncryptor stringEncryptor(@SuppressWarnings("SpringJavaAutowiringInspection") EnvCopy envCopy) {
String encryptorBeanName = envCopy.get().resolveRequiredPlaceholders(ENCRYPTOR_BEAN_PLACEHOLDER);
LOG.info("String Encryptor custom Bean not found with name '{}'. Initializing String Encryptor based on properties with name '{}'",
encryptorBeanName, encryptorBeanName);
return new DefaultLazyEncryptor(envCopy.get());
}
@ConditionalOnMissingBean
@Bean(name = DETECTOR_BEAN_PLACEHOLDER)
public EncryptablePropertyDetector encryptablePropertyDetector(@SuppressWarnings("SpringJavaAutowiringInspection") EnvCopy envCopy) {
String prefix = envCopy.get().resolveRequiredPlaceholders("${jasypt.encryptor.property.prefix:ENC(}");
String suffix = envCopy.get().resolveRequiredPlaceholders("${jasypt.encryptor.property.suffix:)}");
return new DefaultPropertyDetector(prefix, suffix);
}
@ConditionalOnMissingBean
@Bean(name = RESOLVER_BEAN_PLACEHOLDER)
public EncryptablePropertyResolver encryptablePropertyResolver(BeanFactory bf, @SuppressWarnings("SpringJavaAutowiringInspection") EnvCopy envCopy) {
return new DefaultLazyPropertyResolver(ENCRYPTOR_BEAN_PLACEHOLDER, DETECTOR_BEAN_PLACEHOLDER, bf, envCopy.get());
}
/**
* Need a copy of the environment without the Enhanced property sources to avoid circular dependencies.
*/
private static class EnvCopy {
StandardEnvironment copy;
EnvCopy(ConfigurableEnvironment environment) {
copy = new StandardEnvironment();
environment.getPropertySources().forEach(ps -> {
PropertySource<?> original = ps instanceof EncryptablePropertySource ? ((EncryptablePropertySource)ps).getDelegate() : ps;
copy.getPropertySources().addLast(original);
});
}
ConfigurableEnvironment get() {
return copy;
}
}
}