This commit is contained in:
2025-02-12 18:32:21 +09:00
commit aff0f4eeda
767 changed files with 285356 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
package com.caliverse.admin.global.configuration;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.caliverse.admin.domain.dao.admin.AdminMapper;
@Configuration
@RequiredArgsConstructor
public class ApplicationConfig {
private final AdminMapper userMapper;
@Bean
public UserDetailsService userDetailsService(){
return email -> userMapper.findByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
}
@Bean
public AuthenticationProvider authenticationProvider(){
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Lazy
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception{
return config.getAuthenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

View File

@@ -0,0 +1,67 @@
package com.caliverse.admin.global.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.web.cors.CorsConfiguration;
import java.util.List;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class AuthenticationConfig {
private final JwtAuthenticationFilter jwtAuthFilter;
private final AuthenticationProvider authenticationProvider;
private final LogoutHandler logoutHandler;
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.httpBasic().disable()
.csrf().disable() // jwt사용하기 때문에 사용안한다.
.cors(cors -> cors.configurationSource(request -> {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedOrigins(List.of(
"http://localhost:3000",
"http://10.20.20.23:8080",
"http://qa-admintool.caliverse.io:8080",
"http://stage-admintool.caliverse.io:8080",
"http://live-admintool.caliverse.io:8080"
));
corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH"));
corsConfiguration.setAllowedHeaders(List.of("Authorization","Content-Type"));
corsConfiguration.setAllowCredentials(true);
return corsConfiguration;
}))
.authorizeHttpRequests()
.requestMatchers("/api/v1/auth/login","/api/v1/auth/register","/v3/api-docs/**","/swagger-ui/**","swagger-ui.html", "/dev-test/**").permitAll() // login,register은 언제나 가능
.requestMatchers(HttpMethod.POST,"/api/v1/**").authenticated()
.anyRequest()
.authenticated()
.and()
.sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS)) //jwt 사용하는 경우 씀
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(handler -> handler.authenticationEntryPoint(jwtAuthenticationEntryPoint))
.authenticationProvider(authenticationProvider)
.logout()
.logoutUrl("/api/v1/auth/logout")
.addLogoutHandler(logoutHandler)
.logoutSuccessHandler(((request, response, authentication) -> SecurityContextHolder.clearContext()))
.and()
.build();
}
}

View File

