diff --git a/app/kac-app/build.gradle b/app/kac-app/build.gradle index c02f8d4..f5f584e 100644 --- a/app/kac-app/build.gradle +++ b/app/kac-app/build.gradle @@ -12,12 +12,12 @@ dependencies { implementation "$boot:spring-boot-starter-web" // security implementation "$boot:spring-boot-starter-security" - implementation "com.auth0:java-jwt:4.4.0" +// implementation "com.auth0:java-jwt:4.4.0" // db runtimeOnly "com.mysql:mysql-connector-j" implementation "org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4:1.16" // jpa - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' implementation "$boot:spring-boot-starter-data-jpa" // querydsl implementation "com.querydsl:querydsl-jpa:5.0.0:jakarta" @@ -36,6 +36,7 @@ dependencies { implementation project(":common-core") implementation project(":common-util") + implementation project(":common-security") implementation project(":web-api-com") // TDOO: 제거... compileOnly project(":data-com") diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/app/KacAppApplication.java b/app/kac-app/src/main/java/kr/co/palnet/kac/app/KacAppApplication.java index 4cf5590..0efa020 100644 --- a/app/kac-app/src/main/java/kr/co/palnet/kac/app/KacAppApplication.java +++ b/app/kac-app/src/main/java/kr/co/palnet/kac/app/KacAppApplication.java @@ -7,7 +7,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication(scanBasePackages = { "kr.co.palnet.kac.app", "kr.co.palnet.kac.data", - "kr.co.palnet.kac.api" + "kr.co.palnet.kac.api", + "kr.co.palnet.kac.config" }) public class KacAppApplication { public static void main(String[] args) { diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/security/AppSecurityConfig.java b/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/security/AppSecurityConfig.java new file mode 100644 index 0000000..05e7594 --- /dev/null +++ b/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/security/AppSecurityConfig.java @@ -0,0 +1,53 @@ +package kr.co.palnet.kac.app.core.security; + +import kr.co.palnet.kac.config.security.SecurityConfig; +import kr.co.palnet.kac.config.security.exception.BaseAccessDeniedHandler; +import kr.co.palnet.kac.config.security.exception.BaseAuthenticationEntryPoint; +import kr.co.palnet.kac.config.security.service.BaseUserDetailsService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; +import org.springframework.security.web.SecurityFilterChain; + + +@Slf4j +@EnableWebSecurity +@Configuration +public class AppSecurityConfig extends SecurityConfig { + + // 시큐리티 적용 안하는 URL 목록 + private final String[] IGNORE_URL = {}; + + private final String[] USER_URL = {}; + + + + public AppSecurityConfig(BaseUserDetailsService baseUserDetailsService, BaseAuthenticationEntryPoint baseAuthenticationEntryPoint, BaseAccessDeniedHandler baseAccessDeniedHandler) { + super(baseUserDetailsService, baseAuthenticationEntryPoint, baseAccessDeniedHandler); + } + + @Override + @Bean + protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + this.setDefaultHttpSecurity(http); + http + .authorizeHttpRequests(authz -> + authz + .requestMatchers(USER_URL).hasRole("USER") + .anyRequest().authenticated() + ) + ; + + return http.build(); + } + + @Bean + public WebSecurityCustomizer appWebSecurityCustomizer() { + return web -> web.ignoring() + .requestMatchers(IGNORE_URL); + } + +} diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrBasRepository.java b/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrBasRepository.java deleted file mode 100644 index e960ce4..0000000 --- a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrBasRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package kr.co.palnet.kac.data.pty.repository; - -import kr.co.palnet.kac.data.pty.model.PtyCstmrBas; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface PtyCstmrBasRepository extends JpaRepository { -} diff --git a/common/core/src/main/java/kr/co/palnet/kac/core/exception/BaseException.java b/common/core/src/main/java/kr/co/palnet/kac/core/exception/BaseException.java index e22c448..d441498 100644 --- a/common/core/src/main/java/kr/co/palnet/kac/core/exception/BaseException.java +++ b/common/core/src/main/java/kr/co/palnet/kac/core/exception/BaseException.java @@ -7,7 +7,6 @@ import org.springframework.context.MessageSource; import java.util.Locale; @Getter -@Slf4j public class BaseException extends RuntimeException { @@ -126,11 +125,6 @@ public class BaseException extends RuntimeException { if (ms == null) { return BaseErrorCode.UNKNOWN.message(); } - log.debug("############ getErrorMessage : {}", ms); - log.debug("############ getErrorCode : {}", getCode()); - log.debug("############ getParamArray : {}", getParamArray()); - log.debug("############ ErrorCode.NOT_REGIST_ERROR_CODE.message() : {}", BaseErrorCode.UNKNOWN.message()); - log.debug("############ Locale.getDefault() : {}", Locale.getDefault()); return ms.getMessage(getCode(), getParamArray(), BaseErrorCode.UNKNOWN.message(), Locale.getDefault()); } diff --git a/common/security/build.gradle b/common/security/build.gradle new file mode 100644 index 0000000..57fca6f --- /dev/null +++ b/common/security/build.gradle @@ -0,0 +1,11 @@ + + +dependencies { + implementation "$boot:spring-boot-starter-web" + implementation "$boot:spring-boot-starter-security" + implementation "com.auth0:java-jwt:4.4.0" + + implementation project(":common-util") + implementation project(":data-pty") +} + diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/SecurityConfig.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/SecurityConfig.java new file mode 100644 index 0000000..6a63345 --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/SecurityConfig.java @@ -0,0 +1,90 @@ +package kr.co.palnet.kac.config.security; + +import kr.co.palnet.kac.config.security.exception.BaseAccessDeniedHandler; +import kr.co.palnet.kac.config.security.exception.BaseAuthenticationEntryPoint; +import kr.co.palnet.kac.config.security.filter.JwtCheckFilter; +import kr.co.palnet.kac.config.security.filter.JwtLoginFilter; +import kr.co.palnet.kac.config.security.service.BaseUserDetailsService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.password.NoOpPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; + + +@RequiredArgsConstructor +public abstract class SecurityConfig { + + private final BaseUserDetailsService baseUserDetailsService; + private final BaseAuthenticationEntryPoint baseAuthenticationEntryPoint; + private final BaseAccessDeniedHandler baseAccessDeniedHandler; + + private final String[] SWAGGER_URI = { + "/swagger-ui/index.html", + "/v3/api-docs", + "/swagger-resources/**", + "/webjars/**", + "/swagger-ui/**" + }; + + + @Bean + PasswordEncoder passwordEncoder() { +// return new BCryptPasswordEncoder(); + // TODO 테스트 후 BCryptPasswordEncoder 로 변경 + return NoOpPasswordEncoder.getInstance(); + } + + @Bean + public AuthenticationManager authenticationManager() { + DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); + authProvider.setUserDetailsService(baseUserDetailsService); + authProvider.setPasswordEncoder(passwordEncoder()); + return new ProviderManager(authProvider); + } + + @Bean + protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + setDefaultHttpSecurity(http); + http + .authorizeHttpRequests(authz -> + authz + .anyRequest().authenticated() + ); + return http.build(); + } + + public void setDefaultHttpSecurity(HttpSecurity http) throws Exception { + http + .csrf(AbstractHttpConfigurer::disable) + .sessionManagement(session -> + session.sessionCreationPolicy(SessionCreationPolicy.STATELESS) + ) + .httpBasic(httpSecurityHttpBasicConfigurer -> httpSecurityHttpBasicConfigurer.authenticationEntryPoint(baseAuthenticationEntryPoint)) + .addFilterAt(new JwtLoginFilter(authenticationManager(), baseUserDetailsService), UsernamePasswordAuthenticationFilter.class) + .addFilterAt(new JwtCheckFilter(authenticationManager(), baseUserDetailsService, baseAuthenticationEntryPoint), BasicAuthenticationFilter.class) + .exceptionHandling(exceptionHandlingconfig -> + exceptionHandlingconfig + .authenticationEntryPoint(baseAuthenticationEntryPoint) + .accessDeniedHandler(baseAccessDeniedHandler) + ); + } + + @Bean + public WebSecurityCustomizer webSecurityCustomizer() { + return web -> web.ignoring() + .requestMatchers(SWAGGER_URI); + } + +} diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/exception/BaseAccessDeniedHandler.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/exception/BaseAccessDeniedHandler.java new file mode 100644 index 0000000..8b9621c --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/exception/BaseAccessDeniedHandler.java @@ -0,0 +1,23 @@ +package kr.co.palnet.kac.config.security.exception; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@RequiredArgsConstructor +@Component +public class BaseAccessDeniedHandler implements AccessDeniedHandler { + + private final BaseAuthenticationExceptionHandler baseAuthenticationExceptionHandler; + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { + baseAuthenticationExceptionHandler.handle(request, response, accessDeniedException); + } +} diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/exception/BaseAuthenticationEntryPoint.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/exception/BaseAuthenticationEntryPoint.java new file mode 100644 index 0000000..a0e3304 --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/exception/BaseAuthenticationEntryPoint.java @@ -0,0 +1,25 @@ +package kr.co.palnet.kac.config.security.exception; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Slf4j +@RequiredArgsConstructor +@Component +public class BaseAuthenticationEntryPoint implements AuthenticationEntryPoint { + + private final BaseAuthenticationExceptionHandler baseAuthenticationExceptionHandler; + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { + baseAuthenticationExceptionHandler.handle(request, response, authException); + } +} diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/exception/BaseAuthenticationException.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/exception/BaseAuthenticationException.java new file mode 100644 index 0000000..b1935fe --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/exception/BaseAuthenticationException.java @@ -0,0 +1,84 @@ +package kr.co.palnet.kac.config.security.exception; + +import kr.co.palnet.kac.config.security.model.BaseAuthErrorCode; +import lombok.Getter; +import org.springframework.security.core.AuthenticationException; + +@Getter +public class BaseAuthenticationException extends AuthenticationException { + private final BaseAuthErrorCode errorCode; + private final Object[] paramArray; + + public BaseAuthenticationException() { + this(null, BaseAuthErrorCode.UNAUTHORIZED, (Object[]) null); + } + + public BaseAuthenticationException(BaseAuthErrorCode errorCode) { + this(null, errorCode, (Object[]) null); + } + + public BaseAuthenticationException(Object[] paramArray) { + this(null, BaseAuthErrorCode.UNAUTHORIZED, paramArray); + } + + public BaseAuthenticationException(BaseAuthErrorCode errorCode, Object[] paramArray) { + this(null, errorCode, paramArray); + } + + public BaseAuthenticationException(String msg) { + this(msg, BaseAuthErrorCode.UNAUTHORIZED, (Object[]) null); + } + + public BaseAuthenticationException(String msg, Object[] paramArray) { + this(msg, BaseAuthErrorCode.UNAUTHORIZED, paramArray); + } + + public BaseAuthenticationException(String msg, BaseAuthErrorCode errorCode) { + this(msg, errorCode, (Object[]) null); + } + + public BaseAuthenticationException(String msg, BaseAuthErrorCode errorCode, Object[] paramArray) { + super(msg); + this.errorCode = errorCode; + this.paramArray = paramArray; + } + + public BaseAuthenticationException(Throwable cause) { + this(null, BaseAuthErrorCode.UNAUTHORIZED, null, cause); + } + + public BaseAuthenticationException(String msg, BaseAuthErrorCode errorCode, Throwable cause) { + this(msg, errorCode, null, cause); + } + + public BaseAuthenticationException(String msg, Throwable cause) { + this(msg, BaseAuthErrorCode.UNAUTHORIZED, null, cause); + } + + public BaseAuthenticationException(Object[] paramArray, Throwable cause) { + this(null, BaseAuthErrorCode.UNAUTHORIZED, paramArray, cause); + } + + public BaseAuthenticationException(String msg, Object[] paramArray, Throwable cause) { + this(msg, BaseAuthErrorCode.UNAUTHORIZED, paramArray, cause); + } + + public BaseAuthenticationException(BaseAuthErrorCode errorCode, Throwable cause) { + this(null, errorCode, null, cause); + } + + public BaseAuthenticationException(BaseAuthErrorCode errorCode, Object[] paramArray, Throwable cause) { + this(null, errorCode, paramArray, cause); + } + + public BaseAuthenticationException(String msg, BaseAuthErrorCode errorCode, Object[] paramArray, Throwable cause) { + super(msg, cause); + this.errorCode = errorCode; + this.paramArray = paramArray; + } + + + public String getCode() { + return errorCode.code(); + } +} diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/exception/BaseAuthenticationExceptionHandler.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/exception/BaseAuthenticationExceptionHandler.java new file mode 100644 index 0000000..b8132f0 --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/exception/BaseAuthenticationExceptionHandler.java @@ -0,0 +1,83 @@ +package kr.co.palnet.kac.config.security.exception; + +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import kr.co.palnet.kac.config.security.model.BaseAuthErrorCode; +import kr.co.palnet.kac.config.security.model.AuthErrorRS; +import kr.co.palnet.kac.util.ObjectMapperUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.support.MessageSourceAccessor; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.core.AuthenticationException; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.time.Instant; + +@Slf4j +@RequiredArgsConstructor +@Component +public class BaseAuthenticationExceptionHandler { + + @Qualifier("authErrorMessageSourceAccessor") + private final MessageSourceAccessor authErrorMessageSourceAccessor; + + public void handle(HttpServletRequest request, HttpServletResponse response, Exception authException) throws IOException, ServletException { + + Object excpetion = request.getAttribute(RequestDispatcher.ERROR_EXCEPTION); + if (excpetion == null) { + excpetion = authException; + } + + String reqURI = (String) request.getAttribute(RequestDispatcher.ERROR_REQUEST_URI); + if (reqURI == null) { + reqURI = request.getRequestURI(); + } + + + BaseAuthErrorCode errorCode = BaseAuthErrorCode.UNAUTHORIZED; + if (excpetion instanceof BaseAuthenticationException) { + log.debug("BaseAuthenticationException : {}", excpetion.getClass()); + BaseAuthenticationException bae = (BaseAuthenticationException) excpetion; + BaseAuthErrorCode baseAuthErrorCode = bae.getErrorCode(); + if (baseAuthErrorCode != null) { + errorCode = baseAuthErrorCode; + } + } + if (excpetion instanceof AuthenticationException) { + log.debug("AuthenticationException : {}", excpetion.getClass()); + errorCode = BaseAuthErrorCode.INVALID_TOKEN; + AuthenticationException ae = (AuthenticationException) excpetion; + // TODO 종류 별로 ErrrorCode 분기 처리 + + + } else if (excpetion instanceof AccessDeniedException) { + log.debug("AccessDeniedException : {}", excpetion.getClass()); + errorCode = BaseAuthErrorCode.UNAUTHORIZED; + AccessDeniedException ad = (AccessDeniedException) excpetion; + // TODO 종류 별로 ErrrorCode 분기 처리 + + + } + + AuthErrorRS rs = AuthErrorRS.builder() + .timestamp(Instant.now().toString()) + .path(reqURI) + .status(errorCode.status().value()) + .error(errorCode.status().getReasonPhrase()) + .code(errorCode.code()) + .message(authErrorMessageSourceAccessor.getMessage(errorCode.code())) + .build(); + + response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + response.getOutputStream().write(ObjectMapperUtils.getObjectMapper().writeValueAsBytes(rs)); + } +} diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/filter/JwtCheckFilter.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/filter/JwtCheckFilter.java new file mode 100644 index 0000000..3e8a27e --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/filter/JwtCheckFilter.java @@ -0,0 +1,75 @@ +package kr.co.palnet.kac.config.security.filter; + +import com.auth0.jwt.exceptions.TokenExpiredException; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import kr.co.palnet.kac.config.security.util.JwtUtil; +import kr.co.palnet.kac.config.security.exception.BaseAuthenticationException; +import kr.co.palnet.kac.config.security.model.BaseAuthErrorCode; +import kr.co.palnet.kac.config.security.model.BaseUserDetails; +import kr.co.palnet.kac.config.security.service.BaseUserDetailsService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; + +import java.io.IOException; + +@Slf4j +public class JwtCheckFilter extends BasicAuthenticationFilter { + + private BaseUserDetailsService baseUserDetailsService; + + public JwtCheckFilter(AuthenticationManager authenticationManager, BaseUserDetailsService baseUserDetailsService) { + super(authenticationManager); + this.baseUserDetailsService = baseUserDetailsService; + } + + public JwtCheckFilter(AuthenticationManager authenticationManager, BaseUserDetailsService baseUserDetailsService, AuthenticationEntryPoint authenticationEntryPoint) { + super(authenticationManager, authenticationEntryPoint); + this.baseUserDetailsService = baseUserDetailsService; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { +// super.doFilterInternal(request, response, chain); + + String bearer = request.getHeader(HttpHeaders.AUTHORIZATION); + if (bearer == null || !bearer.startsWith("Bearer ")) { + chain.doFilter(request, response); + return; + } + + String token = bearer.substring("Bearer ".length()); + + BaseUserDetails userDetails; + try { + userDetails = JwtUtil.verify(token, "AUTH"); + } catch (TokenExpiredException e) { + throw new BaseAuthenticationException(BaseAuthErrorCode.EXPIRED_TOKEN); + } catch (Exception e) { + log.debug(">>> e : {}", e.getClass().getName()); + throw new BaseAuthenticationException(BaseAuthErrorCode.INVALID_TOKEN); + } + + /* + 실시간 처리가 필요할 경우 사용 + access token(auth token)을 짧게 잡고 refresh token으로 재발급시 DB조회 하도록 구성 + UserDetails newUserDetails = baseUserDetailsService.loadUserByUsername(userDetails.getUserId()); + */ + + // 토큰 자체를 신뢰함. + UsernamePasswordAuthenticationToken userToken = new UsernamePasswordAuthenticationToken( + userDetails, null, userDetails.getAuthorities() + ); + + SecurityContextHolder.getContext().setAuthentication(userToken); + + chain.doFilter(request, response); + } +} diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/filter/JwtLoginFilter.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/filter/JwtLoginFilter.java new file mode 100644 index 0000000..7f470bb --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/filter/JwtLoginFilter.java @@ -0,0 +1,66 @@ +package kr.co.palnet.kac.config.security.filter; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import kr.co.palnet.kac.config.security.util.JwtUtil; +import kr.co.palnet.kac.config.security.model.UserLoginForm; +import kr.co.palnet.kac.config.security.exception.BaseAuthenticationException; +import kr.co.palnet.kac.config.security.model.BaseAuthErrorCode; +import kr.co.palnet.kac.config.security.model.BaseUserDetails; +import kr.co.palnet.kac.config.security.service.BaseUserDetailsService; +import kr.co.palnet.kac.util.ObjectMapperUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import java.io.IOException; + +public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter { + private BaseUserDetailsService baseUserDetailsService; + private ObjectMapper objectMapper = ObjectMapperUtils.getObjectMapper(); + + public JwtLoginFilter(BaseUserDetailsService baseUserDetailsService) { + setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/v1/login", "POST")); + } + + public JwtLoginFilter(AuthenticationManager authenticationManager, BaseUserDetailsService baseUserDetailsService) { + super(authenticationManager); + this.baseUserDetailsService = baseUserDetailsService; + setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/v1/login", "POST")); + + } + + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { + try { + UserLoginForm userLogin = objectMapper.readValue(request.getInputStream(), UserLoginForm.class); + + // TODO 로그인 처리 + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( + userLogin.getUserId(), userLogin.getPassword(), null + ); + return getAuthenticationManager().authenticate(token); + + } catch (IOException e) { + throw new BaseAuthenticationException(BaseAuthErrorCode.INVALID_LOGIN); + } + } + + @Override + protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { + BaseUserDetails user = (BaseUserDetails) authResult.getPrincipal(); + response.setHeader("Auth-Token", JwtUtil.makeAuthToken(user)); + response.setHeader("Refresh-Token", JwtUtil.makeRefreshToken(user)); + response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + response.getOutputStream().write(ObjectMapperUtils.getObjectMapper().writeValueAsBytes(user.toMap())); + } +} diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/message/AuthErrorMessageSourceConfig.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/message/AuthErrorMessageSourceConfig.java new file mode 100644 index 0000000..424e5b4 --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/message/AuthErrorMessageSourceConfig.java @@ -0,0 +1,26 @@ +package kr.co.palnet.kac.config.security.message; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.MessageSource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.MessageSourceAccessor; +import org.springframework.context.support.ReloadableResourceBundleMessageSource; + +@Configuration +public class AuthErrorMessageSourceConfig { + + @Bean(name = "authErrorMessageSource") + public MessageSource getAuthErrorMessageSource() { + ReloadableResourceBundleMessageSource authErrorMessageSource = new ReloadableResourceBundleMessageSource(); + authErrorMessageSource.setBasenames("classpath:messages/errors/auth_error"); + authErrorMessageSource.setDefaultEncoding("UTF-8"); + authErrorMessageSource.setCacheSeconds(300); + return authErrorMessageSource; + } + + @Bean(name = "authErrorMessageSourceAccessor") + public MessageSourceAccessor authErrorMessageSourceAccessor(@Qualifier("authErrorMessageSource") MessageSource authErrorMessageSource) { + return new MessageSourceAccessor(authErrorMessageSource); + } +} diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/model/AuthErrorRS.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/model/AuthErrorRS.java new file mode 100644 index 0000000..a306d7a --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/model/AuthErrorRS.java @@ -0,0 +1,19 @@ +package kr.co.palnet.kac.config.security.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AuthErrorRS { + private String timestamp; + private int status; + private String error; + private String path; + private String message; + private String code; +} diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/model/BaseAuthErrorCode.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/model/BaseAuthErrorCode.java new file mode 100644 index 0000000..356c60b --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/model/BaseAuthErrorCode.java @@ -0,0 +1,49 @@ +package kr.co.palnet.kac.config.security.model; + + +import org.springframework.http.HttpStatus; + +public enum BaseAuthErrorCode { + + // 비밀번호를 10회 이상 틀렸습니다. 관리자에게 문의하길 바랍니다. + PASSWORD_OVER_INPUT("AT001", HttpStatus.BAD_REQUEST, "패스워드 입력 제한횟수 초과"), + // 로그인 정보가 올바르지 않습니다. + INVALID_LOGIN("AT002", HttpStatus.BAD_REQUEST, "잘못된 로그인 정보"), + + // TODO 로그인 상태에 따른 에러코드 정의 필요 + + + // 로그인이 필요한 서비스 입니다. + NON_TOKEN("AT100", HttpStatus.UNAUTHORIZED, "토큰 없음"), + // 토큰 정보가 올바르지 않습니다. + INVALID_TOKEN("AT101", HttpStatus.UNAUTHORIZED, "잘못된 토큰"), + // 토큰이 만료되었습니다. + EXPIRED_TOKEN("AT102", HttpStatus.UNAUTHORIZED, "만료된 토큰"), + // 권한이 없습니다. + UNAUTHORIZED("AT103", HttpStatus.UNAUTHORIZED, "권한 없음"); + + + private final String code; + + private final HttpStatus status; + + private final String message; + + private BaseAuthErrorCode(String code, HttpStatus status, String message) { + this.code = code; + this.status = status; + this.message = message; + } + + public String code() { + return this.code; + } + + public String message() { + return this.message; + } + + public HttpStatus status() { + return this.status; + } +} diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/model/BaseUserDetails.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/model/BaseUserDetails.java new file mode 100644 index 0000000..4be6371 --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/model/BaseUserDetails.java @@ -0,0 +1,89 @@ +package kr.co.palnet.kac.config.security.model; + + +import kr.co.palnet.kac.data.pty.model.PtyCstmrBas; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.List; +import java.util.Map; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class BaseUserDetails implements UserDetails { + + // 유저 기본 정보 + // sno + private Long cstmrSno; + // id + private String userId; + // password + private String userPswd; + // authorities(role) - 추후 여러권한을 가질 수 있도록 설계 필요 + private String cstmrDivCd; + // 계정상태 + private String cstmrStatusCd; + + @Override + public List getAuthorities() { + String role = String.format("ROLE_%s", this.cstmrDivCd); + SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role); + return List.of(authority); + } + + @Override + public String getPassword() { + return this.userPswd; + } + + @Override + public String getUsername() { + return this.userId; + } + + @Override + public boolean isAccountNonExpired() { + return !"DORMANT".equals(this.cstmrStatusCd); + } + + @Override + public boolean isAccountNonLocked() { + return !"LOCK".equals(this.cstmrStatusCd); + } + + @Override + public boolean isCredentialsNonExpired() { + return !"PWD_EXPIRED".equals(this.cstmrStatusCd); + } + + @Override + public boolean isEnabled() { + return "ACTIVE".equals(this.cstmrStatusCd); + } + + public static BaseUserDetails toUserDetails(PtyCstmrBas ptyCstmrBas) { + return BaseUserDetails.builder() + .cstmrSno(ptyCstmrBas.getCstmrSno()) + .userId(ptyCstmrBas.getUserId()) + .userPswd(ptyCstmrBas.getUserPswd()) + .cstmrDivCd(ptyCstmrBas.getCstmrDivCd()) + .cstmrStatusCd(ptyCstmrBas.getCstmrStatusCd()) + .build(); + } + + public Map toMap() { + return Map.of( + "cstmrSno", this.cstmrSno, +// "cstmrDivCd", this.cstmrDivCd, +// "cstmrStatusCd", this.cstmrStatusCd + "userId", this.userId + ); + } + +} diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/model/UserLoginForm.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/model/UserLoginForm.java new file mode 100644 index 0000000..7b82b83 --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/model/UserLoginForm.java @@ -0,0 +1,15 @@ +package kr.co.palnet.kac.config.security.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class UserLoginForm { + private String userId; + private String password; +} diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/service/BaseUserDetailsService.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/service/BaseUserDetailsService.java new file mode 100644 index 0000000..b91c857 --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/service/BaseUserDetailsService.java @@ -0,0 +1,28 @@ +package kr.co.palnet.kac.config.security.service; + +import kr.co.palnet.kac.config.security.model.BaseUserDetails; +import kr.co.palnet.kac.data.pty.model.PtyCstmrBas; +import kr.co.palnet.kac.data.pty.service.PtyCstmrDomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class BaseUserDetailsService implements UserDetailsService { + + private final PtyCstmrDomainService ptyCstmrDomainService; + + @Override + public UserDetails loadUserByUsername(String userId) throws UsernameNotFoundException { + PtyCstmrBas cstmrInfoByUserId = ptyCstmrDomainService.getCstmrInfoByUserId(userId); + if(cstmrInfoByUserId == null){ + throw new UsernameNotFoundException("사용자 정보가 없습니다."); + } + BaseUserDetails userDetails = BaseUserDetails.toUserDetails(cstmrInfoByUserId); + return userDetails; + } + +} diff --git a/common/security/src/main/java/kr/co/palnet/kac/config/security/util/JwtUtil.java b/common/security/src/main/java/kr/co/palnet/kac/config/security/util/JwtUtil.java new file mode 100644 index 0000000..c9966b6 --- /dev/null +++ b/common/security/src/main/java/kr/co/palnet/kac/config/security/util/JwtUtil.java @@ -0,0 +1,75 @@ +package kr.co.palnet.kac.config.security.util; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTVerificationException; +import com.auth0.jwt.interfaces.DecodedJWT; +import kr.co.palnet.kac.config.security.model.BaseUserDetails; +import kr.co.palnet.kac.util.KisaEncryptUtil; +import lombok.extern.slf4j.Slf4j; + +import java.time.Instant; + +@Slf4j +public class JwtUtil { + // TODO key는 properties에서 가져올수 있도록 처리 + private static final Algorithm ALGORITHM = Algorithm.HMAC512("pal-networks"); + // 1시간 +// private static final long AUTH_TIME = 60 * 60; + private static final long AUTH_TIME = 10; + // 7일 + private static final long REFRESH_TIME = 60 * 60 * 24 * 7; + + public static String makeAuthToken(BaseUserDetails user) { + String encCstmrSno = KisaEncryptUtil.CbcEncrypt.encrypt(String.valueOf(user.getCstmrSno())); +// List authorities = user.getAuthorities(); +// String authStr = String.join(",", authorities.stream().map(GrantedAuthority::getAuthority).map(str -> str.replaceFirst("ROLE_", "")).toArray(String[]::new)); + String authStr = user.getCstmrDivCd(); + return JWT.create() + .withSubject("AUTH") + .withAudience("kac") + .withIssuer("palnet") + .withIssuedAt(Instant.now()) + .withExpiresAt(Instant.ofEpochMilli(Instant.now().plusSeconds(AUTH_TIME).toEpochMilli())) + .withClaim("userId", user.getUserId()) + .withClaim("sno", encCstmrSno) + .withClaim("role", authStr) + .sign(ALGORITHM); + } + + public static String makeRefreshToken(BaseUserDetails user) { + String encCstmrSno = KisaEncryptUtil.CbcEncrypt.encrypt(String.valueOf(user.getCstmrSno())); +// List authorities = user.getAuthorities(); +// String authStr = String.join(",", authorities.stream().map(GrantedAuthority::getAuthority).map(str -> str.replaceFirst("ROLE_", "")).toArray(String[]::new)); + String authStr = user.getCstmrDivCd(); + return JWT.create() + .withSubject("REFRESH") + .withAudience("kac") + .withIssuer("palnet") + .withIssuedAt(Instant.now()) + .withExpiresAt(Instant.ofEpochMilli(Instant.now().plusSeconds(REFRESH_TIME).toEpochMilli())) + .withClaim("userId", user.getUserId()) + .withClaim("sno", encCstmrSno) + .withClaim("role", authStr) + .sign(ALGORITHM); + } + + + public static BaseUserDetails verify(String token, String type) { + DecodedJWT decodeJwt = JWT.require(ALGORITHM).build().verify(token); + String sub = decodeJwt.getSubject(); + if (!type.equals(sub)) { + throw new JWTVerificationException("Token is not valid - sub(type)"); + } + String decCstmrSno = KisaEncryptUtil.CbcEncrypt.decrypt(decodeJwt.getClaim("sno").asString()); + String decRole = decodeJwt.getClaim("role").asString(); + BaseUserDetails userDetails = BaseUserDetails.builder() + .userId(decodeJwt.getClaim("userId").asString()) + .cstmrSno(Long.parseLong(decCstmrSno)) + .cstmrDivCd(decRole) + .build(); + return userDetails; + } + + +} diff --git a/common/security/src/main/java/lombok.config b/common/security/src/main/java/lombok.config new file mode 100644 index 0000000..eb6db90 --- /dev/null +++ b/common/security/src/main/java/lombok.config @@ -0,0 +1 @@ +lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier \ No newline at end of file diff --git a/common/security/src/main/resources/messages/errors/auth_error.properties b/common/security/src/main/resources/messages/errors/auth_error.properties new file mode 100644 index 0000000..bd9f58f --- /dev/null +++ b/common/security/src/main/resources/messages/errors/auth_error.properties @@ -0,0 +1,6 @@ +AT001=\uBE44\uBC00\uBC88\uD638\uB97C 10\uD68C \uC774\uC0C1 \uD2C0\uB838\uC2B5\uB2C8\uB2E4. \uAD00\uB9AC\uC790\uC5D0\uAC8C \uBB38\uC758\uD558\uAE38 \uBC14\uB78D\uB2C8\uB2E4. +AT002=\uB85C\uADF8\uC778 \uC815\uBCF4\uAC00 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. +AT100=\uB85C\uADF8\uC778\uC774 \uD544\uC694\uD55C \uC11C\uBE44\uC2A4 \uC785\uB2C8\uB2E4. +AT101=\uD1A0\uD070 \uC815\uBCF4\uAC00 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. +AT102=\uD1A0\uD070\uC774 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. +AT103=\uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \ No newline at end of file diff --git a/common/security/src/main/resources/messages/errors/auth_error_en.properties b/common/security/src/main/resources/messages/errors/auth_error_en.properties new file mode 100644 index 0000000..7f7864a --- /dev/null +++ b/common/security/src/main/resources/messages/errors/auth_error_en.properties @@ -0,0 +1,6 @@ +AT001=Password incorrect more than 10 times, please contact your administrator. +AT002=The login information is not valid. +AT100=This service requires login. +AT101=Token information is incorrect. +AT102=Token has expired. +AT103=You do not have permission. \ No newline at end of file diff --git a/common/util/build.gradle b/common/util/build.gradle index 474ef61..31a311a 100644 --- a/common/util/build.gradle +++ b/common/util/build.gradle @@ -1,6 +1,7 @@ dependencies { - implementation 'org.springframework.boot:spring-boot-starter' +// implementation "$boot:spring-boot-starter" + implementation "$boot:spring-boot-starter-json" } diff --git a/common/util/src/main/java/kr/co/palnet/kac/util/ObjectMapperUtils.java b/common/util/src/main/java/kr/co/palnet/kac/util/ObjectMapperUtils.java new file mode 100644 index 0000000..1699bab --- /dev/null +++ b/common/util/src/main/java/kr/co/palnet/kac/util/ObjectMapperUtils.java @@ -0,0 +1,52 @@ +package kr.co.palnet.kac.util; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +import java.time.format.DateTimeFormatter; +import java.util.TimeZone; + +/** + * packageName : com.sumair.common.core.utils + * fileName : ObjectMapperUtils + * author : dhji + * date : 2023-05-17(017) + * description : + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2023-05-17(017) dhji 최초 생성 + */ +public class ObjectMapperUtils { + public static ObjectMapper getObjectMapper() { + return getObjectMapperBuilder().build(); + } + + public static Jackson2ObjectMapperBuilder getObjectMapperBuilder() { + Jackson2ObjectMapperBuilder jacksonBuilder = new Jackson2ObjectMapperBuilder(); + jacksonBuilder.serializationInclusion(JsonInclude.Include.NON_NULL); + jacksonBuilder.serializationInclusion(JsonInclude.Include.NON_EMPTY); +// jacksonBuilder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); +// jacksonBuilder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); +// jacksonBuilder.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); +// jacksonBuilder.featuresToDisable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES); +// jacksonBuilder.modulesToInstall(new JavaTimeModule()); +// jacksonBuilder.timeZone(TimeZone.getTimeZone("UTC")); +// jacksonBuilder.simpleDateFormat("yyyy-MM-dd HH:mm:ss"); +// jacksonBuilder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); +// jacksonBuilder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); +// jacksonBuilder.deserializers(new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); +// jacksonBuilder.deserializers(new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + + return jacksonBuilder; + } +} diff --git a/data/com/build.gradle b/data/com/build.gradle index d19a085..8b8d407 100644 --- a/data/com/build.gradle +++ b/data/com/build.gradle @@ -1,5 +1,4 @@ - dependencies { implementation "$boot:spring-boot-starter-data-jpa" diff --git a/data/pty/build.gradle b/data/pty/build.gradle new file mode 100644 index 0000000..8b8d407 --- /dev/null +++ b/data/pty/build.gradle @@ -0,0 +1,27 @@ + +dependencies { + implementation "$boot:spring-boot-starter-data-jpa" + + implementation "com.querydsl:querydsl-jpa:5.0.0:jakarta" + annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta" + annotationProcessor "jakarta.annotation:jakarta.annotation-api" + annotationProcessor "jakarta.persistence:jakarta.persistence-api" + + + + testRuntimeOnly("com.h2database:h2") +} + +def querydslDir = layout.buildDirectory.dir("generated/querydsl").get().asFile + +sourceSets { + main.java.srcDir(querydslDir) +} + +tasks.withType(JavaCompile) { + options.getGeneratedSourceOutputDirectory().set(file(querydslDir)) +} + +clean { + delete file(querydslDir) +} diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCrtfyhpBas.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCrtfyhpBas.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCrtfyhpBas.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCrtfyhpBas.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrBas.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrBas.java similarity index 91% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrBas.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrBas.java index 56d1d74..52f57b3 100644 --- a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrBas.java +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrBas.java @@ -21,7 +21,7 @@ public class PtyCstmrBas { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "CSTMR_SNO") - private Integer cstmrSno; + private Long cstmrSno; // 권한ID @Column(name = "AUTH_ID") @@ -79,4 +79,7 @@ public class PtyCstmrBas { @Column(name = "TRMNL_ID") private String trmnlId; + @OneToOne(mappedBy = "ptyCstmrBas", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) + private PtyCstmrDtl ptyCstmrDtl; + } \ No newline at end of file diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrConectHist.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrConectHist.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrConectHist.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrConectHist.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrDtl.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrDtl.java similarity index 88% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrDtl.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrDtl.java index 7e1f9a9..01ddd7d 100644 --- a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrDtl.java +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrDtl.java @@ -1,9 +1,6 @@ package kr.co.palnet.kac.data.pty.model; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Table; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -23,7 +20,7 @@ public class PtyCstmrDtl { // 고객일련번호 @Id @Column(name = "CSTMR_SNO") - private int cstmrSno; + private Long cstmrSno; // 아이핀DI @Column(name = "IPIN_DI") @@ -85,5 +82,9 @@ public class PtyCstmrDtl { @Column(name = "UPDATE_USER_ID") private String updateUserId; + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "CSTMR_SNO", insertable = false, updatable = false) + private PtyCstmrBas ptyCstmrBas; + } \ No newline at end of file diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrGroup.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrGroup.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrGroup.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrGroup.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyGroupBas.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyGroupBas.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyGroupBas.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyGroupBas.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtySnsLoginRel.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtySnsLoginRel.java similarity index 97% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtySnsLoginRel.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtySnsLoginRel.java index df86f31..2d593c3 100644 --- a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtySnsLoginRel.java +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtySnsLoginRel.java @@ -9,7 +9,6 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import java.io.Serializable; import java.time.Instant; diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsAgreeTxn.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsAgreeTxn.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsAgreeTxn.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsAgreeTxn.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsBas.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsBas.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsBas.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsBas.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsDtl.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsDtl.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsDtl.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsDtl.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCrtfyhpBasRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCrtfyhpBasRepository.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCrtfyhpBasRepository.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCrtfyhpBasRepository.java diff --git a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrBasRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrBasRepository.java new file mode 100644 index 0000000..f618693 --- /dev/null +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrBasRepository.java @@ -0,0 +1,11 @@ +package kr.co.palnet.kac.data.pty.repository; + +import kr.co.palnet.kac.data.pty.model.PtyCstmrBas; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface PtyCstmrBasRepository extends JpaRepository { + @Query("select b from PtyCstmrBas b inner join b.ptyCstmrDtl where b.userId = :userId") + PtyCstmrBas findByUserId(@Param("userId") String userId); +} diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrConectHistRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrConectHistRepository.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrConectHistRepository.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrConectHistRepository.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrDtlRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrDtlRepository.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrDtlRepository.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrDtlRepository.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrGroupRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrGroupRepository.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrGroupRepository.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrGroupRepository.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyGroupBasRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyGroupBasRepository.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyGroupBasRepository.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyGroupBasRepository.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtySnsLoginRelRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtySnsLoginRelRepository.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtySnsLoginRelRepository.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtySnsLoginRelRepository.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyTermsAgreeTxnRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyTermsAgreeTxnRepository.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyTermsAgreeTxnRepository.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyTermsAgreeTxnRepository.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyTermsBasRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyTermsBasRepository.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyTermsBasRepository.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyTermsBasRepository.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyTermsDtlRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyTermsDtlRepository.java similarity index 100% rename from app/kac-app/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyTermsDtlRepository.java rename to data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyTermsDtlRepository.java diff --git a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyCstmrDomainService.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyCstmrDomainService.java new file mode 100644 index 0000000..47e429b --- /dev/null +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyCstmrDomainService.java @@ -0,0 +1,19 @@ +package kr.co.palnet.kac.data.pty.service; + +import kr.co.palnet.kac.data.pty.model.PtyCstmrBas; +import kr.co.palnet.kac.data.pty.repository.PtyCstmrBasRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@RequiredArgsConstructor +@Service +public class PtyCstmrDomainService { + private final PtyCstmrBasRepository ptyCstmrBasRepository; + + public PtyCstmrBas getCstmrInfoByUserId(String userId) { + return ptyCstmrBasRepository.findByUserId(userId); + } + +} diff --git a/data/user/build.gradle b/data/user/build.gradle deleted file mode 100644 index 6875d3b..0000000 --- a/data/user/build.gradle +++ /dev/null @@ -1,6 +0,0 @@ - - -dependencies { - -} - diff --git a/http-client/http-client.env.json b/http-client/http-client.env.json new file mode 100644 index 0000000..4ecc77e --- /dev/null +++ b/http-client/http-client.env.json @@ -0,0 +1,5 @@ +{ + "local": { + "host": "http://localhost:8080" + } +} \ No newline at end of file diff --git a/http-client/http/auth.http b/http-client/http/auth.http new file mode 100644 index 0000000..d8c7396 --- /dev/null +++ b/http-client/http/auth.http @@ -0,0 +1,19 @@ +### 로그인 +@userId = user +@password = 1234 + +POST {{host}}/v1/login +Authorization: Bearer {{authToken}} // 토큰이 있을 경우 필터에 걸리는지 확인하기 위한 조치 +Content-Type: application/json + +{ + "userId": "{{userId}}", + "password": "{{password}}" +} + +> {% + client.global.set("authToken", response.headers.valueOf("Auth-Token")); +%} + + + diff --git a/http-client/test.http b/http-client/http/code.http similarity index 73% rename from http-client/test.http rename to http-client/http/code.http index 6a41a08..b158a48 100644 --- a/http-client/test.http +++ b/http-client/http/code.http @@ -1,17 +1,20 @@ ### 전체 코드 조회 - 코드그룹-코드-언어 -GET http://localhost:8080/v1/com/code/all + +GET {{host}}/v1/com/code/all ?siteCd=KAC&langDivCd=ko_KR +Authorization: Bearer {{authToken}} ### 그룹 목록 조회 - 코드 그룹만 -GET http://localhost:8080/v1/com/code/group +GET {{host}}/v1/com/code/group +Authorization: Bearer {{authToken}} ### 코드 목록 조회 - 코드 - 언어 -GET http://localhost:8080/v1/com/code/code +GET {{host}}/v1/com/code/code ?groupCd=TEST1&langDivCd=ko_KR ### 코드 그룹 등록 -POST http://localhost:8080/v1/com/code/group +POST {{host}}/v1/com/code/group Content-Type: application/json { @@ -22,7 +25,7 @@ Content-Type: application/json } ### 코드 등록 -POST http://localhost:8080/v1/com/code/code +POST {{host}}/v1/com/code/code Content-Type: application/json { @@ -35,7 +38,7 @@ Content-Type: application/json } ### 언어 등록 -POST http://localhost:8080/v1/com/code/lang +POST {{host}}/v1/com/code/lang Content-Type: application/json { @@ -47,7 +50,7 @@ Content-Type: application/json } ### 코드 그룹 수정 -PUT http://localhost:8080/v1/com/code/group +PUT {{host}}/v1/com/code/group Content-Type: application/json { @@ -58,7 +61,7 @@ Content-Type: application/json } ### 코드 수정 -PUT http://localhost:8080/v1/com/code/code +PUT {{host}}/v1/com/code/code Content-Type: application/json { @@ -71,7 +74,7 @@ Content-Type: application/json } ### 언어 수정 -PUT http://localhost:8080/v1/com/code/lang +PUT {{host}}/v1/com/code/lang Content-Type: application/json { @@ -84,14 +87,14 @@ Content-Type: application/json ### 코드 그룹 삭제 -DELETE http://localhost:8080/v1/com/code/group +DELETE {{host}}/v1/com/code/group ?groupCd=NEW_GROUP001 ### 코드 삭제 -DELETE http://localhost:8080/v1/com/code/code +DELETE {{host}}/v1/com/code/code ?groupCd=NEW_GROUP001&cdId=NEW_CODE001 ### 언어 삭제 -DELETE http://localhost:8080/v1/com/code/lang +DELETE {{host}}/v1/com/code/lang ?groupCd=NEW_GROUP001&cdId=NEW_CODE001&langDivCd=ko_KR diff --git a/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeDTO.java b/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeDTO.java index 781c1a6..a67b059 100644 --- a/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeDTO.java +++ b/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeDTO.java @@ -44,7 +44,7 @@ public class CodeDTO { // 수정일시 private LocalDateTime updateDt; - public static CodeDTO fromEntity(ComCdBas entity) { + public static CodeDTO toDTO(ComCdBas entity) { return CodeDTO.builder() .groupCd(entity.getGroupCd()) .cdId(entity.getCdId()) diff --git a/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeGroupDTO.java b/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeGroupDTO.java index c3ec437..d9f8983 100644 --- a/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeGroupDTO.java +++ b/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeGroupDTO.java @@ -38,7 +38,7 @@ public class CodeGroupDTO { // 수정일시 private LocalDateTime updateDt; - public static CodeGroupDTO fromEntity(ComCdGroupBas entity){ + public static CodeGroupDTO toDTO(ComCdGroupBas entity){ return CodeGroupDTO.builder() .groupCd(entity.getGroupCd()) .siteCd(entity.getSiteCd()) diff --git a/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeGroupRS.java b/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeGroupRS.java index fd83b21..4664261 100644 --- a/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeGroupRS.java +++ b/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeGroupRS.java @@ -21,7 +21,7 @@ public class CodeGroupRS { private List codeList = new ArrayList<>(); // ComCdGroupBas을 받아서 CodeGroupRS로 변환 - public static CodeGroupRS fromEntity(ComCdGroupBas comCdGroupBas) { + public static CodeGroupRS toRS(ComCdGroupBas comCdGroupBas) { return CodeGroupRS.builder() .groupCd(comCdGroupBas.getGroupCd()) .siteCd(comCdGroupBas.getSiteCd()) diff --git a/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeLangDTO.java b/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeLangDTO.java index 22bc72e..1b2768d 100644 --- a/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeLangDTO.java +++ b/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeLangDTO.java @@ -41,7 +41,7 @@ public class CodeLangDTO { // 수정일시 private LocalDateTime updateDt; - public static CodeLangDTO fromEntity(ComCdLangCtg entity) { + public static CodeLangDTO toDTO(ComCdLangCtg entity) { return CodeLangDTO.builder() .groupCd(entity.getGroupCd()) .cdId(entity.getCdId()) diff --git a/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeRS.java b/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeRS.java index c84506f..b779be0 100644 --- a/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeRS.java +++ b/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/model/CodeRS.java @@ -22,7 +22,7 @@ public class CodeRS { private String addInfoValue; private List children = new ArrayList<>(); - public static CodeRS fromEntity(ComCdBas comCdBas) { + public static CodeRS toRS(ComCdBas comCdBas) { return CodeRS.builder() .groupCd(comCdBas.getComCdGroupBas().getGroupCd()) .cdId(comCdBas.getCdId()) diff --git a/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/service/ComCodeService.java b/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/service/ComCodeService.java index 862d732..35eab1d 100644 --- a/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/service/ComCodeService.java +++ b/web/api-com/src/main/java/kr/co/palnet/kac/api/v1/com/code/service/ComCodeService.java @@ -24,13 +24,13 @@ public class ComCodeService { List comCdGroupBasList = comCodeDomainService.getComCdGroupBasList(rq.getSiteCd()); List codeGroupRSList = comCdGroupBasList.stream().map(group -> { - CodeGroupRS codeGroupRS = CodeGroupRS.fromEntity(group); + CodeGroupRS codeGroupRS = CodeGroupRS.toRS(group); List comCdBasList = group.getComCdBasList(); if (comCdBasList != null && !comCdBasList.isEmpty()) { // TODO 계층 구조 필요시 적용 List codeRSList = comCdBasList.stream().map(code -> { - CodeRS codeRS = CodeRS.fromEntity(code); + CodeRS codeRS = CodeRS.toRS(code); if (code.getComCdLangCtgList() != null && !code.getComCdLangCtgList().isEmpty()) { code.getComCdLangCtgList().stream().filter(lang -> lang.getLangDivCd().equals(rq.getLangDivCd()) @@ -50,14 +50,14 @@ public class ComCodeService { // 그룹 목록 조회 - 코드 그룹만 public List getAllGroupCode() { List comCdGroupBasList = comCodeDomainService.getComCdGroupBasList(); - return comCdGroupBasList.stream().map(CodeGroupRS::fromEntity).toList(); + return comCdGroupBasList.stream().map(CodeGroupRS::toRS).toList(); } // 코드 목록 조회 - 코드 - 언어 public List getAllCodeByGroup(SearchCodeRQ rq) { List comCdBasList = comCodeDomainService.getComCdBasList(rq.getGroupCd()); return comCdBasList.stream().map(entity -> { - CodeRS codeRS = CodeRS.fromEntity(entity); + CodeRS codeRS = CodeRS.toRS(entity); if (entity.getComCdLangCtgList() != null && !entity.getComCdLangCtgList().isEmpty()) { entity.getComCdLangCtgList().stream().filter(lang -> lang.getLangDivCd().equals(rq.getLangDivCd()) @@ -71,21 +71,21 @@ public class ComCodeService { public CodeGroupDTO createCodeGroup(FormCodeGroupRQ rq) { ComCdGroupBas entity = rq.toEntity(); ComCdGroupBas comCdGroupBas = comCodeDomainService.createComCdGroupBas(entity); - return CodeGroupDTO.fromEntity(comCdGroupBas); + return CodeGroupDTO.toDTO(comCdGroupBas); } // 코드 등록 public CodeDTO createCode(FormCodeRQ rq) { ComCdBas entity = rq.toEntity(); ComCdBas comCdBas = comCodeDomainService.createComCdBas(entity); - return CodeDTO.fromEntity(comCdBas); + return CodeDTO.toDTO(comCdBas); } // 언어 등록 public CodeLangDTO createCodeLang(FormCodeLangRQ rq) { ComCdLangCtg entity = rq.toEntity(); ComCdLangCtg comCdLangCtg = comCodeDomainService.createComCdLangCtg(entity); - return CodeLangDTO.fromEntity(comCdLangCtg); + return CodeLangDTO.toDTO(comCdLangCtg); } @@ -93,21 +93,21 @@ public class ComCodeService { public CodeGroupDTO updateCodeGroup(FormCodeGroupRQ rq) { ComCdGroupBas entity = rq.toEntity(); ComCdGroupBas comCdGroupBas = comCodeDomainService.updateComCdGroupBas(entity); - return CodeGroupDTO.fromEntity(comCdGroupBas); + return CodeGroupDTO.toDTO(comCdGroupBas); } // 코드 수정 public CodeDTO updateCode(FormCodeRQ rq) { ComCdBas entity = rq.toEntity(); ComCdBas comCdBas = comCodeDomainService.updateComCdBas(entity); - return CodeDTO.fromEntity(comCdBas); + return CodeDTO.toDTO(comCdBas); } // 언어 수정 public CodeLangDTO updateCodeLang(FormCodeLangRQ rq) { ComCdLangCtg entity = rq.toEntity(); ComCdLangCtg comCdLangCtg = comCodeDomainService.updateComCdLangCtg(entity); - return CodeLangDTO.fromEntity(comCdLangCtg); + return CodeLangDTO.toDTO(comCdLangCtg); } // 코드 그룹 삭제