From fd50dd78a00fe8a761bf369ed986c33e238e9d1a Mon Sep 17 00:00:00 2001 From: jooho Date: Tue, 26 Oct 2021 09:37:45 +0900 Subject: [PATCH] update --- .../api/posts/dto/PostsSimpleResponseDto.java | 12 +- .../domain/board/BoardRepositoryImpl.java | 24 ++- .../domain/posts/PostsRepositoryImpl.java | 42 ++--- .../service/posts/PostsService.java | 25 +-- .../api/board/BoardApiControllerTest.java | 15 +- .../src/main/resources/application.yml | 2 + .../api/PortalApiController.java | 13 +- .../api/banner/BannerApiController.java | 25 +-- .../api/banner/dto/BannerListResponseDto.java | 9 +- .../api/banner/dto/BannerSaveRequestDto.java | 5 +- .../api/content/ContentApiController.java | 13 +- .../api/privacy/PrivacyApiController.java | 16 +- .../config/Resilience4JConfig.java | 7 +- .../service/attachment/AttachmentService.java | 2 +- .../service/banner/BannerService.java | 1 - .../AttachmentApiControllerTest.java | 41 ++--- .../reserveItem/ReserveItemApiController.java | 18 +- .../dto/ReserveItemListResponseDto.java | 55 ++---- .../dto/ReserveItemMainResponseDto.java | 33 +--- .../dto/ReserveItemRelationResponseDto.java | 4 +- .../domain/reserveItem/ReserveItem.java | 36 ++++ .../ReserveItemRepositoryCustom.java | 3 - .../ReserveItemRepositoryImpl.java | 41 +---- .../service/location/LocationService.java | 2 +- .../reserveItem/ReserveItemService.java | 20 ++- .../validator/ReserveItemSaveValidator.java | 54 ++++-- .../api/ReserveApiController.java | 29 ++- .../domain/ReserveRepositoryCustom.java | 4 +- .../domain/ReserveRepositoryImpl.java | 6 +- .../service/ReserveService.java | 38 ++-- .../api/role/AuthorizationApiController.java | 21 +-- .../api/user/UserApiController.java | 46 ++--- .../api/user/dto/UserJoinRequestDto.java | 23 ++- .../api/user/dto/UserSaveRequestDto.java | 20 +-- .../api/user/dto/UserUpdateRequestDto.java | 8 +- .../config/AuthenticationFilter.java | 104 +++++------ .../role/AuthorizationRepositoryImpl.java | 18 +- .../cloud/userservice/domain/user/User.java | 75 ++++---- .../service/role/AuthorizationService.java | 14 +- .../userservice/service/user/UserService.java | 166 +++++++++++------- .../role/AuthorizationApiControllerTest.java | 13 +- 41 files changed, 520 insertions(+), 583 deletions(-) diff --git a/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/api/posts/dto/PostsSimpleResponseDto.java b/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/api/posts/dto/PostsSimpleResponseDto.java index f56e986..dcd7ceb 100644 --- a/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/api/posts/dto/PostsSimpleResponseDto.java +++ b/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/api/posts/dto/PostsSimpleResponseDto.java @@ -1,15 +1,13 @@ package org.egovframe.cloud.boardservice.api.posts.dto; +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto; + import java.io.Serializable; import java.time.LocalDateTime; -import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto; - -import com.querydsl.core.annotations.QueryProjection; - -import lombok.Getter; -import lombok.NoArgsConstructor; - /** * org.egovframe.cloud.boardservice.api.posts.dto.PostsSimpleResponseDto *

diff --git a/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/domain/board/BoardRepositoryImpl.java b/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/domain/board/BoardRepositoryImpl.java index 9905843..9a3c5d9 100644 --- a/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/domain/board/BoardRepositoryImpl.java +++ b/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/domain/board/BoardRepositoryImpl.java @@ -1,17 +1,5 @@ package org.egovframe.cloud.boardservice.domain.board; -import java.util.List; - -import org.egovframe.cloud.boardservice.api.board.dto.BoardListResponseDto; -import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto; -import org.egovframe.cloud.boardservice.api.board.dto.QBoardListResponseDto; -import org.egovframe.cloud.boardservice.api.board.dto.QBoardResponseDto; -import org.egovframe.cloud.boardservice.domain.code.QCode; -import org.egovframe.cloud.common.dto.RequestDto; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; - import com.google.common.base.CaseFormat; import com.querydsl.core.QueryResults; import com.querydsl.core.types.Order; @@ -21,8 +9,18 @@ import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPQLQuery; import com.querydsl.jpa.impl.JPAQueryFactory; - import lombok.RequiredArgsConstructor; +import org.egovframe.cloud.boardservice.api.board.dto.BoardListResponseDto; +import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto; +import org.egovframe.cloud.boardservice.api.board.dto.QBoardListResponseDto; +import org.egovframe.cloud.boardservice.api.board.dto.QBoardResponseDto; +import org.egovframe.cloud.boardservice.domain.code.QCode; +import org.egovframe.cloud.common.dto.RequestDto; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import java.util.List; /** * org.egovframe.cloud.boardservice.domain.board.BoardRepositoryImpl diff --git a/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/domain/posts/PostsRepositoryImpl.java b/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/domain/posts/PostsRepositoryImpl.java index e525ed8..8ce7a1f 100644 --- a/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/domain/posts/PostsRepositoryImpl.java +++ b/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/domain/posts/PostsRepositoryImpl.java @@ -1,25 +1,5 @@ package org.egovframe.cloud.boardservice.domain.posts; -import java.time.LocalDateTime; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.egovframe.cloud.boardservice.api.board.dto.QBoardResponseDto; -import org.egovframe.cloud.boardservice.api.posts.dto.PostsListResponseDto; -import org.egovframe.cloud.boardservice.api.posts.dto.PostsResponseDto; -import org.egovframe.cloud.boardservice.api.posts.dto.PostsSimpleResponseDto; -import org.egovframe.cloud.boardservice.api.posts.dto.QPostsListResponseDto; -import org.egovframe.cloud.boardservice.api.posts.dto.QPostsResponseDto; -import org.egovframe.cloud.boardservice.api.posts.dto.QPostsSimpleResponseDto; -import org.egovframe.cloud.boardservice.domain.board.QBoard; -import org.egovframe.cloud.boardservice.domain.comment.QComment; -import org.egovframe.cloud.boardservice.domain.user.QUser; -import org.egovframe.cloud.common.dto.RequestDto; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; - import com.google.common.base.CaseFormat; import com.querydsl.core.QueryResults; import com.querydsl.core.Tuple; @@ -27,20 +7,28 @@ import com.querydsl.core.types.ExpressionUtils; import com.querydsl.core.types.Order; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Path; -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.core.types.dsl.CaseBuilder; -import com.querydsl.core.types.dsl.Expressions; -import com.querydsl.core.types.dsl.NumberPath; -import com.querydsl.core.types.dsl.SimpleExpression; -import com.querydsl.core.types.dsl.StringPath; +import com.querydsl.core.types.dsl.*; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.JPQLQuery; import com.querydsl.jpa.impl.JPAQueryFactory; import com.querydsl.sql.SQLExpressions; import com.querydsl.sql.SQLQuery; import com.querydsl.sql.SQLQueryFactory; - import lombok.RequiredArgsConstructor; +import org.egovframe.cloud.boardservice.api.board.dto.QBoardResponseDto; +import org.egovframe.cloud.boardservice.api.posts.dto.*; +import org.egovframe.cloud.boardservice.domain.board.QBoard; +import org.egovframe.cloud.boardservice.domain.comment.QComment; +import org.egovframe.cloud.boardservice.domain.user.QUser; +import org.egovframe.cloud.common.dto.RequestDto; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import java.time.LocalDateTime; +import java.util.Iterator; +import java.util.List; +import java.util.Map; /** * org.egovframe.cloud.boardservice.domain.posts.PostsRepositoryImpl diff --git a/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/service/posts/PostsService.java b/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/service/posts/PostsService.java index 80cb705..4e5e42c 100644 --- a/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/service/posts/PostsService.java +++ b/backend/board-service/src/main/java/org/egovframe/cloud/boardservice/service/posts/PostsService.java @@ -1,23 +1,9 @@ package org.egovframe.cloud.boardservice.service.posts; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - +import lombok.RequiredArgsConstructor; import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto; -import org.egovframe.cloud.boardservice.api.posts.dto.PostsDeleteRequestDto; -import org.egovframe.cloud.boardservice.api.posts.dto.PostsListResponseDto; -import org.egovframe.cloud.boardservice.api.posts.dto.PostsResponseDto; -import org.egovframe.cloud.boardservice.api.posts.dto.PostsSaveRequestDto; -import org.egovframe.cloud.boardservice.api.posts.dto.PostsSimpleResponseDto; -import org.egovframe.cloud.boardservice.api.posts.dto.PostsSimpleSaveRequestDto; -import org.egovframe.cloud.boardservice.api.posts.dto.PostsUpdateRequestDto; -import org.egovframe.cloud.boardservice.domain.posts.Posts; -import org.egovframe.cloud.boardservice.domain.posts.PostsId; -import org.egovframe.cloud.boardservice.domain.posts.PostsRead; -import org.egovframe.cloud.boardservice.domain.posts.PostsReadRepository; -import org.egovframe.cloud.boardservice.domain.posts.PostsRepository; +import org.egovframe.cloud.boardservice.api.posts.dto.*; +import org.egovframe.cloud.boardservice.domain.posts.*; import org.egovframe.cloud.boardservice.service.board.BoardService; import org.egovframe.cloud.common.dto.AttachmentEntityMessage; import org.egovframe.cloud.common.dto.RequestDto; @@ -32,7 +18,10 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; -import lombok.RequiredArgsConstructor; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * org.egovframe.cloud.postsservice.service.posts.PostsService diff --git a/backend/board-service/src/test/java/org/egovframe/cloud/boardservice/api/board/BoardApiControllerTest.java b/backend/board-service/src/test/java/org/egovframe/cloud/boardservice/api/board/BoardApiControllerTest.java index 78a0e02..a098808 100644 --- a/backend/board-service/src/test/java/org/egovframe/cloud/boardservice/api/board/BoardApiControllerTest.java +++ b/backend/board-service/src/test/java/org/egovframe/cloud/boardservice/api/board/BoardApiControllerTest.java @@ -1,14 +1,6 @@ package org.egovframe.cloud.boardservice.api.board; -import static org.assertj.core.api.Assertions.assertThat; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - +import lombok.extern.slf4j.Slf4j; import org.assertj.core.api.Condition; import org.egovframe.cloud.boardservice.api.board.dto.BoardListResponseDto; import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto; @@ -30,7 +22,10 @@ import org.springframework.http.ResponseEntity; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.TestPropertySource; -import lombok.extern.slf4j.Slf4j; +import java.math.BigDecimal; +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; /** * org.egovframe.cloud.boardservice.api.board.BoardApiControllerTest diff --git a/backend/discovery/src/main/resources/application.yml b/backend/discovery/src/main/resources/application.yml index 180b3ea..9312ccc 100644 --- a/backend/discovery/src/main/resources/application.yml +++ b/backend/discovery/src/main/resources/application.yml @@ -14,5 +14,7 @@ eureka: client: register-with-eureka: false fetch-registry: false + service-url: + defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@localhost:8761/eureka server: peer-node-read-timeout-ms: 10000 \ No newline at end of file diff --git a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/PortalApiController.java b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/PortalApiController.java index 40437ce..18cf04c 100644 --- a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/PortalApiController.java +++ b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/PortalApiController.java @@ -33,16 +33,10 @@ public class PortalApiController { * * @return */ - @GetMapping("/actuator/health-portal") + @GetMapping("/actuator/health-info") public String status() { return String.format("GET Portal Service on" + "\n local.server.port :" + env.getProperty("local.server.port") - + "\n token expiration time :" + env.getProperty("token.expiration_time") - + "\n egov.server.ip :" + env.getProperty("egov.server.ip") - + "\n spring.datasource.username :" + env.getProperty("spring.datasource.username") - + "\n spring.profiles.active :" + env.getProperty("spring.profiles.active") - + "\n spring.cloud.config.label :" + env.getProperty("spring.cloud.config.label") - + "\n spring.cloud.config.uri :" + env.getProperty("spring.cloud.config.uri") + "\n egov.message :" + env.getProperty("egov.message") ); } @@ -52,13 +46,10 @@ public class PortalApiController { * * @return */ - @PostMapping("/actuator/health-portal") + @PostMapping("/actuator/health-info") public String poststatus() { return String.format("POST Portal Service on" + "\n local.server.port :" + env.getProperty("local.server.port") - + "\n token expiration time :" + env.getProperty("token.expiration_time") - + "\n egov.server.ip :" + env.getProperty("egov.server.ip") - + "\n spring.datasource.username :" + env.getProperty("spring.datasource.username") + "\n egov.message :" + env.getProperty("egov.message") ); } diff --git a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/banner/BannerApiController.java b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/banner/BannerApiController.java index e824e0a..3465df0 100644 --- a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/banner/BannerApiController.java +++ b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/banner/BannerApiController.java @@ -1,30 +1,17 @@ package org.egovframe.cloud.portalservice.api.banner; -import java.util.List; -import java.util.Map; - -import javax.validation.Valid; - -import org.egovframe.cloud.portalservice.api.banner.dto.BannerImageResponseDto; -import org.egovframe.cloud.portalservice.api.banner.dto.BannerListResponseDto; -import org.egovframe.cloud.portalservice.api.banner.dto.BannerRequestDto; -import org.egovframe.cloud.portalservice.api.banner.dto.BannerResponseDto; -import org.egovframe.cloud.portalservice.api.banner.dto.BannerSaveRequestDto; -import org.egovframe.cloud.portalservice.api.banner.dto.BannerUpdateRequestDto; +import lombok.RequiredArgsConstructor; +import org.egovframe.cloud.portalservice.api.banner.dto.*; import org.egovframe.cloud.portalservice.service.banner.BannerService; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.web.PageableDefault; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; -import lombok.RequiredArgsConstructor; +import javax.validation.Valid; +import java.util.List; +import java.util.Map; /** * org.egovframe.cloud.portalservice.api.banner.BannerApiController diff --git a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/banner/dto/BannerListResponseDto.java b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/banner/dto/BannerListResponseDto.java index 13a3ebf..839a7f8 100644 --- a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/banner/dto/BannerListResponseDto.java +++ b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/banner/dto/BannerListResponseDto.java @@ -1,13 +1,12 @@ package org.egovframe.cloud.portalservice.api.banner.dto; +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; +import lombok.NoArgsConstructor; + import java.io.Serializable; import java.time.LocalDateTime; -import com.querydsl.core.annotations.QueryProjection; - -import lombok.Getter; -import lombok.NoArgsConstructor; - /** * org.egovframe.cloud.portalservice.api.content.dto.BannerListResponseDto *

diff --git a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/banner/dto/BannerSaveRequestDto.java b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/banner/dto/BannerSaveRequestDto.java index aa295ff..04eba42 100644 --- a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/banner/dto/BannerSaveRequestDto.java +++ b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/banner/dto/BannerSaveRequestDto.java @@ -1,11 +1,10 @@ package org.egovframe.cloud.portalservice.api.banner.dto; -import javax.validation.constraints.NotBlank; - +import lombok.Getter; import org.egovframe.cloud.portalservice.domain.banner.Banner; import org.egovframe.cloud.portalservice.domain.menu.Site; -import lombok.Getter; +import javax.validation.constraints.NotBlank; /** * org.egovframe.cloud.portalservice.api.content.dto.BannerSaveRequestDto diff --git a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/content/ContentApiController.java b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/content/ContentApiController.java index 0f288f3..41262b8 100644 --- a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/content/ContentApiController.java +++ b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/content/ContentApiController.java @@ -1,7 +1,6 @@ package org.egovframe.cloud.portalservice.api.content; -import javax.validation.Valid; - +import lombok.RequiredArgsConstructor; import org.egovframe.cloud.common.dto.RequestDto; import org.egovframe.cloud.portalservice.api.content.dto.ContentListResponseDto; import org.egovframe.cloud.portalservice.api.content.dto.ContentResponseDto; @@ -12,15 +11,9 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.web.PageableDefault; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; -import lombok.RequiredArgsConstructor; +import javax.validation.Valid; /** * org.egovframe.cloud.portalservice.api.content.ContentApiController diff --git a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/privacy/PrivacyApiController.java b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/privacy/PrivacyApiController.java index b5e278f..f3b10fe 100644 --- a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/privacy/PrivacyApiController.java +++ b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/api/privacy/PrivacyApiController.java @@ -1,9 +1,6 @@ package org.egovframe.cloud.portalservice.api.privacy; -import java.util.List; - -import javax.validation.Valid; - +import lombok.RequiredArgsConstructor; import org.egovframe.cloud.common.dto.RequestDto; import org.egovframe.cloud.portalservice.api.privacy.dto.PrivacyListResponseDto; import org.egovframe.cloud.portalservice.api.privacy.dto.PrivacyResponseDto; @@ -14,15 +11,10 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.web.PageableDefault; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; -import lombok.RequiredArgsConstructor; +import javax.validation.Valid; +import java.util.List; /** * org.egovframe.cloud.portalservice.api.privacy.PrivacyApiController diff --git a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/config/Resilience4JConfig.java b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/config/Resilience4JConfig.java index 8f27736..1833469 100644 --- a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/config/Resilience4JConfig.java +++ b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/config/Resilience4JConfig.java @@ -34,10 +34,9 @@ public class Resilience4JConfig { @Bean public Customizer resilience4JCircuitBreakerFactoryCustomizer() { CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom() - .failureRateThreshold(50) // Circuit 열지 말지 결정하는 실패 threshold 퍼센테이지 - .waitDurationInOpenState(Duration.ofSeconds(5)) // (half closed 전에) circuitBreaker가 open 되기 전에 기다리는 기간 - .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED) // circuit breaker count 기반 처리 - .slidingWindowSize(10) // 통계 대상 건수 -> N건의 요청중.. + .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED) // circuit breaker time 기반 처리 + .slowCallDurationThreshold(Duration.ofSeconds(10)) // 요청 지연으로 간주하는 시간 + .minimumNumberOfCalls(10) // 통계 최소 요청 건 .build(); return circuitBreakerFactory -> circuitBreakerFactory.configureDefault( diff --git a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/service/attachment/AttachmentService.java b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/service/attachment/AttachmentService.java index b35c6d0..b7b2676 100644 --- a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/service/attachment/AttachmentService.java +++ b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/service/attachment/AttachmentService.java @@ -455,7 +455,7 @@ public class AttachmentService extends AbstractService { for (Attachment attachment: attachmentList) { // 첨부파일 저장 후 기능 저장 시 오류 날 경우에만 첨부파일 전체 삭제를 하므로 // entity 정보가 있는 경우에는 삭제하지 못하도록 한다. - if (attachment.getEntityId() != null || StringUtils.hasText(attachment.getEntityId())) { + if ((attachment.getEntityId() != null || StringUtils.hasText(attachment.getEntityId())) && !attachment.getEntityId().equals("-1")) { throw new BusinessMessageException(getMessage("valid.file.not_deleted")); } // 물리적 파일 삭제 diff --git a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/service/banner/BannerService.java b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/service/banner/BannerService.java index 664cb55..8a86a0b 100644 --- a/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/service/banner/BannerService.java +++ b/backend/portal-service/src/main/java/org/egovframe/cloud/portalservice/service/banner/BannerService.java @@ -118,7 +118,6 @@ public class BannerService extends AbstractService { */ @Transactional public BannerResponseDto save(BannerSaveRequestDto requestDto) { - System.out.println("@@@@@@@@requestDto:"+requestDto); //site 정보 조회 Site site = siteRepository.findById(requestDto.getSiteId()) .orElseThrow(() -> diff --git a/backend/portal-service/src/test/java/org/egovframe/cloud/portalservice/api/attachment/AttachmentApiControllerTest.java b/backend/portal-service/src/test/java/org/egovframe/cloud/portalservice/api/attachment/AttachmentApiControllerTest.java index 09db073..06ab44b 100644 --- a/backend/portal-service/src/test/java/org/egovframe/cloud/portalservice/api/attachment/AttachmentApiControllerTest.java +++ b/backend/portal-service/src/test/java/org/egovframe/cloud/portalservice/api/attachment/AttachmentApiControllerTest.java @@ -1,25 +1,9 @@ package org.egovframe.cloud.portalservice.api.attachment; -import static org.assertj.core.api.Assertions.assertThat; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; - +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Base64; -import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentBase64RequestDto; -import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentEditorResponseDto; -import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentFileResponseDto; -import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentResponseDto; -import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentTempSaveRequestDto; -import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentUpdateRequestDto; -import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentUploadRequestDto; +import org.egovframe.cloud.portalservice.api.attachment.dto.*; import org.egovframe.cloud.portalservice.domain.attachment.Attachment; import org.egovframe.cloud.portalservice.domain.attachment.AttachmentRepository; import org.egovframe.cloud.portalservice.service.attachment.AttachmentService; @@ -35,12 +19,7 @@ import org.springframework.boot.web.server.LocalServerPort; import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; +import org.springframework.http.*; import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.TestPropertySource; @@ -48,9 +27,17 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.multipart.MultipartFile; -import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; -import lombok.extern.slf4j.Slf4j; +import static org.assertj.core.api.Assertions.assertThat; @Slf4j @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) diff --git a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/ReserveItemApiController.java b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/ReserveItemApiController.java index ceb9b56..6f278b1 100644 --- a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/ReserveItemApiController.java +++ b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/ReserveItemApiController.java @@ -14,6 +14,7 @@ import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemRes import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemSaveRequestDto; import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemUpdateRequestDto; import org.egovframe.cloud.reserveitemservice.service.reserveItem.ReserveItemService; +import org.springframework.core.env.Environment; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.http.HttpStatus; @@ -55,6 +56,21 @@ public class ReserveItemApiController { private final ReserveItemService reserveItemService; + private final Environment env; + + /** + * 서비스 상태 확인 + * + * @return + */ + @GetMapping("/actuator/health-info") + public String status() { + return String.format("GET Reserve Item Service on" + + "\n local.server.port :" + env.getProperty("local.server.port") + + "\n egov.message :" + env.getProperty("egov.message") + ); + } + /** * 목록 조회 * @@ -148,7 +164,7 @@ public class ReserveItemApiController { @GetMapping("/api/v1/reserve-items/relations/{reserveItemId}") @ResponseStatus(HttpStatus.OK) public Mono findByIdWithRelations(@PathVariable Long reserveItemId) { - return reserveItemService.findByIdWithRelations(reserveItemId).log(); + return reserveItemService.findByIdWithRelations(reserveItemId); } /** diff --git a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/dto/ReserveItemListResponseDto.java b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/dto/ReserveItemListResponseDto.java index 49c49ce..59946c8 100644 --- a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/dto/ReserveItemListResponseDto.java +++ b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/dto/ReserveItemListResponseDto.java @@ -45,49 +45,18 @@ public class ReserveItemListResponseDto { private Boolean isPossible; //예약 가능 여부 @Builder - public ReserveItemListResponseDto(ReserveItem reserveItem) { - this.reserveItemId = reserveItem.getReserveItemId(); - this.reserveItemName = reserveItem.getReserveItemName(); - this.locationId = reserveItem.getLocationId(); - this.locationName = reserveItem.getLocation().getLocationName(); - this.categoryId = reserveItem.getCategoryId(); - this.categoryName = reserveItem.getCategoryName(); - this.totalQty = reserveItem.getTotalQty(); - this.inventoryQty = reserveItem.getInventoryQty(); - this.isUse = reserveItem.getIsUse(); - this.createDate = reserveItem.getCreateDate(); - this.isPossible = isReservationPossible(reserveItem); - } - - /** - * 예약 가능 여부 체크 - * - * @param reserveItem - * @return - */ - private boolean isReservationPossible(ReserveItem reserveItem) { - LocalDateTime now = LocalDateTime.now(); - if (!reserveItem.getIsUse()) { - return false; - } - - if (reserveItem.getInventoryQty() <= 0) { - return false; - } - - if (reserveItem.getIsPeriod()) { - if (reserveItem.getRequestStartDate().isBefore(now) && reserveItem.getRequestEndDate().isAfter(now)) { - return true; - }else { - return false; - } - } else { - if (reserveItem.getOperationStartDate().isBefore(now) && reserveItem.getOperationEndDate().isAfter(now)) { - return true; - }else { - return false; - } - } + public ReserveItemListResponseDto(ReserveItem entity) { + this.reserveItemId = entity.getReserveItemId(); + this.reserveItemName = entity.getReserveItemName(); + this.locationId = entity.getLocationId(); + this.locationName = entity.getLocation().getLocationName(); + this.categoryId = entity.getCategoryId(); + this.categoryName = entity.getCategoryName(); + this.totalQty = entity.getTotalQty(); + this.inventoryQty = entity.getInventoryQty(); + this.isUse = entity.getIsUse(); + this.createDate = entity.getCreateDate(); + this.isPossible = entity.isReservationPossible(); } } diff --git a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/dto/ReserveItemMainResponseDto.java b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/dto/ReserveItemMainResponseDto.java index 28ad80b..57de071 100644 --- a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/dto/ReserveItemMainResponseDto.java +++ b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/dto/ReserveItemMainResponseDto.java @@ -36,38 +36,7 @@ public class ReserveItemMainResponseDto { this.endDate = entity.getRequestEndDate(); } } - this.isPossible = isReservationPossible(entity); - } - - /** - * 예약 가능 여부 체크 - * - * @param entity - * @return - */ - private boolean isReservationPossible(ReserveItem entity) { - LocalDateTime now = LocalDateTime.now(); - if (!entity.getIsUse()) { - return false; - } - - if (entity.getInventoryQty() <= 0) { - return false; - } - - if (entity.getIsPeriod()) { - if (entity.getRequestStartDate().isBefore(now) && entity.getRequestEndDate().isAfter(now)) { - return true; - }else { - return false; - } - } else { - if (entity.getOperationStartDate().isBefore(now) && entity.getOperationEndDate().isAfter(now)) { - return true; - }else { - return false; - } - } + this.isPossible = entity.isReservationPossible(); } } diff --git a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/dto/ReserveItemRelationResponseDto.java b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/dto/ReserveItemRelationResponseDto.java index d3e8cc3..4e77acc 100644 --- a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/dto/ReserveItemRelationResponseDto.java +++ b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/api/reserveItem/dto/ReserveItemRelationResponseDto.java @@ -66,6 +66,7 @@ public class ReserveItemRelationResponseDto { private String managerDept; //담당자 소속 private String managerName; //담당자 이름 private String managerContact; //담당자 연락처 + private Boolean isPossible; //예약 가능 여부 @Builder public ReserveItemRelationResponseDto(ReserveItem entity) { @@ -103,8 +104,9 @@ public class ReserveItemRelationResponseDto { this.managerDept = entity.getManagerDept(); this.managerName = entity.getManagerName(); this.managerContact = entity.getManagerContact(); - + this.isPossible = entity.isReservationPossible(); } + } diff --git a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/domain/reserveItem/ReserveItem.java b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/domain/reserveItem/ReserveItem.java index d8cedb6..6576540 100644 --- a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/domain/reserveItem/ReserveItem.java +++ b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/domain/reserveItem/ReserveItem.java @@ -332,10 +332,46 @@ public class ReserveItem extends BaseEntity { return this; } + /** + * 생성일 세팅 + * + * @param createDate + * @return + */ public ReserveItem setCreateDate(LocalDateTime createDate) { this.createDate = createDate; return this; } + + /** + * 예약 가능 여부 체크 + * + * @return + */ + public Boolean isReservationPossible() { + if (!this.getIsUse()) { + return false; + } + + if (this.getInventoryQty() <= 0) { + return false; + } + + LocalDateTime now = LocalDateTime.now(); + if (this.getReserveMethodId().equals("internet") && this.getReserveMeansId().equals("realtime")) { + if (this.getRequestStartDate().isBefore(now) && this.getRequestEndDate().isAfter(now)) { + return true; + }else { + return false; + } + } else { + if (this.getOperationStartDate().isBefore(now) && this.getOperationEndDate().isAfter(now)) { + return true; + }else { + return false; + } + } + } } diff --git a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/domain/reserveItem/ReserveItemRepositoryCustom.java b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/domain/reserveItem/ReserveItemRepositoryCustom.java index 55d55b5..1f73c57 100644 --- a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/domain/reserveItem/ReserveItemRepositoryCustom.java +++ b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/domain/reserveItem/ReserveItemRepositoryCustom.java @@ -33,9 +33,6 @@ public interface ReserveItemRepositoryCustom { Flux search(ReserveItemRequestDto requestDto, Pageable pageable); Mono searchCount(ReserveItemRequestDto requestDto, Pageable pageable); - Flux searchForUser(String categoryId, ReserveItemRequestDto requestDto, Pageable pageable); - Mono searchCountForUser(String categoryId, ReserveItemRequestDto requestDto, Pageable pageable); - Mono findWithRelation(Long reserveItemId); Flux findLatestByCategory(Integer count, String categoryId); diff --git a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/domain/reserveItem/ReserveItemRepositoryImpl.java b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/domain/reserveItem/ReserveItemRepositoryImpl.java index c8937cb..eaf3f6e 100644 --- a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/domain/reserveItem/ReserveItemRepositoryImpl.java +++ b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/domain/reserveItem/ReserveItemRepositoryImpl.java @@ -77,42 +77,6 @@ public class ReserveItemRepositoryImpl implements ReserveItemRepositoryCustom{ .count(); } - @Override - public Flux searchForUser(String categoryId, ReserveItemRequestDto requestDto, Pageable pageable) { - Criteria where = Criteria.from(whereQuery(requestDto)); - - if (!"all".equals(categoryId)) { - where = where.and(where("category_id").is(categoryId)); - } - - Query query = Query.query(where("use_at").isTrue().and(where)) - .sort(Sort.by(Sort.Direction.DESC, "create_date")) - .with(pageable); - - return entityTemplate.select(ReserveItem.class) - .matching(query) - .all() - .flatMap(this::loadRelations) - .switchIfEmpty(Flux.empty()); - } - - - @Override - public Mono searchCountForUser(String categoryId, ReserveItemRequestDto requestDto, Pageable pageable) { - Criteria where = Criteria.from(whereQuery(requestDto)); - - if (!"all".equals(categoryId)) { - where = where.and(where("category_id").is(categoryId)); - } - - Query query = Query.query(where("use_at").isTrue().and(where)) - .sort(Sort.by(Sort.Direction.DESC, "create_date")) - .with(pageable); - return entityTemplate.select(ReserveItem.class) - .matching(query) - .count(); - } - /** * relation 걸린 table 정보도 같이 조회 * 공통코드, 지역 @@ -258,11 +222,11 @@ public class ReserveItemRepositoryImpl implements ReserveItemRepositoryCustom{ } } - if (requestDto.getLocationId() != null) { + if (requestDto.getLocationId() != null && !"null".equals(requestDto.getLocationId()) && !"undefined".equals(requestDto.getLocationId())) { whereCriteria.add(where("location_id").in(requestDto.getLocationId())); } - if (requestDto.getCategoryId() != null ) { + if (requestDto.getCategoryId() != null && !"null".equals(requestDto.getCategoryId()) && !"undefined".equals(requestDto.getCategoryId())) { whereCriteria.add(where("category_id").in(requestDto.getCategoryId())); } @@ -271,6 +235,7 @@ public class ReserveItemRepositoryImpl implements ReserveItemRepositoryCustom{ whereCriteria.add(where("use_at").isTrue()); whereCriteria.add(where("reserve_method_id").is("internet")); } + System.out.println(whereCriteria.toString()); return whereCriteria; } diff --git a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/service/location/LocationService.java b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/service/location/LocationService.java index 5c73685..6963e5b 100644 --- a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/service/location/LocationService.java +++ b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/service/location/LocationService.java @@ -165,7 +165,7 @@ public class LocationService extends ReactiveAbstractService { .switchIfEmpty(monoResponseStatusEntityNotFoundException(locationId)) .flatMap(locationRepository::delete) .onErrorResume(DataIntegrityViolationException.class, - throwable -> Mono.error(new BusinessMessageException("참조하는 데이터가 있어 삭제할 수 없습니다."))); + throwable -> Mono.error(new BusinessMessageException(getMessage("err.db.constraint.delete")))); } /** diff --git a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/service/reserveItem/ReserveItemService.java b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/service/reserveItem/ReserveItemService.java index 1466c7e..e3ef3d5 100644 --- a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/service/reserveItem/ReserveItemService.java +++ b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/service/reserveItem/ReserveItemService.java @@ -1,5 +1,6 @@ package org.egovframe.cloud.reserveitemservice.service.reserveItem; +import java.time.Duration; import java.time.LocalDateTime; import java.util.Collection; import java.util.Collections; @@ -79,7 +80,7 @@ public class ReserveItemService extends ReactiveAbstractService { * @return */ private Mono convertReserveItemListResponseDto(ReserveItem reserveItem) { - return Mono.just(ReserveItemListResponseDto.builder().reserveItem(reserveItem).build()); + return Mono.just(ReserveItemListResponseDto.builder().entity(reserveItem).build()); } /** @@ -108,10 +109,13 @@ public class ReserveItemService extends ReactiveAbstractService { */ @Transactional(readOnly = true) public Mono> searchForUser(String categoryId, ReserveItemRequestDto requestDto, Pageable pageable) { - return reserveItemRepository.searchForUser(categoryId, requestDto, pageable) + if (!"all".equals(categoryId)) { + requestDto.setCategoryId(categoryId); + } + return reserveItemRepository.search(requestDto, pageable) .flatMap(this::convertReserveItemListResponseDto) .collectList() - .zipWith(reserveItemRepository.searchCountForUser(categoryId, requestDto, pageable)) + .zipWith(reserveItemRepository.searchCount(requestDto, pageable)) .flatMap(tuple -> Mono.just(new PageImpl<>(tuple.getT1(), pageable, tuple.getT2()))); } @@ -200,22 +204,26 @@ public class ReserveItemService extends ReactiveAbstractService { .switchIfEmpty(monoResponseStatusEntityNotFoundException(reserveItemId)) .flatMap(reserveItem -> { if (!Category.EDUCATION.isEquals(reserveItem.getCategoryId())) { - return Mono.error(new BusinessMessageException("저장할 수 없습니다.")); + //해당 예약은 수정할 수 없습니다. + return Mono.error(new BusinessMessageException(getMessage("valid.reserve_not_update"))); } LocalDateTime now = LocalDateTime.now(); if (!(now.isAfter(reserveItem.getRequestStartDate()) && now.isBefore(reserveItem.getRequestEndDate()))) { - return Mono.error(new BusinessMessageException("예약 가능 일자가 아닙니다.")); + //해당 날짜에는 예약할 수 없습니다. + return Mono.error(new BusinessMessageException(getMessage("valid.reserve_date"))); } int qty = reserveItem.getInventoryQty() - reserveQty; if (qty < 0) { - return Mono.error(new BusinessMessageException("재고가 없습니다.")); + //해당 날짜에 예약할 수 있는 재고수량이 없습니다. + return Mono.error(new BusinessMessageException(getMessage("valid.reserve_count"))); } return Mono.just(reserveItem.updateInventoryQty(qty)); }) .flatMap(reserveItemRepository::save) + .delayElement(Duration.ofSeconds(5)) .publishOn(Schedulers.boundedElastic()) .doOnNext(reserveItem -> { log.info("reserve item inventory updated success"); diff --git a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/validator/ReserveItemSaveValidator.java b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/validator/ReserveItemSaveValidator.java index 746fade..d159d32 100644 --- a/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/validator/ReserveItemSaveValidator.java +++ b/backend/reserve-item-service/src/main/java/org/egovframe/cloud/reserveitemservice/validator/ReserveItemSaveValidator.java @@ -2,9 +2,12 @@ package org.egovframe.cloud.reserveitemservice.validator; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; + +import org.egovframe.cloud.common.util.MessageUtil; import org.egovframe.cloud.reserveitemservice.validator.annotation.ReserveItemSaveValid; import org.springframework.util.StringUtils; +import javax.annotation.Resource; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.lang.reflect.Field; @@ -30,6 +33,11 @@ import java.time.LocalDateTime; @Slf4j public class ReserveItemSaveValidator implements ConstraintValidator { + @Resource( + name = "messageUtil" + ) + protected MessageUtil messageUtil; + private String message; @Override @@ -54,7 +62,8 @@ public class ReserveItemSaveValidator implements ConstraintValidator create(@RequestBody Mono saveRequestDtoMono) { return saveRequestDtoMono.flatMap(reserveService::create); @@ -79,10 +98,12 @@ public class ReserveApiController { * @param reserveId * @return */ + @CrossOrigin() @GetMapping(value = "/api/v1/requests/direct/{reserveId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - public Flux receiveReservationResult(@PathVariable String reserveId) { + public Flux receiveReservationResult(@PathVariable String reserveId) { MessageListenerContainer mlc = messageListenerContainerFactory.createMessageListenerContainer(reserveId); Flux f = Flux.create(emitter -> { + mlc.setupMessageListener((MessageListener) m -> { String qname = m.getMessageProperties().getConsumerQueue(); log.info("message received, queue={}", qname); @@ -118,7 +139,9 @@ public class ReserveApiController { .map(v -> { log.info("sending keepalive message..."); return "no news is good news"; - }).mergeWith(f); + }) + .mergeWith(f) + .delayElements(Duration.ofSeconds(5)); } } diff --git a/backend/reserve-request-service/src/main/java/org/egovframe/cloud/reserverequestservice/domain/ReserveRepositoryCustom.java b/backend/reserve-request-service/src/main/java/org/egovframe/cloud/reserverequestservice/domain/ReserveRepositoryCustom.java index 584d374..2223e71 100644 --- a/backend/reserve-request-service/src/main/java/org/egovframe/cloud/reserverequestservice/domain/ReserveRepositoryCustom.java +++ b/backend/reserve-request-service/src/main/java/org/egovframe/cloud/reserverequestservice/domain/ReserveRepositoryCustom.java @@ -23,6 +23,6 @@ import reactor.core.publisher.Mono; */ public interface ReserveRepositoryCustom { Mono insert(Reserve reserve); - Flux findAllByReserveDateWithoutSelf(String reserveId, Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate); - Mono findAllByReserveDateWithoutSelfCount(String reserveId, Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate); + Flux findAllByReserveDate(Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate); + Mono findAllByReserveDateCount(Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate); } diff --git a/backend/reserve-request-service/src/main/java/org/egovframe/cloud/reserverequestservice/domain/ReserveRepositoryImpl.java b/backend/reserve-request-service/src/main/java/org/egovframe/cloud/reserverequestservice/domain/ReserveRepositoryImpl.java index 1958b1f..99b6a0f 100644 --- a/backend/reserve-request-service/src/main/java/org/egovframe/cloud/reserverequestservice/domain/ReserveRepositoryImpl.java +++ b/backend/reserve-request-service/src/main/java/org/egovframe/cloud/reserverequestservice/domain/ReserveRepositoryImpl.java @@ -54,12 +54,11 @@ public class ReserveRepositoryImpl implements ReserveRepositoryCustom { * @return */ @Override - public Flux findAllByReserveDateWithoutSelf(String reserveId, Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate) { + public Flux findAllByReserveDate(Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate) { return entityTemplate.select(Reserve.class) .matching(Query.query(where("reserve_item_id").is(reserveItemId) .and ("reserve_start_date").lessThanOrEquals(endDate) .and("reserve_end_date").greaterThanOrEquals(startDate) - .and("reserve_id").not(reserveId) )) .all(); } @@ -74,12 +73,11 @@ public class ReserveRepositoryImpl implements ReserveRepositoryCustom { * @return */ @Override - public Mono findAllByReserveDateWithoutSelfCount(String reserveId, Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate) { + public Mono findAllByReserveDateCount(Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate) { return entityTemplate.select(Reserve.class) .matching(Query.query(where("reserve_item_id").is(reserveItemId) .and ("reserve_start_date").lessThanOrEquals(endDate) .and("reserve_end_date").greaterThanOrEquals(startDate) - .and("reserve_id").not(reserveId) )) .count(); } diff --git a/backend/reserve-request-service/src/main/java/org/egovframe/cloud/reserverequestservice/service/ReserveService.java b/backend/reserve-request-service/src/main/java/org/egovframe/cloud/reserverequestservice/service/ReserveService.java index 4e6bc9a..e1cf582 100644 --- a/backend/reserve-request-service/src/main/java/org/egovframe/cloud/reserverequestservice/service/ReserveService.java +++ b/backend/reserve-request-service/src/main/java/org/egovframe/cloud/reserverequestservice/service/ReserveService.java @@ -3,6 +3,7 @@ package org.egovframe.cloud.reserverequestservice.service; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.egovframe.cloud.common.config.GlobalConstant; +import org.egovframe.cloud.common.dto.AttachmentEntityMessage; import org.egovframe.cloud.common.exception.BusinessMessageException; import org.egovframe.cloud.reactive.service.ReactiveAbstractService; import org.egovframe.cloud.reserverequestservice.api.dto.ReserveResponseDto; @@ -99,6 +100,12 @@ public class ReserveService extends ReactiveAbstractService { return Mono.just(tuple.getT1()); }) .flatMap(reserveRepository::insert) + .doOnNext(reserve -> sendAttachmentEntityInfo(streamBridge, + AttachmentEntityMessage.builder() + .attachmentCode(reserve.getAttachmentCode()) + .entityName(reserve.getClass().getName()) + .entityId(reserve.getReserveId()) + .build())) .flatMap(this::convertReserveResponseDto); } @@ -164,7 +171,8 @@ public class ReserveService extends ReactiveAbstractService { }else if (Category.SPACE.isEquals(saveRequestDto.getCategoryId())) { return checkSpace(saveRequestDto); } - return Mono.error(new BusinessMessageException("저장 할 수 없습니다.")); + //해당 날짜에는 예약할 수 없습니다. + return Mono.error(new BusinessMessageException(getMessage("valid.reserve_date"))); } /** @@ -180,17 +188,23 @@ public class ReserveService extends ReactiveAbstractService { saveRequestDto.getRequestEndDate() : saveRequestDto.getOperationEndDate(); if (saveRequestDto.getReserveStartDate().isBefore(startDate)) { - return Mono.error(new BusinessMessageException("시작일이 운영/예약 시작일 이전입니다.")); + //{0}이 {1} 보다 빠릅니다. 시작일, 운영/예약 시작일 + return Mono.error(new BusinessMessageException(getMessage("valid.to_be_fast.format", new Object[]{getMessage("common.start_date"), + getMessage("reserve_item.operation")+getMessage("reserve")+" "+getMessage("common.start_date")}))); } if (saveRequestDto.getReserveEndDate().isAfter(endDate)) { - return Mono.error(new BusinessMessageException("종료일이 운영/예약 종료일 이후입니다.")); + //{0}이 {1} 보다 늦습니다. 종료일, 운영/예약 종료일 + return Mono.error(new BusinessMessageException(getMessage("valid.to_be_slow.format", new Object[]{getMessage("common.end_date"), + getMessage("reserve_item.operation")+getMessage("reserve")+" "+getMessage("common.end_date")}))); } + if (saveRequestDto.getIsPeriod()) { long between = ChronoUnit.DAYS.between(saveRequestDto.getReserveStartDate(), saveRequestDto.getReserveEndDate()); if (saveRequestDto.getPeriodMaxCount() < between) { - return Mono.error(new BusinessMessageException("최대 예약 가능 일수보다 예약기간이 깁니다. (최대 예약 가능일 수 : "+saveRequestDto.getPeriodMaxCount()+")")); + //최대 예약 가능 일수보다 예약기간이 깁니다. (최대 예약 가능일 수 : {0}) + return Mono.error(new BusinessMessageException(getMessage("valid.reserve_period", new Object[]{saveRequestDto.getPeriodMaxCount()}))); } } return Mono.just(saveRequestDto); @@ -204,14 +218,14 @@ public class ReserveService extends ReactiveAbstractService { */ private Mono checkSpace(ReserveSaveRequestDto saveRequestDto) { return this.checkReserveDate(saveRequestDto) - .flatMap(result -> reserveRepository.findAllByReserveDateWithoutSelfCount( - result.getReserveId(), + .flatMap(result -> reserveRepository.findAllByReserveDateCount( result.getReserveItemId(), result.getReserveStartDate(), result.getReserveEndDate()) .flatMap(count -> { if (count > 0) { - return Mono.error(new BusinessMessageException("해당 날짜에는 예약할 수 없습니다.")); + //해당 날짜에는 예약할 수 없습니다. + return Mono.error(new BusinessMessageException(getMessage("valid.reserve_date"))); } return Mono.just(result); }) @@ -226,8 +240,7 @@ public class ReserveService extends ReactiveAbstractService { */ private Mono checkEquipment(ReserveSaveRequestDto saveRequestDto) { return this.checkReserveDate(saveRequestDto) - .flatMap(result -> this.getMaxByReserveDateWithoutSelf( - result.getReserveId(), + .flatMap(result -> this.getMaxByReserveDate( result.getReserveItemId(), result.getReserveStartDate(), result.getReserveEndDate()) @@ -239,7 +252,8 @@ public class ReserveService extends ReactiveAbstractService { }) .flatMap(isValid -> { if (!isValid) { - return Mono.error(new BusinessMessageException("해당 날짜에 예약할 수 있는 재고수량이 없습니다.")); + //해당 날짜에 예약할 수 있는 재고수량이 없습니다. + return Mono.error(new BusinessMessageException(getMessage("valid.reserve_count"))); } return Mono.just(saveRequestDto); }) @@ -255,8 +269,8 @@ public class ReserveService extends ReactiveAbstractService { * @param endDate * @return */ - private Mono getMaxByReserveDateWithoutSelf(String reserveId, Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate) { - Flux reserveFlux = reserveRepository.findAllByReserveDateWithoutSelf(reserveId, reserveItemId, startDate, endDate) + private Mono getMaxByReserveDate( Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate) { + Flux reserveFlux = reserveRepository.findAllByReserveDate(reserveItemId, startDate, endDate) .switchIfEmpty(Flux.empty()); if (reserveFlux.equals(Flux.empty())) { diff --git a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/role/AuthorizationApiController.java b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/role/AuthorizationApiController.java index dbe7e8d..d689f3d 100644 --- a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/role/AuthorizationApiController.java +++ b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/role/AuthorizationApiController.java @@ -1,10 +1,7 @@ package org.egovframe.cloud.userservice.api.role; -import java.util.List; -import java.util.stream.Collectors; - -import javax.validation.Valid; - +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.egovframe.cloud.common.dto.RequestDto; import org.egovframe.cloud.userservice.api.role.dto.AuthorizationListResponseDto; import org.egovframe.cloud.userservice.api.role.dto.AuthorizationResponseDto; @@ -18,17 +15,11 @@ import org.springframework.data.web.PageableDefault; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; +import javax.validation.Valid; +import java.util.List; +import java.util.stream.Collectors; /** * org.egovframe.cloud.userservice.api.role.AuthorizationApiController diff --git a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/UserApiController.java b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/UserApiController.java index abd95b1..896f232 100644 --- a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/UserApiController.java +++ b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/UserApiController.java @@ -1,27 +1,10 @@ package org.egovframe.cloud.userservice.api.user; -import java.io.IOException; -import java.security.GeneralSecurityException; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; - +import lombok.RequiredArgsConstructor; import org.egovframe.cloud.common.dto.RequestDto; import org.egovframe.cloud.common.exception.BusinessMessageException; import org.egovframe.cloud.common.util.MessageUtil; -import org.egovframe.cloud.userservice.api.user.dto.UserEmailRequestDto; -import org.egovframe.cloud.userservice.api.user.dto.UserFindPasswordSaveRequestDto; -import org.egovframe.cloud.userservice.api.user.dto.UserFindPasswordUpdateRequestDto; -import org.egovframe.cloud.userservice.api.user.dto.UserJoinRequestDto; -import org.egovframe.cloud.userservice.api.user.dto.UserListResponseDto; -import org.egovframe.cloud.userservice.api.user.dto.UserPasswordMatchRequestDto; -import org.egovframe.cloud.userservice.api.user.dto.UserPasswordUpdateRequestDto; -import org.egovframe.cloud.userservice.api.user.dto.UserResponseDto; -import org.egovframe.cloud.userservice.api.user.dto.UserSaveRequestDto; -import org.egovframe.cloud.userservice.api.user.dto.UserUpdateInfoRequestDto; -import org.egovframe.cloud.userservice.api.user.dto.UserUpdateRequestDto; -import org.egovframe.cloud.userservice.api.user.dto.UserVerifyRequestDto; +import org.egovframe.cloud.userservice.api.user.dto.*; import org.egovframe.cloud.userservice.config.TokenProvider; import org.egovframe.cloud.userservice.service.user.UserService; import org.springframework.core.env.Environment; @@ -29,15 +12,13 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpHeaders; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; -import lombok.RequiredArgsConstructor; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.security.GeneralSecurityException; /** * org.egovframe.cloud.userservice.api.user.UserApiController @@ -149,6 +130,17 @@ public class UserApiController { tokenProvider.refreshToken(refreshToken, response); } + /** + * 사용자 회원 가입 + * + * @param requestDto 사용자 가입 요청 DTO + * @return Boolean 성공 여부 + */ + @PostMapping("/api/v1/users/social") + public SocialUserResponseDto social(@RequestBody @Valid SocialUserRequestDto requestDto) { + return userService.getSocialUserInfo(requestDto.getProvider(), requestDto.getToken()); + } + /** * 이메일 중복 확인 * diff --git a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/dto/UserJoinRequestDto.java b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/dto/UserJoinRequestDto.java index 0172255..e68703a 100644 --- a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/dto/UserJoinRequestDto.java +++ b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/dto/UserJoinRequestDto.java @@ -33,24 +33,43 @@ import java.util.UUID; @NoArgsConstructor public class UserJoinRequestDto { + /** + * 사용자 이름 + */ @NotBlank(message = "{user.user_name}{valid.required}") private String userName; + /** + * 이메일 + */ @NotBlank(message = "{user.email}{valid.required}") @Email private String email; + /** + * 비밀번호 + */ // (숫자)(영문)(특수문자)(공백제거)(자리수) @Pattern(regexp = "(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\W)(?=\\S+$).{8,20}", message = "{valid.password}") private String password; + /** + * 소셜 공급자 + */ + private String provider; + + /** + * 소셜 토큰 + */ + private String token; + /** * UserSaveRequestDto 의 필드 값을 User Entity 빌더를 사용하여 주입 후 User를 리턴한다. * UserSaveRequestDto 가 가지고 있는 User 의 필드만 세팅할 수 있게 된다. * - * @param passwordEncoder - * @return + * @param passwordEncoder 비밀번호 인코더 + * @return User 사용자 엔티티 */ public User toEntity(BCryptPasswordEncoder passwordEncoder) { return User.builder() diff --git a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/dto/UserSaveRequestDto.java b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/dto/UserSaveRequestDto.java index 46d65a7..c9a2f97 100644 --- a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/dto/UserSaveRequestDto.java +++ b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/dto/UserSaveRequestDto.java @@ -1,19 +1,17 @@ package org.egovframe.cloud.userservice.api.user.dto; -import java.util.Arrays; -import java.util.UUID; - -import javax.validation.constraints.Email; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; - -import org.egovframe.cloud.common.domain.Role; -import org.egovframe.cloud.userservice.domain.user.User; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; - import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.egovframe.cloud.common.domain.Role; +import org.egovframe.cloud.userservice.domain.user.User; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import java.util.Arrays; +import java.util.UUID; /** * org.egovframe.cloud.userservice.api.user.dto.UserSaveRequestDto diff --git a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/dto/UserUpdateRequestDto.java b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/dto/UserUpdateRequestDto.java index ebf10c6..6ab8c2b 100644 --- a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/dto/UserUpdateRequestDto.java +++ b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/api/user/dto/UserUpdateRequestDto.java @@ -1,13 +1,13 @@ package org.egovframe.cloud.userservice.api.user.dto; -import javax.validation.constraints.Email; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; - import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; + /** * org.egovframe.cloud.userservice.api.user.dto.UserUpdateRequestDto *

diff --git a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/config/AuthenticationFilter.java b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/config/AuthenticationFilter.java index 60f5d0d..d0c06c2 100644 --- a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/config/AuthenticationFilter.java +++ b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/config/AuthenticationFilter.java @@ -1,21 +1,9 @@ package org.egovframe.cloud.userservice.config; -import static org.egovframe.cloud.common.config.GlobalConstant.LOGIN_URI; -import static org.springframework.util.StringUtils.hasLength; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import com.fasterxml.jackson.databind.ObjectMapper; +import io.jsonwebtoken.Claims; +import lombok.extern.slf4j.Slf4j; +import org.egovframe.cloud.common.exception.BusinessException; import org.egovframe.cloud.common.util.LogUtil; import org.egovframe.cloud.userservice.api.user.dto.UserLoginRequestDto; import org.egovframe.cloud.userservice.api.user.dto.UserResponseDto; @@ -34,10 +22,19 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.transaction.annotation.Transactional; -import com.fasterxml.jackson.databind.ObjectMapper; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; -import io.jsonwebtoken.Claims; -import lombok.extern.slf4j.Slf4j; +import static org.springframework.util.StringUtils.hasLength; /** * org.egovframe.cloud.userservice.config.AuthenticationFilter @@ -76,11 +73,11 @@ public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter { * @param request http 요청 * @param response http 응답 * @return Authentication 인증정보 - * @throws NullPointerException 널 포인터 예외 - * @throws Exception 예외 + * @throws IOException 입출력 예외 + * @throws Exception 예외 */ @Override - public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) { try { // 사용자가 입력한 인증정보 받기, POST method 값이기 때문에 input stream으로 받았다. UserLoginRequestDto creds = new ObjectMapper().readValue(request.getInputStream(), UserLoginRequestDto.class); @@ -108,12 +105,12 @@ public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter { // 인증정보 만들기 return getAuthenticationManager().authenticate(upat); } - } catch (NullPointerException e) { + } catch (IOException e) { log.error(e.getLocalizedMessage()); throw new RuntimeException(e); } catch (Exception e) { log.error(e.getLocalizedMessage()); - throw new RuntimeException(e); + throw e; } } @@ -163,46 +160,41 @@ public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter { * @param request * @param response * @param chain - * @throws IOException - * @throws ServletException */ @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - HttpServletRequest httpRequest = (HttpServletRequest) request; - String token = httpRequest.getHeader(HttpHeaders.AUTHORIZATION); - if (!hasLength(token) || "undefined".equals(token)) { - super.doFilter(request, response, chain); - } else { - try { - final String requestURI = httpRequest.getRequestURI(); - log.info("httpRequest.getRequestURI() ={}", requestURI); + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { + try { + HttpServletRequest httpRequest = (HttpServletRequest) request; + String token = httpRequest.getHeader(HttpHeaders.AUTHORIZATION); + if (!hasLength(token) || "undefined".equals(token)) { + super.doFilter(request, response, chain); + } else { + // 토큰 유효성 검사는 API Gateway ReactiveAuthorization 클래스에서 미리 처리된다. + Claims claims = tokenProvider.getClaimsFromToken(token); - if (LOGIN_URI.equals(requestURI)) { - // 로그인 등 토큰 정보를 꺼낼 필요가 없는 경우 + String username = claims.getSubject(); + if (username == null) { + // refresh token 에는 subject, authorities 정보가 없다. SecurityContextHolder.getContext().setAuthentication(null); } else { - // 토큰 유효성 검사는 API Gateway ReactiveAuthorization 클래스에서 미리 처리된다. - Claims claims = tokenProvider.getClaimsFromToken(token); - - String username = claims.getSubject(); - if (username == null) { - // refresh token 에는 subject, authorities 정보가 없다. - SecurityContextHolder.getContext().setAuthentication(null); - } else { - List roleList = Arrays.stream(claims.get(tokenProvider.TOKEN_CLAIM_NAME, String.class).split(",")) - .map(SimpleGrantedAuthority::new) - .collect(Collectors.toList()); - SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(username, null, roleList)); - } + List roleList = Arrays.stream(claims.get(tokenProvider.TOKEN_CLAIM_NAME, String.class).split(",")) + .map(SimpleGrantedAuthority::new) + .collect(Collectors.toList()); + SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(username, null, roleList)); } - chain.doFilter(request, response); - } catch (Exception e) { - SecurityContextHolder.getContext().setAuthentication(null); - HttpServletResponse httpServletResponse = (HttpServletResponse) response; - httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value()); - log.error("AuthenticationFilter doFilter", e); + chain.doFilter(request, response); } + } catch (BusinessException e) { + SecurityContextHolder.getContext().setAuthentication(null); + HttpServletResponse httpServletResponse = (HttpServletResponse) response; + httpServletResponse.setStatus(e.getErrorCode().getStatus()); + log.error("AuthenticationFilter doFilter error: {}", e.getMessage()); + } catch (Exception e) { + SecurityContextHolder.getContext().setAuthentication(null); + HttpServletResponse httpServletResponse = (HttpServletResponse) response; + httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value()); + log.error("AuthenticationFilter doFilter error: {}", e.getMessage()); } } } diff --git a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/domain/role/AuthorizationRepositoryImpl.java b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/domain/role/AuthorizationRepositoryImpl.java index 9f2cd53..8814600 100644 --- a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/domain/role/AuthorizationRepositoryImpl.java +++ b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/domain/role/AuthorizationRepositoryImpl.java @@ -1,14 +1,5 @@ package org.egovframe.cloud.userservice.domain.role; -import java.util.List; - -import org.egovframe.cloud.common.dto.RequestDto; -import org.egovframe.cloud.userservice.api.role.dto.AuthorizationListResponseDto; -import org.egovframe.cloud.userservice.domain.user.QUser; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; - import com.google.common.base.CaseFormat; import com.querydsl.core.QueryResults; import com.querydsl.core.types.Order; @@ -20,8 +11,15 @@ import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.JPQLQuery; import com.querydsl.jpa.impl.JPAQueryFactory; - import lombok.RequiredArgsConstructor; +import org.egovframe.cloud.common.dto.RequestDto; +import org.egovframe.cloud.userservice.api.role.dto.AuthorizationListResponseDto; +import org.egovframe.cloud.userservice.domain.user.QUser; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import java.util.List; /** * org.egovframe.cloud.userservice.domain.role.AuthorizationRepositoryImpl diff --git a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/domain/user/User.java b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/domain/user/User.java index 01a9fbd..f571d3a 100644 --- a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/domain/user/User.java +++ b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/domain/user/User.java @@ -1,25 +1,18 @@ package org.egovframe.cloud.userservice.domain.user; -import static javax.persistence.GenerationType.IDENTITY; - -import java.time.LocalDateTime; -import java.util.Arrays; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; - +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; import org.egovframe.cloud.common.domain.Role; import org.egovframe.cloud.servlet.domain.BaseEntity; import org.hibernate.annotations.DynamicInsert; import org.hibernate.annotations.DynamicUpdate; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import javax.persistence.*; +import java.time.LocalDateTime; +import java.util.Arrays; + +import static javax.persistence.GenerationType.IDENTITY; /** * org.egovframe.cloud.userservice.domain.user.User @@ -191,36 +184,6 @@ public class User extends BaseEntity { return this; } - /** - * 구글 id 등록 - * - * @return User 사용자 엔티티 - */ - public User updateGoogleId(String googleId) { - this.googleId = googleId; - return this; - } - - /** - * 카카오 id 등록 - * - * @return User 사용자 엔티티 - */ - public User updateKakaoId(String kakaoId) { - this.kakaoId = kakaoId; - return this; - } - - /** - * 네이버 id 등록 - * - * @return User 사용자 엔티티 - */ - public User updateNaverId(String naverId) { - this.naverId = naverId; - return this; - } - /** * 소셜 사용자 여부 반환 * @@ -234,6 +197,28 @@ public class User extends BaseEntity { return false; } + /** + * 소셜 정보 설정 + * + * @return User 사용자 엔티티 + */ + public User setSocial(String provider, String providerId) { + switch (provider) { + case "google": + this.googleId = providerId; + break; + case "naver": + this.naverId = providerId; + break; + case "kakao": + this.kakaoId = providerId; + break; + default: + } + + return this; + } + public String getRoleKey() { return this.role.getKey(); } diff --git a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/service/role/AuthorizationService.java b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/service/role/AuthorizationService.java index 6da6342..aa9b6ee 100644 --- a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/service/role/AuthorizationService.java +++ b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/service/role/AuthorizationService.java @@ -1,11 +1,7 @@ package org.egovframe.cloud.userservice.service.role; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -import javax.servlet.http.HttpServletRequest; - +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.egovframe.cloud.common.config.GlobalConstant; import org.egovframe.cloud.common.dto.RequestDto; import org.egovframe.cloud.common.exception.EntityNotFoundException; @@ -28,7 +24,10 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.AntPathMatcher; -import lombok.RequiredArgsConstructor; +import javax.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; /** * org.egovframe.cloud.userservice.service.role.AuthorizationService @@ -50,6 +49,7 @@ import lombok.RequiredArgsConstructor; @Transactional(readOnly = true) @RequiredArgsConstructor @Service +@Slf4j public class AuthorizationService extends AbstractService { /** diff --git a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/service/user/UserService.java b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/service/user/UserService.java index f13280b..3a1d9ef 100644 --- a/backend/user-service/src/main/java/org/egovframe/cloud/userservice/service/user/UserService.java +++ b/backend/user-service/src/main/java/org/egovframe/cloud/userservice/service/user/UserService.java @@ -12,7 +12,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.egovframe.cloud.common.domain.Role; import org.egovframe.cloud.common.dto.RequestDto; +import org.egovframe.cloud.common.exception.BusinessException; import org.egovframe.cloud.common.exception.BusinessMessageException; +import org.egovframe.cloud.common.exception.dto.ErrorCode; import org.egovframe.cloud.common.service.AbstractService; import org.egovframe.cloud.common.util.LogUtil; import org.egovframe.cloud.userservice.api.user.dto.*; @@ -21,6 +23,7 @@ import org.egovframe.cloud.userservice.config.dto.SocialUser; import org.egovframe.cloud.userservice.domain.log.LoginLog; import org.egovframe.cloud.userservice.domain.log.LoginLogRepository; import org.egovframe.cloud.userservice.domain.user.*; +import org.egovframe.cloud.userservice.api.user.dto.SocialUserResponseDto; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -315,7 +318,14 @@ public class UserService extends AbstractService implements UserDetailsService { throw new BusinessMessageException(getMessage("msg.join.email.exists")); } - userRepository.save(requestDto.toEntity(passwordEncoder)); + User user = requestDto.toEntity(passwordEncoder); + + if (requestDto.getProvider() != null && !"".equals(requestDto.getProvider()) && requestDto.getToken() != null && !"".equals(requestDto.getToken())) { + SocialUserResponseDto socialUserResponseDto = getSocialUserInfo(requestDto.getProvider(), requestDto.getToken()); + user.setSocial(requestDto.getProvider(), socialUserResponseDto.getId()); + } + + userRepository.save(user); return true; } @@ -364,12 +374,10 @@ public class UserService extends AbstractService implements UserDetailsService { log.info("end send change password email - emailAddr: " + emailAddr + ", tokenValue: " + tokenValue); } catch (MessagingException e) { - e.printStackTrace(); String errorMessage = getMessage("err.user.find.password"); log.error(errorMessage + ": " + e.getMessage()); throw new BusinessMessageException(errorMessage); } catch (Exception e) { - e.printStackTrace(); String errorMessage = getMessage("err.user.find.password"); log.error(errorMessage + ": " + e.getMessage()); throw new BusinessMessageException(errorMessage); @@ -579,9 +587,9 @@ public class UserService extends AbstractService implements UserDetailsService { */ @Transactional public UserResponseDto loadUserBySocial(UserLoginRequestDto requestDto) { - String[] userInfo = getSocialUserInfo(requestDto.getProvider(), requestDto.getToken()); + /*SocialUserResponseDto socialUserDto = getSocialUserInfo(requestDto.getProvider(), requestDto.getToken()); - UserResponseDto userDto = getAndSaveSocialUser(requestDto.getProvider(), userInfo[0], userInfo[1], userInfo[2]); + UserResponseDto userDto = getAndSaveSocialUser(requestDto.getProvider(), socialUserDto); if (userDto == null) { throw new BusinessMessageException(getMessage("err.user.join.social")); @@ -590,7 +598,29 @@ public class UserService extends AbstractService implements UserDetailsService { throw new BusinessMessageException(getMessage("err.user.state.cantlogin")); } - return userDto; + return userDto;*/ + SocialUserResponseDto socialUserResponseDto = getSocialUserInfo(requestDto.getProvider(), requestDto.getToken()); + + User user = findSocialUser(requestDto.getProvider(), socialUserResponseDto.getId()); + + /*// 이메일이 없는 사용자가 이메일을 직접입력하고 나중에 원래 이메일을 가지고 있는 사용자가 다른 접근할 경우 문제가 생길 수 있음 + if (user == null && socialUserResponseDto.getEmail() != null) { + user = userRepository.findByEmail(socialUserResponseDto.getEmail()).orElse(null); + + // 공급자 id로 조회되지 않지만 이메일로 조회되는 경우 공급자 id 등록 + if (user != null) { + user.setSocial(requestDto.getProvider(), socialUserResponseDto.getId()); + } + }*/ + + if (user == null) { + throw new BusinessException(ErrorCode.REQUIRE_USER_JOIN); + } + if (!UserStateCode.NORMAL.getKey().equals(user.getUserStateCode())) { + throw new BusinessMessageException(getMessage("err.user.state.cantlogin")); + } + + return new UserResponseDto(user); } /** @@ -601,9 +631,9 @@ public class UserService extends AbstractService implements UserDetailsService { * @return User 사용자 엔티티 */ private User findSocialUserByToken(String provider, String token) { - String[] userInfo = getSocialUserInfo(provider, token); + SocialUserResponseDto socialUserResponseDto = getSocialUserInfo(provider, token); - return findSocialUser(provider, userInfo[0]); + return findSocialUser(provider, socialUserResponseDto.getId()); } /** @@ -613,26 +643,26 @@ public class UserService extends AbstractService implements UserDetailsService { * @param token 토큰 * @return String[] 소셜 사용자 정보 */ - private String[] getSocialUserInfo(String provider, String token) { - String[] userInfo = null; + public SocialUserResponseDto getSocialUserInfo(String provider, String token) { + SocialUserResponseDto social = null; switch (provider) { case "google": - userInfo = getGoogleUserInfo(token); + social = getGoogleUserInfo(token); break; case "naver": - userInfo = getNaverUserInfo(token); + social = getNaverUserInfo(token); break; case "kakao": - userInfo = getKakaoUserInfo(token); + social = getKakaoUserInfo(token); break; default: break; } - if (userInfo == null) throw new BusinessMessageException(getMessage("err.user.social.get")); + if (social == null) throw new BusinessMessageException(getMessage("err.user.social.get")); - return userInfo; + return social; } /** @@ -641,7 +671,7 @@ public class UserService extends AbstractService implements UserDetailsService { * @param token 토큰 * @return String[] 구글 사용자 정보 */ - private String[] getGoogleUserInfo(String token) { + private SocialUserResponseDto getGoogleUserInfo(String token) { try { HttpTransport transport = new NetHttpTransport(); GsonFactory gsonFactory = new GsonFactory(); @@ -652,14 +682,18 @@ public class UserService extends AbstractService implements UserDetailsService { GoogleIdToken idToken = verifier.verify(token); - GoogleIdToken.Payload payload = idToken.getPayload(); - log.info("google oauth2: {}", payload.toString()); + if (idToken != null) { + GoogleIdToken.Payload payload = idToken.getPayload(); + log.info("google oauth2: {}", payload.toString()); - return new String[]{ - payload.getSubject(), - payload.getEmail(), - (String) payload.get("name") - }; + return SocialUserResponseDto.builder() + .id(payload.getSubject()) + .email(payload.getEmail()) + .name((String) payload.get("name")) + .build(); + } + + return null; } catch (GeneralSecurityException e) { throw new BusinessMessageException(getMessage("err.user.social.get")); } catch (IOException e) { @@ -675,7 +709,7 @@ public class UserService extends AbstractService implements UserDetailsService { * @param token 토큰 * @return String[] 네이버 사용자 정보 */ - private String[] getNaverUserInfo(String token) { + private SocialUserResponseDto getNaverUserInfo(String token) { HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", "Bearer " + token); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); @@ -688,14 +722,26 @@ public class UserService extends AbstractService implements UserDetailsService { if (response.getBody() != null && !"".equals(response.getBody())) { JsonElement element = JsonParser.parseString(response.getBody()); JsonObject object = element.getAsJsonObject(); - log.info("naver oauth2: {}", object.toString()); + log.info("naver oauth2: {}", object); if (object.get("resultcode") != null && "00".equals(object.get("resultcode").getAsString())) { - return new String[]{ - object.get("response").getAsJsonObject().get("id").getAsString(), - object.get("response").getAsJsonObject().get("email").getAsString(), - object.get("response").getAsJsonObject().get("name").getAsString() - }; + JsonElement responseElement = object.get("response"); + + if (responseElement != null) { + SocialUserResponseDto.SocialUserResponseDtoBuilder builder = SocialUserResponseDto.builder(); + + if (responseElement.getAsJsonObject().get("id") != null && !"".equals(responseElement.getAsJsonObject().get("id").getAsString())) { + builder.id(responseElement.getAsJsonObject().get("id").getAsString()); + } + if (responseElement.getAsJsonObject().get("email") != null && !"".equals(responseElement.getAsJsonObject().get("email").getAsString())) { + builder.email(responseElement.getAsJsonObject().get("email").getAsString()); + } + if (responseElement.getAsJsonObject().get("name") != null && !"".equals(responseElement.getAsJsonObject().get("name").getAsString())) { + builder.name(responseElement.getAsJsonObject().get("name").getAsString()); + } + + return builder.build(); + } } } @@ -708,7 +754,7 @@ public class UserService extends AbstractService implements UserDetailsService { * @param token 토큰 * @return String[] 카카오 사용자 정보 */ - private String[] getKakaoUserInfo(String token) { + private SocialUserResponseDto getKakaoUserInfo(String token) { HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", "Bearer " + token); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); @@ -721,14 +767,26 @@ public class UserService extends AbstractService implements UserDetailsService { if (response.getBody() != null && !"".equals(response.getBody())) { JsonElement element = JsonParser.parseString(response.getBody()); JsonObject object = element.getAsJsonObject(); + JsonElement kakaoAccount = object.get("kakao_account"); log.info("kakao oauth2: {}", object.toString()); - if (object.get("id") != null && !"".equals(object.get("id").getAsString())) { - return new String[]{ - object.get("id").getAsString(), - object.get("kakao_account").getAsJsonObject().get("email").getAsString(), - object.get("kakao_account").getAsJsonObject().get("profile").getAsJsonObject().get("nickname").getAsString() - }; + String id = object.get("id") != null && !"".equals(object.get("id").getAsString()) ? object.get("id").getAsString() : null; + + if (id != null) { + SocialUserResponseDto.SocialUserResponseDtoBuilder builder = SocialUserResponseDto.builder() + .id(id); + + if (kakaoAccount.getAsJsonObject().get("email") != null && !"".equals(kakaoAccount.getAsJsonObject().get("email").getAsString())) { + builder.email(kakaoAccount.getAsJsonObject().get("email").getAsString()); + } + JsonElement profile = kakaoAccount.getAsJsonObject().get("profile"); + if (profile != null) { + if (profile.getAsJsonObject().get("nickname") != null && !"".equals(profile.getAsJsonObject().get("nickname").getAsString())) { + builder.name(profile.getAsJsonObject().get("nickname").getAsString()); + } + } + + return builder.build(); } } @@ -785,19 +843,7 @@ public class UserService extends AbstractService implements UserDetailsService { // 공급자 id로 조회되지 않지만 이메일로 조회되는 경우 공급자 id 등록 if (user != null) { - switch (providerCode) { - case "google": - user = user.updateGoogleId(providerId); - break; - case "kakao": - user = user.updateKakaoId(providerId); - break; - case "naver": - user = user.updateNaverId(providerId); - break; - default: - break; - } + user.setSocial(providerCode, providerId); } } @@ -806,27 +852,15 @@ public class UserService extends AbstractService implements UserDetailsService { final String userId = UUID.randomUUID().toString(); //final String password = makeRandomPassword(); // 임의 비밀번호 생성 시 복호화 불가능 - User.UserBuilder userBuilder = User.builder() + user = User.builder() .email(email) // 100byte //.encryptedPassword(passwordEncoder.encode(password)) // 100 byte .userName(userName) .userId(userId) .role(Role.USER) - .userStateCode(UserStateCode.NORMAL.getKey()); - - switch (providerCode) { - case "google": - user = userBuilder.googleId(providerId).build(); - break; - case "kakao": - user = userBuilder.kakaoId(providerId).build(); - break; - case "naver": - user = userBuilder.naverId(providerId).build(); - break; - default: - break; - } + .userStateCode(UserStateCode.NORMAL.getKey()) + .build(); + user.setSocial(providerCode, providerId); if (user != null) { userRepository.save(user); diff --git a/backend/user-service/src/test/java/org/egovframe/cloud/userservice/api/role/AuthorizationApiControllerTest.java b/backend/user-service/src/test/java/org/egovframe/cloud/userservice/api/role/AuthorizationApiControllerTest.java index 864e1b8..cbf1653 100644 --- a/backend/user-service/src/test/java/org/egovframe/cloud/userservice/api/role/AuthorizationApiControllerTest.java +++ b/backend/user-service/src/test/java/org/egovframe/cloud/userservice/api/role/AuthorizationApiControllerTest.java @@ -1,13 +1,6 @@ package org.egovframe.cloud.userservice.api.role; -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - +import com.fasterxml.jackson.databind.ObjectMapper; import org.egovframe.cloud.userservice.domain.role.Authorization; import org.egovframe.cloud.userservice.domain.role.AuthorizationRepository; import org.egovframe.cloud.userservice.domain.role.RoleAuthorization; @@ -36,7 +29,9 @@ import org.springframework.util.MultiValueMap; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.filter.CharacterEncodingFilter; -import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; /** * org.egovframe.cloud.userservice.api.role.AuthorizationApiControllerTest