@@ -0,0 +1,163 @@
package com.caliverse.admin.global.configuration;
import com.caliverse.admin.domain.batch.CustomProcessor;
import com.caliverse.admin.domain.batch.CustomReader;
import com.caliverse.admin.domain.batch.CustomWriter;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
@Configuration
public class BatchConfiguration {
//public class BatchConfiguration extends DefaultBatchConfiguration {
// @Autowired
// @Qualifier("dataSource")
// private DataSource dataSource;
//
// @Autowired
// @Qualifier("batchTransactionManager")
// private PlatformTransactionManager transactionManger;
//
// @Override
// public DataSource getDataSource() {
// return dataSource;
// }
//
// @Override
// public PlatformTransactionManager getTransactionManager() {
// return transactionManger;
//
// }
//
//
// @Bean
// public Job createJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
// return new JobBuilder("testJob", jobRepository)
// .flow(createStep(jobRepository, transactionManager)).end().build();
// }
//
// @Bean
// Step createStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
// return new StepBuilder("testStep", jobRepository)
// .<String, String> chunk(3, transactionManager)
// .allowStartIfComplete(true)
// .reader(new CustomReader())
// .processor(new CustomProcessor())
// .writer(new CustomWriter())
// .build();
// }
// @Bean
// public org.springframework.batch.core.Job testJob(JobRepository jobRepository,PlatformTransactionManager transactionManager) throws DuplicateJobException {
// org.springframework.batch.core.Job job = new JobBuilder("testJob",jobRepository)
// .start(testStep(jobRepository,transactionManager))
// .build();
// return job;
// }
// public Step testStep(JobRepository jobRepository,PlatformTransactionManager transactionManager){
// Step step = new StepBuilder("testStep",jobRepository)
// .tasklet(testTasklet(),transactionManager)
// .build();
// return step;
// }
// public Tasklet testTasklet(){
// return ((contribution, chunkContext) -> {
// System.out.println("***** hello batch! *****");
// // 원하는 비지니스 로직 작성
// return RepeatStatus.FINISHED;
// });
// }
// @Bean
// public JobRepository jobRepository() {
// JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
// factory.setDataSource(dataSource);
// factory.setTransactionManager(transactionManager);
// try {
// return factory.getObject();
// } catch (Exception e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// return null;
// }
// @Bean
// public JobLauncher jobLauncher() {
// TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
// jobLauncher.setJobRepository(jobRepository());
// jobLauncher.setTaskExecutor(new SyncTaskExecutor()); // Optional: You can use a different TaskExecutor
// return jobLauncher;
// }
// @Bean
// public JobLauncher jobLauncher() {
// JobLauncherFactoryBean factory = new JobLauncherFactoryBean();
// factory.setJobRepository(jobRepository());
// return factory.getObject();
// }
// tag::readerwriterprocessor[]
// @Bean
// public FlatFileItemReader<Person> reader() {
// return new FlatFileItemReaderBuilder<Person>()
// .name("personItemReader")
// .resource(new ClassPathResource("sample-data.csv"))
// .delimited()
// .names("firstName", "lastName")
// .targetType(Person.class)
// .build();
// }
// @Bean
// public PersonItemProcessor processor() {
// return new PersonItemProcessor();
// }
// @Bean
// public JdbcBatchItemWriter<Person> writer(DataSource dataSource) {
// return new JdbcBatchItemWriterBuilder<Person>()
// .sql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)")
// .dataSource(dataSource)
// .beanMapped()
// .build();
// }
// // end::readerwriterprocessor[]
// // tag::jobstep[]
// @Bean
// public Job importUserJob(JobRepository jobRepository,Step step1, JobCompletionNotificationListener listener) {
// return new JobBuilder("importUserJob", jobRepository)
// .listener(listener)
// .start(step1)
// .build();
// }
// @Bean
// public Step step1(JobRepository jobRepository, DataSourceTransactionManager transactionManager,
// FlatFileItemReader<Person> reader, PersonItemProcessor processor, JdbcBatchItemWriter<Person> writer) {
// return new StepBuilder("step1", jobRepository)
// .<Person, Person> chunk(3, transactionManager)
// .reader(reader)
// .processor(processor)
// .writer(writer)
// .build();
// end::jobstep[]
}

View File

@@ -0,0 +1,61 @@
package com.caliverse.admin.global.configuration;
import com.caliverse.admin.domain.entity.CLOTHSMALLTYPE;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.auth.credentials.*;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatch.CloudWatchClient;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
@Configuration
public class DynamoDBConfig {
@Value("${amazon.dynamodb.endpoint}")
private String amazonDynamoDBEndpoint;
@Value("${amazon.aws.accesskey}")
private String amazonAWSAccessKey;
@Value("${amazon.aws.secretkey}")
private String amazonAWSSecretKey;
@Value("${amazon.aws.region}")
private String amazonAWSRegion;
@Bean
public DynamoDbClient dynamoDbClient() {
var builder = DynamoDbClient.builder()
.region(Region.US_WEST_2)
.credentialsProvider(awsCredentialsProvider());
if (amazonDynamoDBEndpoint != null && !amazonDynamoDBEndpoint.isEmpty()) {
builder.endpointOverride(java.net.URI.create(amazonDynamoDBEndpoint));
}
return builder.build();
}
@Bean
public AwsCredentialsProvider awsCredentialsProvider() {
if (amazonAWSAccessKey == null || amazonAWSAccessKey.isEmpty() ||amazonAWSSecretKey == null || amazonAWSSecretKey.isEmpty()) {
return StaticCredentialsProvider.create(AwsBasicCredentials.create("fakeAccesskey", "fakeSecretKey"));
}
return StaticCredentialsProvider.create(AwsBasicCredentials.create(amazonAWSAccessKey, amazonAWSSecretKey));
}
@Bean
public CloudWatchClient cloudWatchClient() {
return CloudWatchClient.builder()
.region(Region.US_WEST_2)
.credentialsProvider(awsCredentialsProvider())
.build();
}
@Bean
public DynamoDbEnhancedClient dynamoDbEnhancedClient(DynamoDbClient dynamoDbClient) {
return DynamoDbEnhancedClient.builder()
.dynamoDbClient(dynamoDbClient)
.build();
}
}

View File

@@ -0,0 +1,24 @@
package com.caliverse.admin.global.configuration;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
private final HandlerExceptionResolver resolver;
public JwtAuthenticationEntryPoint(@Qualifier("handlerExceptionResolver") HandlerExceptionResolver resolver) {
this.resolver = resolver;
}
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) {
resolver.resolveException(request, response, null, authException);
}
}

View File

@@ -0,0 +1,78 @@
package com.caliverse.admin.global.configuration;
import java.io.IOException;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import com.caliverse.admin.domain.dao.admin.TokenMapper;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
private final TokenMapper tokenMapper;
@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain
) throws ServletException, IOException {
if (request.getServletPath().contains("/api/v1/auth") || request.getServletPath().contains("/api-docs") || request.getServletPath().contains("/swagger-ui") || request.getServletPath().equals("/favicon.ico")) {
filterChain.doFilter(request, response);
return;
}
final String authHeader = request.getHeader("Authorization");
if (authHeader == null ||!authHeader.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
final String jwt = authHeader.substring(7);
String userEmail = null;
try{
userEmail = jwtService.extractUseremail(jwt);
} catch (Exception e){
request.setAttribute("exception", e);
}
if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(userEmail);
var isTokenValid = tokenMapper.findByToken(jwt)
.map(t -> !t.isExpired() && !t.isRevoked())
.orElse(false);
if (jwtService.isTokenValid(jwt, userDetails) && isTokenValid) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);
authToken.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request)
);
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
}

View File

@@ -0,0 +1,113 @@
package com.caliverse.admin.global.configuration;
import com.caliverse.admin.global.common.code.ErrorCode;
import com.caliverse.admin.global.common.exception.RestApiException;
import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
@Service
public class JwtService {
@Value("${spring.jwt.secret_key}")
private String secretKey;
@Value("${spring.jwt.expiration}")
private long jwtExpiration;
@Value("${spring.jwt.refresh-token.expiration}")
private long refreshExpiration;
public String extractUseremail(String token) {
return extractClaim(token, Claims::getSubject);
}
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver){
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}
public String generateToken(UserDetails userDetails){
return generateToken(new HashMap<>(), userDetails);
}
public String generateToken(
Map<String, Object> extraClaims,
UserDetails userDetails
){
return buildToken(extraClaims, userDetails, jwtExpiration);
}
public String generateRefreshToken(
UserDetails userDetails
){
return buildToken(new HashMap<>(), userDetails, refreshExpiration);
}
private String buildToken(
Map<String, Object> extraClaims,
UserDetails userDetails,
long expiration
){
return Jwts
.builder()
.setClaims(extraClaims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + expiration))
.signWith(getSignInKey(), SignatureAlgorithm.HS256)
.compact();
}
public Boolean isTokenValid(String token, UserDetails userDetails){
final String username = extractUseremail(token);
return (username.equals(userDetails.getUsername())) && !isTokenExpired(token);
}
public Boolean isTokenExpired(String token){
return extractExpiration(token).before(new Date());
}
private Date extractExpiration(String token) {
return extractClaim(token, Claims::getExpiration);
}
private Claims extractAllClaims(String token){
try{
return Jwts
.parserBuilder()
.setSigningKey(getSignInKey())
.build()
.parseClaimsJws(token)
.getBody();
}catch (SecurityException | MalformedJwtException e){
throw new RestApiException(-1 , ErrorCode.WRONG_TYPE_TOKEN.getMessage());
} catch (ExpiredJwtException e) {
throw new RestApiException(-1 , ErrorCode.EXPIRED_TOKEN.getMessage());
} catch (UnsupportedJwtException e) {
throw new RestApiException(-1 , ErrorCode.UNSUPPORTED_TOKEN.getMessage());
} catch (IllegalArgumentException e) {
throw new RestApiException(-1 , ErrorCode.WRONG_TOKEN.getMessage());
} catch (SignatureException e){
throw new RestApiException(-1 , ErrorCode.SIGNATURE_ERROR.getMessage());
} catch (Exception e){
throw new RestApiException(-1 , ErrorCode.AUTHENTICATION_FAILED.getMessage());
}
}
private Key getSignInKey() {
byte[] keyBytes = Decoders.BASE64.decode(secretKey);
return Keys.hmacShaKeyFor(keyBytes);
}
}

View File

@@ -0,0 +1,51 @@
package com.caliverse.admin.global.configuration;
import com.caliverse.admin.history.repository.MongoAdminRepository;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@Configuration
@EnableMongoRepositories(basePackages = "com.caliverse.admin.history.repository", mongoTemplateRef = "mongoAdminTemplate")
public class MongoAdminConfig {
@Value("${mongodb.host}")
String businessLogHost;
@Value("${mongodb.admin.username}")
String username;
@Value("${mongodb.admin.password}")
String password;
@Value("${mongodb.admin.db}")
String db;
@Bean(name = "mongoAdminClient")
public MongoClient mongoStatClient() {
String encodePassword = URLEncoder.encode(password, StandardCharsets.UTF_8);
String auth = username.isEmpty() ? "" : String.format("%s:%s@",username, encodePassword);
String connection = String.format("mongodb://%s%s/?authSource=%s", auth, businessLogHost, db);
return MongoClients.create(connection);
}
@Bean(name = "mongoAdminFactory")
public MongoDatabaseFactory mongoIndicatorFactory(@Qualifier("mongoAdminClient") MongoClient mongoIndicatorClient) {
return new SimpleMongoClientDatabaseFactory(mongoIndicatorClient, db);
}
@Bean(name = "mongoAdminTemplate")
public MongoTemplate mongoIndicatorTemplate(@Qualifier("mongoAdminFactory") MongoDatabaseFactory mongoIndicatorFactory) {
return new MongoTemplate(mongoIndicatorFactory);
}
}

View File

@@ -0,0 +1,53 @@
package com.caliverse.admin.global.configuration;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import com.caliverse.admin.logs.logrepository.mongobusinesslogrepository.MongoBusinessLogRepository;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@Configuration
@EnableMongoRepositories(basePackageClasses = MongoBusinessLogRepository.class, mongoTemplateRef = "mongoBusinessLogTemplate")
public class MongoBusinessLogConfig {
@Value("${mongodb.host}")
String businessLogHost;
@Value("${mongodb.business-log.username}")
String username;
@Value("${mongodb.business-log.password}")
String password;
@Value("${mongodb.business-log.db}")
String businessLogdb;
@Bean(name = "mongoBusinessLogClient")
public MongoClient mongoBusinessLogClient() {
String encodePassword = URLEncoder.encode(password, StandardCharsets.UTF_8);
String auth = username.isEmpty() ? "" : String.format("%s:%s@",username, encodePassword);
String connection = String.format("mongodb://%s%s/?authSource=%s", auth, businessLogHost, businessLogdb);
return MongoClients.create(connection);
}
@Bean(name = "mongoBusinessLogFactory")
public MongoDatabaseFactory mongoBusinessLogFactory(@Qualifier("mongoBusinessLogClient") MongoClient mongoClient) {
return new SimpleMongoClientDatabaseFactory(mongoClient, businessLogdb);
}
@Bean(name = "mongoBusinessLogTemplate")
public MongoTemplate mongoBusinessLogTemplate(@Qualifier("mongoBusinessLogFactory") MongoDatabaseFactory mongoFactory) {
return new MongoTemplate(mongoFactory);
}
}

View File

@@ -0,0 +1,53 @@
package com.caliverse.admin.global.configuration;
import com.caliverse.admin.Indicators.indicatorrepository.MongoIndicatorRepository;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@Configuration
@EnableMongoRepositories(basePackageClasses = MongoIndicatorRepository.class, mongoTemplateRef = "mongoIndicatorTemplate")
public class MongoIndicatorConfig {
// @Value("${mongodb.indicator.uri}")
// String uri;
@Value("${mongodb.host}")
String businessLogHost;
@Value("${mongodb.indicator.username}")
String username;
@Value("${mongodb.indicator.password}")
String password;
@Value("${mongodb.indicator.db}")
String db;
@Bean(name = "mongoIndicatorClient")
public MongoClient mongoStatClient() {
String encodePassword = URLEncoder.encode(password, StandardCharsets.UTF_8);
String auth = username.isEmpty() ? "" : String.format("%s:%s@",username, encodePassword);
String connection = String.format("mongodb://%s%s/?authSource=%s", auth, businessLogHost, db);
return MongoClients.create(connection);
}
@Bean(name = "mongoIndicatorFactory")
public MongoDatabaseFactory mongoIndicatorFactory(@Qualifier("mongoIndicatorClient") MongoClient mongoIndicatorClient) {
return new SimpleMongoClientDatabaseFactory(mongoIndicatorClient, db);
}
@Bean(name = "mongoIndicatorTemplate")
public MongoTemplate mongoIndicatorTemplate(@Qualifier("mongoIndicatorFactory") MongoDatabaseFactory mongoIndicatorFactory) {
return new MongoTemplate(mongoIndicatorFactory);
}
}

View File

@@ -0,0 +1,52 @@
package com.caliverse.admin.global.configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
@MapperScan(value = "com.caliverse.admin.domain.dao.admin", sqlSessionFactoryRef = "SqlSessionFactory")
@EnableTransactionManagement
public class MybatisConfig {
@Value("${spring.mybatis.mapper-locations}")
String mPath;
@Bean(name = "dataSource")
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource DataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "SqlSessionFactory")
public SqlSessionFactory SqlSessionFactory(@Qualifier("dataSource") DataSource DataSource, ApplicationContext applicationContext) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(DataSource);
sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources(mPath));
return sqlSessionFactoryBean.getObject();
}
@Bean(name = "SessionTemplate")
public SqlSessionTemplate SqlSessionTemplate(@Qualifier("SqlSessionFactory") SqlSessionFactory firstSqlSessionFactory) {
return new SqlSessionTemplate(firstSqlSessionFactory);
}
@Bean(name = "transactionManager")
public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}

View File

@@ -0,0 +1,22 @@
package com.caliverse.admin.global.configuration;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.text.SimpleDateFormat;
@Configuration
public class ObjectMapperConfig {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper()
.registerModule(new JavaTimeModule())
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
}
}

View File

@@ -0,0 +1,69 @@
package com.caliverse.admin.global.configuration;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.SslContextFactory;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.IOException;
import java.security.*;
import java.util.concurrent.TimeoutException;
@Slf4j
@Configuration
public class RabbitMqConfig
{
@Value("${rabbitmq.url}")
String m_rabbitmq_host;
@Value("${rabbitmq.port}")
int m_rabbitmq_port;
@Value("${rabbitmq.username}")
String m_rabbitmq_username;
@Value("${rabbitmq.password}")
String m_rabbitmq_password;
@Value("${rabbitmq.ssl}")
boolean m_rabbitmq_ssl;
@Bean
public Connection rabbitMqClient() throws IOException, TimeoutException, NoSuchAlgorithmException, KeyManagementException {
var factory = new ConnectionFactory();
setConnectionInfo(factory);
if(m_rabbitmq_ssl)
{
// SSLContext 초기화
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
// 기본 TrustManager 로드
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
try{
tmf.init((KeyStore) null); // 기본 Trust Store로 초기화
}
catch(KeyStoreException e){
log.error(e.getMessage());
return null;
}
// SSLContext를 기본 TrustManager와 SecureRandom으로 초기화
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
// SSLContext를 사용하도록 ConnectionFactory 설정
factory.useSslProtocol(sslContext);
}
return factory.newConnection();
}
private void setConnectionInfo(ConnectionFactory factory){
factory.setHost(m_rabbitmq_host);
factory.setPort(m_rabbitmq_port);
factory.setUsername(m_rabbitmq_username);
factory.setPassword(m_rabbitmq_password);
factory.setAutomaticRecoveryEnabled(true);
factory.setRequestedHeartbeat(60);
}
}

View File

@@ -0,0 +1,133 @@
package com.caliverse.admin.global.configuration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
import java.time.Duration;
@Slf4j
@Configuration
public class RedisConfig {
@Value("${redis.host}")
private String host;
@Value("${redis.port}")
private int port;
@Value("${redis.password}")
private String password;
@Value("${redis.async-timeout}")
private int asyncTimeout;
@Value("${redis.sync-timeout}")
private int syncTimeout;
@Value("${redis.ssl}")
private boolean ssl;
@Value("${redis.abort-connect}")
private boolean abortConnect;
@Value("${spring.profiles.active}")
private String activeProfile;
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
// String activeProfile = System.getProperty("active.profile", "local");
log.info("RedisConfig Active profile: {}", activeProfile);
if(activeProfile.equals("local") || activeProfile.equals("dev")){
log.info("RedisConfig local config Set");
/// Redis Standalone 설정
RedisStandaloneConfiguration standaloneConfig = new RedisStandaloneConfiguration();
standaloneConfig.setHostName(host);
standaloneConfig.setPort(port);
if (password != null && !password.isEmpty()) {
standaloneConfig.setPassword(password);
}
JedisClientConfiguration.JedisClientConfigurationBuilder jedisClientConfig = JedisClientConfiguration.builder();
jedisClientConfig.connectTimeout(java.time.Duration.ofMillis(asyncTimeout)); // AsyncTimeout
jedisClientConfig.readTimeout(java.time.Duration.ofMillis(syncTimeout)); // SyncTimeout
if (ssl) {
jedisClientConfig.useSsl();
}
//if (!abortConnect) { jedisClientConfig.blockOnReconnect(false);}
return new JedisConnectionFactory(standaloneConfig, jedisClientConfig.build());
}
log.info("RedisConfig deploy config Set");
//cluster로 변경 수정
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(128); // 연결 풀 설정
// Redis 클러스터 진입점 노드만 지정
RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration();
clusterConfig.clusterNode(host, port);
clusterConfig.setPassword(password); // 패스워드 설정
clusterConfig.setMaxRedirects(5);
var builder = JedisClientConfiguration.builder();
builder.usePooling().poolConfig(poolConfig);
if(ssl){
builder.useSsl();
}
JedisClientConfiguration clientConfig = builder.build();
JedisConnectionFactory factory = new JedisConnectionFactory(clusterConfig, clientConfig);
factory.afterPropertiesSet();
try {
factory.getConnection().ping(); // Redis 서버에 Ping 명령어를 전송해 응답을 확인
log.info("Successfully connected to Redis server: {}", factory.getHostName());
} catch (Exception e) {
log.error("Failed to connect to Redis server: {}", e.getMessage());
}
return factory;
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(jedisConnectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new StringRedisSerializer());
try {
template.getConnectionFactory().getConnection().ping();
log.info("redisTemplate Successfully connected to Redis server");
} catch (Exception e) {
log.error("redisTemplate Failed to connect to Redis server: {}", e.getMessage());
}
return template;
}
@Bean
public RedisCacheManager cacheManager(JedisConnectionFactory jedisConnectionFactory) {
RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(60)) // 캐시 TTL 설정
.disableCachingNullValues(); // null 값 캐싱 금지
return RedisCacheManager.builder(jedisConnectionFactory)
.cacheDefaults(cacheConfig)
.build();
}
}

View File

@@ -0,0 +1,72 @@
package com.caliverse.admin.global.configuration;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.web.client.RestTemplate;
import java.util.Collections;
@Configuration
@RequiredArgsConstructor
@Getter
@Setter
public class RestConfig {
@Value("${web3.timeout}")
private int timeout;
@Value("${web3.url}")
private String url;
@Value("${web3.delay}")
private long delay;
@Value("${web3.max-retry}")
private int maxRetry;
private final ObjectMapper objectMapper;
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
// Timeout 설정
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(timeout);
factory.setConnectionRequestTimeout(timeout);
restTemplate.setRequestFactory(factory);
// MessageConverter 설정
MappingJackson2HttpMessageConverter converter =
new MappingJackson2HttpMessageConverter(objectMapper);
restTemplate.setMessageConverters(Collections.singletonList(converter));
return restTemplate;
}
@Bean
public RetryTemplate retryTemplate() {
RetryTemplate retryTemplate = new RetryTemplate();
//retry 2초간격 3회
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
backOffPolicy.setBackOffPeriod(delay);
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(maxRetry);
retryTemplate.setBackOffPolicy(backOffPolicy);
retryTemplate.setRetryPolicy(retryPolicy);
return retryTemplate;
}
}

View File

@@ -0,0 +1,35 @@
package com.caliverse.admin.global.configuration;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
@Configuration
@RequiredArgsConstructor
public class S3Config {
@Value("${amazon.aws.accesskey}")
private String accessKey;
@Value("${amazon.aws.secretkey}")
private String secretKey;
@Value("${amazon.aws.region}")
private String region;
@Bean
@ConditionalOnProperty(name = "amazon.s3.enabled", havingValue = "true")
public S3Client s3Client() {
AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKey, secretKey);
return S3Client.builder()
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.region(Region.of(region))
.build();
}
}

View File

@@ -0,0 +1,25 @@
package com.caliverse.admin.global.configuration;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.components(new Components())
.info(apiInfo());
}
private Info apiInfo() {
return new Info()
.title("칼리버스 API 명세서")
.description("칼리버스 어드민 툴 스웨거 ")
.version("v1");
}
}

View File

@@ -0,0 +1,162 @@
package com.caliverse.admin.global.configuration;
import javax.sql.DataSource;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import com.caliverse.admin.domain.batch.CustomProcessor;
import com.caliverse.admin.domain.batch.CustomReader;
import com.caliverse.admin.domain.batch.CustomWriter;
@Configuration
//public class TestBatchConfiguration extends DefaultBatchConfiguration {
public class TestBatchConfiguration {
// @Autowired
// @Qualifier("dataSource-normal")
// private DataSource dataSource;
//
// @Autowired
// @Qualifier("batchTransactionManager")
// private PlatformTransactionManager transactionManger;
//
// @Override
// public DataSource getDataSource() {
// return dataSource;
// }
//
// @Override
// public PlatformTransactionManager getTransactionManager() {
// return transactionManger;
//
// }
//
//
// @Bean
// public Job createJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
// return new JobBuilder("testJob", jobRepository)
// .flow(createStep(jobRepository, transactionManager)).end().build();
// }
//
// @Bean
// Step createStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
// return new StepBuilder("testStep", jobRepository)
// .<String, String> chunk(3, transactionManager)
// .allowStartIfComplete(true)
// .reader(new CustomReader())
// .processor(new CustomProcessor())
// .writer(new CustomWriter())
// .build();
// }
// @Bean
// public org.springframework.batch.core.Job testJob(JobRepository jobRepository,PlatformTransactionManager transactionManager) throws DuplicateJobException {
// org.springframework.batch.core.Job job = new JobBuilder("testJob",jobRepository)
// .start(testStep(jobRepository,transactionManager))
// .build();
// return job;
// }
// public Step testStep(JobRepository jobRepository,PlatformTransactionManager transactionManager){
// Step step = new StepBuilder("testStep",jobRepository)
// .tasklet(testTasklet(),transactionManager)
// .build();
// return step;
// }
// public Tasklet testTasklet(){
// return ((contribution, chunkContext) -> {
// System.out.println("***** hello batch! *****");
// // 원하는 비지니스 로직 작성
// return RepeatStatus.FINISHED;
// });
// }
// @Bean
// public JobRepository jobRepository() {
// JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
// factory.setDataSource(dataSource);
// factory.setTransactionManager(transactionManager);
// try {
// return factory.getObject();
// } catch (Exception e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// return null;
// }
// @Bean
// public JobLauncher jobLauncher() {
// TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
// jobLauncher.setJobRepository(jobRepository());
// jobLauncher.setTaskExecutor(new SyncTaskExecutor()); // Optional: You can use a different TaskExecutor
// return jobLauncher;
// }
// @Bean
// public JobLauncher jobLauncher() {
// JobLauncherFactoryBean factory = new JobLauncherFactoryBean();
// factory.setJobRepository(jobRepository());
// return factory.getObject();
// }
// tag::readerwriterprocessor[]
// @Bean
// public FlatFileItemReader<Person> reader() {
// return new FlatFileItemReaderBuilder<Person>()
// .name("personItemReader")
// .resource(new ClassPathResource("sample-data.csv"))
// .delimited()
// .names("firstName", "lastName")
// .targetType(Person.class)
// .build();
// }
// @Bean
// public PersonItemProcessor processor() {
// return new PersonItemProcessor();
// }
// @Bean
// public JdbcBatchItemWriter<Person> writer(DataSource dataSource) {
// return new JdbcBatchItemWriterBuilder<Person>()
// .sql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)")
// .dataSource(dataSource)
// .beanMapped()
// .build();
// }
// // end::readerwriterprocessor[]
// // tag::jobstep[]
// @Bean
// public Job importUserJob(JobRepository jobRepository,Step step1, JobCompletionNotificationListener listener) {
// return new JobBuilder("importUserJob", jobRepository)
// .listener(listener)
// .start(step1)
// .build();
// }
// @Bean
// public Step step1(JobRepository jobRepository, DataSourceTransactionManager transactionManager,
// FlatFileItemReader<Person> reader, PersonItemProcessor processor, JdbcBatchItemWriter<Person> writer) {
// return new StepBuilder("step1", jobRepository)
// .<Person, Person> chunk(3, transactionManager)
// .reader(reader)
// .processor(processor)
// .writer(writer)
// .build();
// end::jobstep[]
}

View File

@@ -0,0 +1,49 @@
package com.caliverse.admin.global.configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
@MapperScan(value = "com.caliverse.admin.domain.dao.total", sqlSessionFactoryRef = "TotalSqlSessionFactory")
@EnableTransactionManagement
public class TotalMybatisConfig{
@Value("${spring.mybatis.mapper-locations}")
String mPath;
@Bean(name = "totalDataSource")
@ConfigurationProperties(prefix = "spring.total-datasource")
public DataSource DataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "TotalSqlSessionFactory")
public SqlSessionFactory TotalSqlSessionFactory(@Qualifier("totalDataSource") DataSource DataSource, ApplicationContext applicationContext) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(DataSource);
sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources(mPath));
return sqlSessionFactoryBean.getObject();
}
@Bean(name = "TotalSessionTemplate")
public SqlSessionTemplate SqlSessionTemplate(@Qualifier("TotalSqlSessionFactory") SqlSessionFactory firstSqlSessionFactory) {
return new SqlSessionTemplate(firstSqlSessionFactory);
}
@Bean(name = "totalTransactionManager")
public DataSourceTransactionManager totalTransactionManager(@Qualifier("totalDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}