From c23d6ffa53bca8215a1e973ed1334efbb27332e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?user=20=EC=9D=B4=EB=A6=84?= Date: Sun, 4 Feb 2024 06:43:18 +0900 Subject: [PATCH 1/5] =?UTF-8?q?YEL-199=20[feat]=20Spring=20Boot=203=20migr?= =?UTF-8?q?ation=20&=20=EC=96=B4=EB=93=9C=EB=AF=BC=20=EA=B3=B5=EC=A7=80=20?= =?UTF-8?q?CRU=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + build.gradle | 34 ++-- src/docs/asciidoc/find-friend-votes-v2.adoc | 2 +- src/docs/asciidoc/find-friend-votes.adoc | 2 +- src/docs/asciidoc/find-friends.adoc | 2 +- src/docs/asciidoc/find-group-friends.adoc | 2 +- src/docs/asciidoc/find-kakao-friends.adoc | 2 +- .../asciidoc/find-onboarding-friends.adoc | 2 +- src/docs/asciidoc/find-votes.adoc | 2 +- src/docs/asciidoc/reissue-token.adoc | 2 - src/docs/asciidoc/search-department.adoc | 2 +- src/docs/asciidoc/search-friend.adoc | 2 +- src/docs/asciidoc/search-high-class.adoc | 2 +- src/docs/asciidoc/search-high-name.adoc | 2 +- src/docs/asciidoc/search-school.adoc | 2 +- src/docs/asciidoc/validate-yelloid.adoc | 2 +- .../admin/controller/AdminController.java | 26 +++ .../dto/request/AdminNoticeCreateRequest.java | 13 ++ .../dto/request/AdminUserDetailRequest.java | 2 +- .../admin/entity/AdminConfiguration.java | 12 +- .../AdminConfigurationTypeConverter.java | 4 +- .../server/domain/admin/entity/UserAdmin.java | 20 +- .../domain/admin/service/AdminService.java | 67 ++++++ .../configuration/SecurityConfiguration.java | 42 ++-- .../controller/AuthController.java | 4 +- .../dto/request/OnBoardingFriendRequest.java | 2 +- .../dto/request/SignUpRequest.java | 4 +- .../CustomAuthenticationEntryPoint.java | 6 +- .../filter/JwtExceptionFilter.java | 8 +- .../authorization/filter/JwtFilter.java | 8 +- .../authorization/service/AuthService.java | 2 +- .../domain/cooldown/entity/Cooldown.java | 23 ++- .../friend/controller/FriendController.java | 2 +- .../server/domain/friend/entity/Friend.java | 24 ++- .../server/domain/group/entity/UserGroup.java | 18 +- .../domain/group/entity/UserGroupData.java | 19 +- .../entity/UserGroupDataTagConterver.java | 4 +- .../group/entity/UserGroupTypeConverter.java | 4 +- .../server/domain/keyword/entity/Keyword.java | 19 +- .../notice/controller/NoticeController.java | 5 +- .../server/domain/notice/entity/Notice.java | 15 +- .../notice/entity/NoticeTypeConverter.java | 4 +- .../notice/repository/NoticeRepository.java | 8 +- .../repository/NoticeRepositoryImpl.java | 55 +++-- .../yello/server/domain/pay/entity/Pay.java | 17 +- .../purchase/entity/GatewayConverter.java | 4 +- .../purchase/entity/ProductTypeConverter.java | 4 +- .../domain/purchase/entity/Purchase.java | 25 ++- .../entity/PurchaseStateConverter.java | 4 +- .../domain/question/entity/Question.java | 24 +-- .../question/entity/QuestionGroupType.java | 18 +- .../domain/user/entity/GenderConverter.java | 4 +- .../domain/user/entity/SocialConverter.java | 4 +- .../user/entity/SubscribeConverter.java | 4 +- .../yello/server/domain/user/entity/User.java | 35 ++-- .../server/domain/user/entity/UserData.java | 23 ++- .../user/entity/UserDataTypeConverter.java | 2 +- .../yello/server/domain/vote/entity/Vote.java | 30 +-- .../domain/vote/entity/VoteTypeConverter.java | 4 +- .../server/global/common/SuccessCode.java | 3 + .../global/common/dto/AuditingTimeEntity.java | 4 +- .../dto/MultiReadHttpServletRequest.java | 10 +- .../global/common/entity/GoogleToken.java | 8 +- .../common/entity/ZonedDateTimeConverter.java | 28 +++ .../configuration/QueryDslConfiguration.java | 4 +- .../exception/ControllerExceptionAdvice.java | 2 +- .../exception/ExceptionHandlerFilter.java | 10 +- .../client/AppleApiWebClient.java | 5 +- .../SlackApplePurchaseNotificationAspect.java | 2 +- .../SlackPurchaseNotificationAspect.java | 2 +- .../aspect/SlackSignUpNotificationAspect.java | 2 +- .../factory/SlackWebhookMessageFactory.java | 17 +- .../resources/static/docs/add-friend.html | 161 +++++++-------- src/main/resources/static/docs/apple.html | 158 +++++++------- .../resources/static/docs/check-keyword.html | 158 +++++++------- .../static/docs/check-user-by-id.html | 158 +++++++------- .../resources/static/docs/check-user-v2.html | 158 +++++++------- .../resources/static/docs/check-user.html | 158 +++++++------- .../static/docs/check-vote-available.html | 158 +++++++------- .../resources/static/docs/create-vote.html | 158 +++++++------- .../resources/static/docs/delete-friend.html | 158 +++++++------- .../resources/static/docs/delete-user-v2.html | 158 +++++++------- .../resources/static/docs/delete-user.html | 158 +++++++------- .../resources/static/docs/device-token.html | 158 +++++++------- src/main/resources/static/docs/edit-user.html | 158 +++++++------- .../static/docs/find-friend-votes-v2.html | 158 +++++++------- .../static/docs/find-friend-votes.html | 158 +++++++------- .../resources/static/docs/find-friends.html | 158 +++++++------- .../static/docs/find-group-friends.html | 158 +++++++------- .../static/docs/find-kakao-friends.html | 158 +++++++------- .../resources/static/docs/find-notice.html | 158 +++++++------- .../static/docs/find-onboarding-friends.html | 158 +++++++------- .../resources/static/docs/find-question.html | 158 +++++++------- src/main/resources/static/docs/find-vote.html | 158 +++++++------- .../resources/static/docs/find-votes.html | 158 +++++++------- .../static/docs/get-unread-vote.html | 158 +++++++------- src/main/resources/static/docs/google.html | 158 +++++++------- src/main/resources/static/docs/index.html | 169 +++++++-------- src/main/resources/static/docs/login.html | 158 +++++++------- src/main/resources/static/docs/overview.html | 158 +++++++------- src/main/resources/static/docs/pay.html | 158 +++++++------- .../resources/static/docs/purchase-check.html | 158 +++++++------- .../resources/static/docs/purchase-info.html | 158 +++++++------- .../resources/static/docs/reissue-token.html | 192 ++++++++---------- .../static/docs/reveal-full-name.html | 158 +++++++------- .../resources/static/docs/reveal-name.html | 158 +++++++------- .../static/docs/search-department.html | 158 +++++++------- .../resources/static/docs/search-friend.html | 158 +++++++------- .../static/docs/search-high-class.html | 158 +++++++------- .../static/docs/search-high-name.html | 158 +++++++------- .../resources/static/docs/search-school.html | 158 +++++++------- .../static/docs/shuffle-friends.html | 158 +++++++------- src/main/resources/static/docs/signup.html | 158 +++++++------- src/main/resources/static/docs/sub-check.html | 158 +++++++------- .../resources/static/docs/user-data-get.html | 158 +++++++------- .../resources/static/docs/user-data-post.html | 158 +++++++------- .../static/docs/validate-yelloid.html | 158 +++++++------- .../medium/AuthControllerTest.java | 14 +- .../friend/medium/FriendControllerTest.java | 10 +- .../domain/notice/FakeNoticeRepository.java | 27 ++- .../purchase/FakeAppleApiWebClient.java | 5 +- .../vote/medium/VoteControllerTest.java | 106 +++++----- 122 files changed, 4150 insertions(+), 3954 deletions(-) create mode 100644 src/main/java/com/yello/server/domain/admin/dto/request/AdminNoticeCreateRequest.java create mode 100644 src/main/java/com/yello/server/global/common/entity/ZonedDateTimeConverter.java diff --git a/.gitignore b/.gitignore index 29c585e5..8ac8c49c 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,6 @@ monitoring/prometheus/volume monitoring/grafana src/main/resources/application-local.yml + +### QueryDSL ### +src/main/generated/ diff --git a/build.gradle b/build.gradle index 267afcb6..67629786 100644 --- a/build.gradle +++ b/build.gradle @@ -6,11 +6,10 @@ buildscript { plugins { id 'java' - id 'org.springframework.boot' version '2.7.4' - id 'io.spring.dependency-management' version '1.0.15.RELEASE' + id 'org.springframework.boot' version '3.2.2' + id 'io.spring.dependency-management' version '1.1.4' id "org.asciidoctor.jvm.convert" version "3.3.2" id 'jacoco' - id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } group = 'com.yello' @@ -39,13 +38,16 @@ repositories { } dependencies { + // Properties Migrator + runtimeOnly "org.springframework.boot:spring-boot-properties-migrator" + implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' // Repositories implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.amqp:spring-rabbit:2.3.12' + implementation 'org.springframework.amqp:spring-rabbit:3.1.1' runtimeOnly 'com.h2database:h2' runtimeOnly 'com.mysql:mysql-connector-j:8.0.31' @@ -85,7 +87,7 @@ dependencies { asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' testImplementation 'org.springframework.security:spring-security-test' - testImplementation 'org.mockito:mockito-inline' + testImplementation 'org.mockito:mockito-inline:5.2.0' // jwt decode implementation 'org.bouncycastle:bcprov-jdk15on:1.69' @@ -97,9 +99,12 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-aop' // querydsl - implementation "com.querydsl:querydsl-jpa:${queryDslVersion}" - implementation "com.querydsl:querydsl-apt:${queryDslVersion}" implementation "com.querydsl:querydsl-core:${queryDslVersion}" + annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}:jakarta" + implementation "com.querydsl:querydsl-jpa:${queryDslVersion}:jakarta" + annotationProcessor "jakarta.persistence:jakarta.persistence-api" + implementation "jakarta.annotation:jakarta.annotation-api" + implementation "com.querydsl:querydsl-codegen:${queryDslVersion}" } asciidoctor { @@ -142,21 +147,6 @@ jacocoTestReport { // finalizedBy 'jacocoTestCoverageVerification' } -// QueryDsl -def querydslDir = "$buildDir/generated/querydsl" - -querydsl { - jpa = true - querydslSourcesDir = querydslDir -} -sourceSets { - main.java.srcDir querydslDir -} - -compileQuerydsl { - options.annotationProcessorPath = configurations.querydsl -} - //jacocoTestCoverageVerification { // violationRules { // rule { diff --git a/src/docs/asciidoc/find-friend-votes-v2.adoc b/src/docs/asciidoc/find-friend-votes-v2.adoc index a201d4e7..c5694126 100644 --- a/src/docs/asciidoc/find-friend-votes-v2.adoc +++ b/src/docs/asciidoc/find-friend-votes-v2.adoc @@ -7,7 +7,7 @@ include::{snippets}/api/v2/vote/friend/http-request.adoc[] === 요청 파라미터 -include::{snippets}/api/v2/vote/friend/request-parameters.adoc[] +include::{snippets}/api/v2/vote/friend/query-parameters.adoc[] === 응답 diff --git a/src/docs/asciidoc/find-friend-votes.adoc b/src/docs/asciidoc/find-friend-votes.adoc index 28379cfd..f964a24b 100644 --- a/src/docs/asciidoc/find-friend-votes.adoc +++ b/src/docs/asciidoc/find-friend-votes.adoc @@ -7,7 +7,7 @@ include::{snippets}/api/v1/vote/findAllFriendVotes/http-request.adoc[] === 요청 파라미터 -include::{snippets}/api/v1/vote/findAllFriendVotes/request-parameters.adoc[] +include::{snippets}/api/v1/vote/findAllFriendVotes/query-parameters.adoc[] === 응답 diff --git a/src/docs/asciidoc/find-friends.adoc b/src/docs/asciidoc/find-friends.adoc index c37ac0d7..6e442a68 100644 --- a/src/docs/asciidoc/find-friends.adoc +++ b/src/docs/asciidoc/find-friends.adoc @@ -7,7 +7,7 @@ include::{snippets}/api/v1/friend/findAllFriend/http-request.adoc[] === 요청 파라미터 -include::{snippets}/api/v1/friend/findAllFriend/request-parameters.adoc[] +include::{snippets}/api/v1/friend/findAllFriend/query-parameters.adoc[] === 응답 diff --git a/src/docs/asciidoc/find-group-friends.adoc b/src/docs/asciidoc/find-group-friends.adoc index 03d9ddce..d7d17e51 100644 --- a/src/docs/asciidoc/find-group-friends.adoc +++ b/src/docs/asciidoc/find-group-friends.adoc @@ -7,7 +7,7 @@ include::{snippets}/api/v1/friend/findAllRecommendSchoolFriends/http-request.ado === 요청 파라미터 -include::{snippets}/api/v1/friend/findAllRecommendSchoolFriends/request-parameters.adoc[] +include::{snippets}/api/v1/friend/findAllRecommendSchoolFriends/query-parameters.adoc[] === 응답 diff --git a/src/docs/asciidoc/find-kakao-friends.adoc b/src/docs/asciidoc/find-kakao-friends.adoc index 21130236..d253f5d3 100644 --- a/src/docs/asciidoc/find-kakao-friends.adoc +++ b/src/docs/asciidoc/find-kakao-friends.adoc @@ -7,7 +7,7 @@ include::{snippets}/api/v1/friend/findAllRecommendKakaoFriends/http-request.adoc === 요청 파라미터 -include::{snippets}/api/v1/friend/findAllRecommendKakaoFriends/request-parameters.adoc[] +include::{snippets}/api/v1/friend/findAllRecommendKakaoFriends/query-parameters.adoc[] === 응답 diff --git a/src/docs/asciidoc/find-onboarding-friends.adoc b/src/docs/asciidoc/find-onboarding-friends.adoc index 3a8c9a8d..92a41136 100644 --- a/src/docs/asciidoc/find-onboarding-friends.adoc +++ b/src/docs/asciidoc/find-onboarding-friends.adoc @@ -7,7 +7,7 @@ include::{snippets}/api/v1/auth/findOnBoardingFriends/http-request.adoc[] === 요청 파라미터 -include::{snippets}/api/v1/auth/findOnBoardingFriends/request-parameters.adoc[] +include::{snippets}/api/v1/auth/findOnBoardingFriends/query-parameters.adoc[] === 응답 diff --git a/src/docs/asciidoc/find-votes.adoc b/src/docs/asciidoc/find-votes.adoc index 3026b251..be1cfc2e 100644 --- a/src/docs/asciidoc/find-votes.adoc +++ b/src/docs/asciidoc/find-votes.adoc @@ -7,7 +7,7 @@ include::{snippets}/api/v1/vote/findAllMyVotes/http-request.adoc[] === 요청 파라미터 -include::{snippets}/api/v1/vote/findAllMyVotes/request-parameters.adoc[] +include::{snippets}/api/v1/vote/findAllMyVotes/query-parameters.adoc[] === 응답 diff --git a/src/docs/asciidoc/reissue-token.adoc b/src/docs/asciidoc/reissue-token.adoc index 2ce80986..6c9edfb3 100644 --- a/src/docs/asciidoc/reissue-token.adoc +++ b/src/docs/asciidoc/reissue-token.adoc @@ -1,8 +1,6 @@ :reproducible: == 토큰 재발급 -operation::api/v1/auth/reIssueToken[snippets='http-request,http-response'] - === 요청 include::{snippets}/api/v1/auth/reIssueToken/http-request.adoc[] diff --git a/src/docs/asciidoc/search-department.adoc b/src/docs/asciidoc/search-department.adoc index 670573f6..5b5864af 100644 --- a/src/docs/asciidoc/search-department.adoc +++ b/src/docs/asciidoc/search-department.adoc @@ -7,7 +7,7 @@ include::{snippets}/api/v1/auth/findAllUnivDepartmentName/http-request.adoc[] === 요청 파라미터 -include::{snippets}/api/v1/auth/findAllUnivDepartmentName/request-parameters.adoc[] +include::{snippets}/api/v1/auth/findAllUnivDepartmentName/query-parameters.adoc[] === 응답 diff --git a/src/docs/asciidoc/search-friend.adoc b/src/docs/asciidoc/search-friend.adoc index 3db6e3ee..e23dce32 100644 --- a/src/docs/asciidoc/search-friend.adoc +++ b/src/docs/asciidoc/search-friend.adoc @@ -7,7 +7,7 @@ include::{snippets}/api/v1/friend/searchFriend/http-request.adoc[] === 요청 파라미터 -include::{snippets}/api/v1/friend/searchFriend/request-parameters.adoc[] +include::{snippets}/api/v1/friend/searchFriend/query-parameters.adoc[] === 응답 diff --git a/src/docs/asciidoc/search-high-class.adoc b/src/docs/asciidoc/search-high-class.adoc index 6f0ce4b4..56bcf491 100644 --- a/src/docs/asciidoc/search-high-class.adoc +++ b/src/docs/asciidoc/search-high-class.adoc @@ -7,7 +7,7 @@ include::{snippets}/api/v1/auth/findGroupIdByName/http-request.adoc[] === 요청 파라미터 -include::{snippets}/api/v1/auth/findGroupIdByName/request-parameters.adoc[] +include::{snippets}/api/v1/auth/findGroupIdByName/query-parameters.adoc[] === 응답 diff --git a/src/docs/asciidoc/search-high-name.adoc b/src/docs/asciidoc/search-high-name.adoc index f82fb744..56d3356f 100644 --- a/src/docs/asciidoc/search-high-name.adoc +++ b/src/docs/asciidoc/search-high-name.adoc @@ -7,7 +7,7 @@ include::{snippets}/api/v1/auth/findAllHighSchoolName/http-request.adoc[] === 요청 파라미터 -include::{snippets}/api/v1/auth/findAllHighSchoolName/request-parameters.adoc[] +include::{snippets}/api/v1/auth/findAllHighSchoolName/query-parameters.adoc[] === 응답 diff --git a/src/docs/asciidoc/search-school.adoc b/src/docs/asciidoc/search-school.adoc index 80452fa7..ae12d1b8 100644 --- a/src/docs/asciidoc/search-school.adoc +++ b/src/docs/asciidoc/search-school.adoc @@ -7,7 +7,7 @@ include::{snippets}/api/v1/auth/findAllUnivName/http-request.adoc[] === 요청 파라미터 -include::{snippets}/api/v1/auth/findAllUnivName/request-parameters.adoc[] +include::{snippets}/api/v1/auth/findAllUnivName/query-parameters.adoc[] === 응답 diff --git a/src/docs/asciidoc/validate-yelloid.adoc b/src/docs/asciidoc/validate-yelloid.adoc index 572c7d30..0de66e04 100644 --- a/src/docs/asciidoc/validate-yelloid.adoc +++ b/src/docs/asciidoc/validate-yelloid.adoc @@ -7,7 +7,7 @@ include::{snippets}/api/v1/auth/getYelloIdValidation/http-request.adoc[] === 요청 파라미터 -include::{snippets}/api/v1/auth/getYelloIdValidation/request-parameters.adoc[] +include::{snippets}/api/v1/auth/getYelloIdValidation/query-parameters.adoc[] === 응답 diff --git a/src/main/java/com/yello/server/domain/admin/controller/AdminController.java b/src/main/java/com/yello/server/domain/admin/controller/AdminController.java index 51bc57c2..214dfb8f 100644 --- a/src/main/java/com/yello/server/domain/admin/controller/AdminController.java +++ b/src/main/java/com/yello/server/domain/admin/controller/AdminController.java @@ -7,6 +7,9 @@ import static com.yello.server.global.common.SuccessCode.DELETE_QUESTION_ADMIN_SUCCESS; import static com.yello.server.global.common.SuccessCode.DELETE_USER_ADMIN_SUCCESS; import static com.yello.server.global.common.SuccessCode.LOGIN_USER_ADMIN_SUCCESS; +import static com.yello.server.global.common.SuccessCode.NOTICE_CREATE_ADMIN_SUCCESS; +import static com.yello.server.global.common.SuccessCode.NOTICE_READ_ADMIN_SUCCESS; +import static com.yello.server.global.common.SuccessCode.NOTICE_UPDATE_DETAIL_ADMIN_SUCCESS; import static com.yello.server.global.common.SuccessCode.READ_COOLDOWN_ADMIN_SUCCESS; import static com.yello.server.global.common.SuccessCode.READ_QUESTION_ADMIN_SUCCESS; import static com.yello.server.global.common.SuccessCode.READ_QUESTION_DETAIL_ADMIN_SUCCESS; @@ -18,6 +21,7 @@ import static com.yello.server.global.common.factory.PaginationFactory.createPageableLimitTen; import com.yello.server.domain.admin.dto.request.AdminLoginRequest; +import com.yello.server.domain.admin.dto.request.AdminNoticeCreateRequest; import com.yello.server.domain.admin.dto.request.AdminQuestionVoteRequest; import com.yello.server.domain.admin.dto.request.AdminUserDetailRequest; import com.yello.server.domain.admin.dto.response.AdminConfigurationResponse; @@ -30,12 +34,14 @@ import com.yello.server.domain.admin.dto.response.AdminUserResponse; import com.yello.server.domain.admin.entity.AdminConfigurationType; import com.yello.server.domain.admin.service.AdminService; +import com.yello.server.domain.notice.entity.Notice; import com.yello.server.domain.user.entity.User; import com.yello.server.global.common.annotation.AccessTokenUser; import com.yello.server.global.common.dto.BaseResponse; import com.yello.server.global.common.dto.EmptyObject; import com.yello.server.infrastructure.firebase.dto.request.NotificationCustomMessage; import com.yello.server.infrastructure.firebase.service.NotificationService; +import java.util.List; import javax.annotation.Nullable; import lombok.RequiredArgsConstructor; import lombok.val; @@ -168,4 +174,24 @@ public BaseResponse postConfigurations( return BaseResponse.success(CONFIGURATION_UPDATE_ADMIN_SUCCESS, data); } + + @GetMapping("/notice") + public BaseResponse> getNotices(@AccessTokenUser User user) { + val data = adminService.getNotices(user.getId()); + return BaseResponse.success(NOTICE_READ_ADMIN_SUCCESS, data); + } + + @PostMapping("/notice") + public BaseResponse createNotice(@AccessTokenUser User user, + @RequestBody AdminNoticeCreateRequest request) { + val data = adminService.createNotice(user.getId(), request); + return BaseResponse.success(NOTICE_CREATE_ADMIN_SUCCESS, data); + } + + @PostMapping("/notice/{id}") + public BaseResponse updateNotice(@AccessTokenUser User user, @PathVariable("id") Long noticeId, + @RequestBody AdminNoticeCreateRequest request) { + val data = adminService.updateNotice(user.getId(), noticeId, request); + return BaseResponse.success(NOTICE_UPDATE_DETAIL_ADMIN_SUCCESS, data); + } } diff --git a/src/main/java/com/yello/server/domain/admin/dto/request/AdminNoticeCreateRequest.java b/src/main/java/com/yello/server/domain/admin/dto/request/AdminNoticeCreateRequest.java new file mode 100644 index 00000000..7ba27af0 --- /dev/null +++ b/src/main/java/com/yello/server/domain/admin/dto/request/AdminNoticeCreateRequest.java @@ -0,0 +1,13 @@ +package com.yello.server.domain.admin.dto.request; + +public record AdminNoticeCreateRequest( + String imageUrl, + String redirectUrl, + String startDate, + String endDate, + Boolean isAvailable, + String tag, + String title +) { + +} diff --git a/src/main/java/com/yello/server/domain/admin/dto/request/AdminUserDetailRequest.java b/src/main/java/com/yello/server/domain/admin/dto/request/AdminUserDetailRequest.java index a985c470..ed743ecd 100644 --- a/src/main/java/com/yello/server/domain/admin/dto/request/AdminUserDetailRequest.java +++ b/src/main/java/com/yello/server/domain/admin/dto/request/AdminUserDetailRequest.java @@ -4,7 +4,7 @@ import com.yello.server.domain.user.entity.Gender; import com.yello.server.domain.user.entity.Social; import com.yello.server.domain.user.entity.Subscribe; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; public record AdminUserDetailRequest( @JsonIgnore Long id, diff --git a/src/main/java/com/yello/server/domain/admin/entity/AdminConfiguration.java b/src/main/java/com/yello/server/domain/admin/entity/AdminConfiguration.java index 8eacd32b..a88c093b 100644 --- a/src/main/java/com/yello/server/domain/admin/entity/AdminConfiguration.java +++ b/src/main/java/com/yello/server/domain/admin/entity/AdminConfiguration.java @@ -1,11 +1,11 @@ package com.yello.server.domain.admin.entity; -import javax.persistence.Column; -import javax.persistence.Convert; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/src/main/java/com/yello/server/domain/admin/entity/AdminConfigurationTypeConverter.java b/src/main/java/com/yello/server/domain/admin/entity/AdminConfigurationTypeConverter.java index 413c65fa..5ff6c3a5 100644 --- a/src/main/java/com/yello/server/domain/admin/entity/AdminConfigurationTypeConverter.java +++ b/src/main/java/com/yello/server/domain/admin/entity/AdminConfigurationTypeConverter.java @@ -1,7 +1,7 @@ package com.yello.server.domain.admin.entity; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import lombok.extern.log4j.Log4j2; @Converter diff --git a/src/main/java/com/yello/server/domain/admin/entity/UserAdmin.java b/src/main/java/com/yello/server/domain/admin/entity/UserAdmin.java index 5119d364..c1f9b3e6 100644 --- a/src/main/java/com/yello/server/domain/admin/entity/UserAdmin.java +++ b/src/main/java/com/yello/server/domain/admin/entity/UserAdmin.java @@ -2,17 +2,20 @@ import com.yello.server.domain.user.entity.User; import com.yello.server.global.common.dto.AuditingTimeEntity; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToOne; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; @Getter @Entity @@ -24,7 +27,8 @@ public class UserAdmin extends AuditingTimeEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne(fetch = FetchType.LAZY) + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "userId") + @OnDelete(action = OnDeleteAction.CASCADE) private User user; } diff --git a/src/main/java/com/yello/server/domain/admin/service/AdminService.java b/src/main/java/com/yello/server/domain/admin/service/AdminService.java index 5c90b776..0ffa2aee 100644 --- a/src/main/java/com/yello/server/domain/admin/service/AdminService.java +++ b/src/main/java/com/yello/server/domain/admin/service/AdminService.java @@ -9,6 +9,7 @@ import static com.yello.server.global.common.ErrorCode.YELLOID_CONFLICT_USER_EXCEPTION; import com.yello.server.domain.admin.dto.request.AdminLoginRequest; +import com.yello.server.domain.admin.dto.request.AdminNoticeCreateRequest; import com.yello.server.domain.admin.dto.request.AdminQuestionVoteRequest; import com.yello.server.domain.admin.dto.request.AdminUserDetailRequest; import com.yello.server.domain.admin.dto.response.AdminConfigurationResponse; @@ -31,6 +32,9 @@ import com.yello.server.domain.authorization.service.AuthManager; import com.yello.server.domain.cooldown.entity.Cooldown; import com.yello.server.domain.cooldown.repository.CooldownRepository; +import com.yello.server.domain.notice.entity.Notice; +import com.yello.server.domain.notice.entity.NoticeType; +import com.yello.server.domain.notice.repository.NoticeRepository; import com.yello.server.domain.question.entity.Question; import com.yello.server.domain.question.repository.QuestionRepository; import com.yello.server.domain.user.entity.Gender; @@ -41,6 +45,8 @@ import com.yello.server.domain.vote.entity.Vote; import com.yello.server.domain.vote.repository.VoteRepository; import com.yello.server.global.common.dto.EmptyObject; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -58,6 +64,7 @@ public class AdminService { private final AdminConfigurationRepository adminConfigurationRepository; private final AuthManager authManager; private final CooldownRepository cooldownRepository; + private final NoticeRepository noticeRepository; private final QuestionRepository questionRepository; private final UserAdminRepository userAdminRepository; private final UserManager userManager; @@ -321,4 +328,64 @@ public EmptyObject updateConfigurations(Long adminId, AdminConfigurationType tag return EmptyObject.builder().build(); } + + public List getNotices(Long adminId) { + // exception + final User admin = userRepository.getById(adminId); + userAdminRepository.getByUser(admin); + + final List noticeList = noticeRepository.findAll(); + + return noticeList; + } + + @Transactional + public EmptyObject createNotice(Long adminId, AdminNoticeCreateRequest request) { + // exception + final User admin = userRepository.getById(adminId); + userAdminRepository.getByUser(admin); + + ZonedDateTime startDate = ZonedDateTime.parse(request.startDate(), DateTimeFormatter.ISO_OFFSET_DATE_TIME); + ZonedDateTime endDate = ZonedDateTime.parse(request.endDate(), DateTimeFormatter.ISO_OFFSET_DATE_TIME); + final NoticeType tag = NoticeType.fromCode(request.tag()); + + final Notice notice = Notice.builder() + .imageUrl(request.imageUrl()) + .redirectUrl(request.redirectUrl()) + .startDate(startDate) + .endDate(endDate) + .isAvailable(true) + .tag(tag) + .title(request.title()) + .build(); + + noticeRepository.save(notice); + + return EmptyObject.builder().build(); + } + + @Transactional + public EmptyObject updateNotice(Long adminId, Long noticeId, AdminNoticeCreateRequest request) { + // exception + final User admin = userRepository.getById(adminId); + userAdminRepository.getByUser(admin); + final Notice notice = noticeRepository.getById(noticeId); + + ZonedDateTime startDate = ZonedDateTime.parse(request.startDate(), DateTimeFormatter.ISO_OFFSET_DATE_TIME); + ZonedDateTime endDate = ZonedDateTime.parse(request.endDate(), DateTimeFormatter.ISO_OFFSET_DATE_TIME); + final NoticeType tag = NoticeType.fromCode(request.tag()); + + noticeRepository.update(Notice.builder() + .id(notice.getId()) + .imageUrl(request.imageUrl()) + .redirectUrl(request.redirectUrl()) + .startDate(startDate) + .endDate(endDate) + .isAvailable(request.isAvailable()) + .tag(tag) + .title(request.title()) + .build()); + + return EmptyObject.builder().build(); + } } diff --git a/src/main/java/com/yello/server/domain/authorization/configuration/SecurityConfiguration.java b/src/main/java/com/yello/server/domain/authorization/configuration/SecurityConfiguration.java index ad06a64a..14bc887d 100644 --- a/src/main/java/com/yello/server/domain/authorization/configuration/SecurityConfiguration.java +++ b/src/main/java/com/yello/server/domain/authorization/configuration/SecurityConfiguration.java @@ -11,7 +11,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @@ -20,32 +20,36 @@ @Configuration @EnableWebSecurity @RequiredArgsConstructor -@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) +@EnableMethodSecurity(securedEnabled = true) public class SecurityConfiguration { private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint; - private final UserRepository userRepository; private final TokenProvider tokenProvider; + private final UserRepository userRepository; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { return httpSecurity - .httpBasic().disable() - .csrf().disable() - .cors() - .and() - .authorizeRequests() - .antMatchers("/api/v1/auth/oauth", "/api/v1/auth/signup").permitAll() - .antMatchers("/api/*").authenticated() - .and() - .sessionManagement() - .sessionCreationPolicy(STATELESS) - .and() - .exceptionHandling() - .authenticationEntryPoint(customAuthenticationEntryPoint) - .and() - .addFilterBefore(new JwtFilter(userRepository), - UsernamePasswordAuthenticationFilter.class) + .httpBasic(httpSecurityHttpBasicConfigurer -> { + httpSecurityHttpBasicConfigurer.disable(); + }) + .csrf(httpSecurityCsrfConfigurer -> { + httpSecurityCsrfConfigurer.disable(); + }) + .cors(httpSecurityCorsConfigurer -> { + httpSecurityCorsConfigurer.disable(); + }) + .authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> { + authorizationManagerRequestMatcherRegistry + .anyRequest().permitAll(); + }) + .sessionManagement(httpSecuritySessionManagementConfigurer -> { + httpSecuritySessionManagementConfigurer.sessionCreationPolicy(STATELESS); + }) + .exceptionHandling(httpSecurityExceptionHandlingConfigurer -> { + httpSecurityExceptionHandlingConfigurer.authenticationEntryPoint(customAuthenticationEntryPoint); + }) + .addFilterBefore(new JwtFilter(userRepository), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(new JwtExceptionFilter(tokenProvider), JwtFilter.class) .addFilterBefore(new ExceptionHandlerFilter(), JwtExceptionFilter.class) .build(); diff --git a/src/main/java/com/yello/server/domain/authorization/controller/AuthController.java b/src/main/java/com/yello/server/domain/authorization/controller/AuthController.java index 93df7e50..f1d68052 100644 --- a/src/main/java/com/yello/server/domain/authorization/controller/AuthController.java +++ b/src/main/java/com/yello/server/domain/authorization/controller/AuthController.java @@ -25,8 +25,8 @@ import com.yello.server.global.common.annotation.ServiceToken; import com.yello.server.global.common.dto.BaseResponse; import com.yello.server.infrastructure.slack.annotation.SlackSignUpNotification; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; import lombok.val; import org.springframework.web.bind.annotation.GetMapping; diff --git a/src/main/java/com/yello/server/domain/authorization/dto/request/OnBoardingFriendRequest.java b/src/main/java/com/yello/server/domain/authorization/dto/request/OnBoardingFriendRequest.java index 1c2bfacc..106d6bc2 100644 --- a/src/main/java/com/yello/server/domain/authorization/dto/request/OnBoardingFriendRequest.java +++ b/src/main/java/com/yello/server/domain/authorization/dto/request/OnBoardingFriendRequest.java @@ -1,7 +1,7 @@ package com.yello.server.domain.authorization.dto.request; +import jakarta.validation.constraints.NotNull; import java.util.List; -import javax.validation.constraints.NotNull; import lombok.Builder; @Builder diff --git a/src/main/java/com/yello/server/domain/authorization/dto/request/SignUpRequest.java b/src/main/java/com/yello/server/domain/authorization/dto/request/SignUpRequest.java index e9dbaaa5..a89088f6 100644 --- a/src/main/java/com/yello/server/domain/authorization/dto/request/SignUpRequest.java +++ b/src/main/java/com/yello/server/domain/authorization/dto/request/SignUpRequest.java @@ -2,9 +2,9 @@ import com.yello.server.domain.user.entity.Gender; import com.yello.server.domain.user.entity.Social; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotNull; import java.util.List; -import javax.validation.constraints.Email; -import javax.validation.constraints.NotNull; import lombok.Builder; @Builder diff --git a/src/main/java/com/yello/server/domain/authorization/exception/CustomAuthenticationEntryPoint.java b/src/main/java/com/yello/server/domain/authorization/exception/CustomAuthenticationEntryPoint.java index 1b2c73b0..3261ab46 100644 --- a/src/main/java/com/yello/server/domain/authorization/exception/CustomAuthenticationEntryPoint.java +++ b/src/main/java/com/yello/server/domain/authorization/exception/CustomAuthenticationEntryPoint.java @@ -5,10 +5,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.yello.server.global.common.dto.BaseResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import lombok.extern.log4j.Log4j2; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; diff --git a/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java b/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java index 6623b08d..a7bc2921 100644 --- a/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java +++ b/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java @@ -16,11 +16,11 @@ import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.MalformedJwtException; import io.jsonwebtoken.security.SignatureException; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import lombok.val; diff --git a/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java b/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java index 04ae15c5..7e7015de 100644 --- a/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java +++ b/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java @@ -2,12 +2,12 @@ import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.repository.UserRepository; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import lombok.val; diff --git a/src/main/java/com/yello/server/domain/authorization/service/AuthService.java b/src/main/java/com/yello/server/domain/authorization/service/AuthService.java index 82bf43bd..cffd8941 100644 --- a/src/main/java/com/yello/server/domain/authorization/service/AuthService.java +++ b/src/main/java/com/yello/server/domain/authorization/service/AuthService.java @@ -38,11 +38,11 @@ import com.yello.server.global.common.manager.ConnectionManager; import com.yello.server.infrastructure.firebase.service.NotificationService; import com.yello.server.infrastructure.rabbitmq.repository.MessageQueueRepository; +import jakarta.validation.constraints.NotNull; import java.time.ZonedDateTime; import java.util.List; import java.util.Objects; import java.util.Optional; -import javax.validation.constraints.NotNull; import lombok.Builder; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; diff --git a/src/main/java/com/yello/server/domain/cooldown/entity/Cooldown.java b/src/main/java/com/yello/server/domain/cooldown/entity/Cooldown.java index 99d87952..6b1a05fc 100644 --- a/src/main/java/com/yello/server/domain/cooldown/entity/Cooldown.java +++ b/src/main/java/com/yello/server/domain/cooldown/entity/Cooldown.java @@ -4,22 +4,24 @@ import static com.yello.server.global.common.util.ConstantUtil.TIMER_TIME; import com.yello.server.domain.user.entity.User; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import java.time.LocalDateTime; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToOne; -import javax.persistence.Table; -import javax.persistence.UniqueConstraint; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; import org.hibernate.annotations.Where; import org.springframework.data.annotation.CreatedDate; @@ -45,6 +47,7 @@ public class Cooldown { @OneToOne(fetch = FetchType.LAZY) @JoinColumn(nullable = false, name = "userId") + @OnDelete(action = OnDeleteAction.CASCADE) private User user; private String messageId; diff --git a/src/main/java/com/yello/server/domain/friend/controller/FriendController.java b/src/main/java/com/yello/server/domain/friend/controller/FriendController.java index 85838714..95d3ddcc 100644 --- a/src/main/java/com/yello/server/domain/friend/controller/FriendController.java +++ b/src/main/java/com/yello/server/domain/friend/controller/FriendController.java @@ -18,8 +18,8 @@ import com.yello.server.global.common.annotation.AccessTokenUser; import com.yello.server.global.common.dto.BaseResponse; import com.yello.server.infrastructure.firebase.service.NotificationService; +import jakarta.validation.Valid; import java.util.List; -import javax.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.val; import org.springframework.web.bind.annotation.DeleteMapping; diff --git a/src/main/java/com/yello/server/domain/friend/entity/Friend.java b/src/main/java/com/yello/server/domain/friend/entity/Friend.java index 51a6b826..75698d95 100644 --- a/src/main/java/com/yello/server/domain/friend/entity/Friend.java +++ b/src/main/java/com/yello/server/domain/friend/entity/Friend.java @@ -2,22 +2,24 @@ import com.yello.server.domain.user.entity.User; import com.yello.server.global.common.dto.AuditingTimeEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import java.time.LocalDateTime; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.Table; -import javax.persistence.UniqueConstraint; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; import org.hibernate.annotations.Where; @Getter @@ -42,10 +44,12 @@ public class Friend extends AuditingTimeEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(nullable = false, name = "user") + @OnDelete(action = OnDeleteAction.CASCADE) private User user; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(nullable = false, name = "target") + @OnDelete(action = OnDeleteAction.CASCADE) private User target; @Column diff --git a/src/main/java/com/yello/server/domain/group/entity/UserGroup.java b/src/main/java/com/yello/server/domain/group/entity/UserGroup.java index e795209b..54edb39b 100644 --- a/src/main/java/com/yello/server/domain/group/entity/UserGroup.java +++ b/src/main/java/com/yello/server/domain/group/entity/UserGroup.java @@ -1,14 +1,14 @@ package com.yello.server.domain.group.entity; -import javax.persistence.Column; -import javax.persistence.Convert; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.Index; -import javax.persistence.Table; -import javax.persistence.UniqueConstraint; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Index; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/src/main/java/com/yello/server/domain/group/entity/UserGroupData.java b/src/main/java/com/yello/server/domain/group/entity/UserGroupData.java index a025ffae..ac4df791 100644 --- a/src/main/java/com/yello/server/domain/group/entity/UserGroupData.java +++ b/src/main/java/com/yello/server/domain/group/entity/UserGroupData.java @@ -1,19 +1,21 @@ package com.yello.server.domain.group.entity; import com.yello.server.global.common.dto.AuditingTimeEntity; -import javax.persistence.Convert; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; @Getter @Entity @@ -28,6 +30,7 @@ public class UserGroupData extends AuditingTimeEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "groupName", referencedColumnName = "groupName") + @OnDelete(action = OnDeleteAction.RESTRICT) private UserGroup group; @Convert(converter = UserGroupDataTagConterver.class) diff --git a/src/main/java/com/yello/server/domain/group/entity/UserGroupDataTagConterver.java b/src/main/java/com/yello/server/domain/group/entity/UserGroupDataTagConterver.java index d8facf03..0086d0c9 100644 --- a/src/main/java/com/yello/server/domain/group/entity/UserGroupDataTagConterver.java +++ b/src/main/java/com/yello/server/domain/group/entity/UserGroupDataTagConterver.java @@ -1,7 +1,7 @@ package com.yello.server.domain.group.entity; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import lombok.extern.log4j.Log4j2; @Converter diff --git a/src/main/java/com/yello/server/domain/group/entity/UserGroupTypeConverter.java b/src/main/java/com/yello/server/domain/group/entity/UserGroupTypeConverter.java index 5382169b..76a24212 100644 --- a/src/main/java/com/yello/server/domain/group/entity/UserGroupTypeConverter.java +++ b/src/main/java/com/yello/server/domain/group/entity/UserGroupTypeConverter.java @@ -1,7 +1,7 @@ package com.yello.server.domain.group.entity; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import lombok.extern.log4j.Log4j2; @Converter diff --git a/src/main/java/com/yello/server/domain/keyword/entity/Keyword.java b/src/main/java/com/yello/server/domain/keyword/entity/Keyword.java index 83941cd4..2014b69d 100644 --- a/src/main/java/com/yello/server/domain/keyword/entity/Keyword.java +++ b/src/main/java/com/yello/server/domain/keyword/entity/Keyword.java @@ -1,19 +1,21 @@ package com.yello.server.domain.keyword.entity; import com.yello.server.domain.question.entity.Question; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; @Getter @Entity @@ -31,6 +33,7 @@ public class Keyword { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "questionId") + @OnDelete(action = OnDeleteAction.RESTRICT) private Question question; public static Keyword of(String keywordName, Question question) { diff --git a/src/main/java/com/yello/server/domain/notice/controller/NoticeController.java b/src/main/java/com/yello/server/domain/notice/controller/NoticeController.java index 5911f6e5..51b9be99 100644 --- a/src/main/java/com/yello/server/domain/notice/controller/NoticeController.java +++ b/src/main/java/com/yello/server/domain/notice/controller/NoticeController.java @@ -1,8 +1,9 @@ package com.yello.server.domain.notice.controller; +import static com.yello.server.global.common.SuccessCode.READ_NOTICE_SUCCESS; + import com.yello.server.domain.notice.dto.NoticeDataResponse; -import com.yello.server.domain.notice.entity.NoticeType; import com.yello.server.domain.notice.service.NoticeService; import com.yello.server.domain.user.entity.User; import com.yello.server.global.common.annotation.AccessTokenUser; @@ -14,8 +15,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import static com.yello.server.global.common.SuccessCode.READ_NOTICE_SUCCESS; - @RestController @RequiredArgsConstructor @RequestMapping("api/v1") diff --git a/src/main/java/com/yello/server/domain/notice/entity/Notice.java b/src/main/java/com/yello/server/domain/notice/entity/Notice.java index 4d6d4103..e70e27ba 100644 --- a/src/main/java/com/yello/server/domain/notice/entity/Notice.java +++ b/src/main/java/com/yello/server/domain/notice/entity/Notice.java @@ -1,13 +1,14 @@ package com.yello.server.domain.notice.entity; import com.yello.server.global.common.dto.AuditingTimeEntity; +import com.yello.server.global.common.entity.ZonedDateTimeConverter; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; import java.time.ZonedDateTime; -import javax.persistence.Column; -import javax.persistence.Convert; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; @@ -32,9 +33,11 @@ public class Notice extends AuditingTimeEntity { private String redirectUrl; @Column(nullable = false) + @Convert(converter = ZonedDateTimeConverter.class) private ZonedDateTime startDate; @Column(nullable = false) + @Convert(converter = ZonedDateTimeConverter.class) private ZonedDateTime endDate; @Column(nullable = false) diff --git a/src/main/java/com/yello/server/domain/notice/entity/NoticeTypeConverter.java b/src/main/java/com/yello/server/domain/notice/entity/NoticeTypeConverter.java index c84cffc1..169b9ea3 100644 --- a/src/main/java/com/yello/server/domain/notice/entity/NoticeTypeConverter.java +++ b/src/main/java/com/yello/server/domain/notice/entity/NoticeTypeConverter.java @@ -1,7 +1,7 @@ package com.yello.server.domain.notice.entity; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import lombok.extern.log4j.Log4j2; @Converter diff --git a/src/main/java/com/yello/server/domain/notice/repository/NoticeRepository.java b/src/main/java/com/yello/server/domain/notice/repository/NoticeRepository.java index b4af79f0..78db8741 100644 --- a/src/main/java/com/yello/server/domain/notice/repository/NoticeRepository.java +++ b/src/main/java/com/yello/server/domain/notice/repository/NoticeRepository.java @@ -2,12 +2,18 @@ import com.yello.server.domain.notice.entity.Notice; import com.yello.server.domain.notice.entity.NoticeType; - +import java.util.List; import java.util.Optional; public interface NoticeRepository { Optional findTopNotice(NoticeType tag); + + List findAll(); + + Notice getById(Long id); + Notice save(Notice notice); + void update(Notice newNotice); } diff --git a/src/main/java/com/yello/server/domain/notice/repository/NoticeRepositoryImpl.java b/src/main/java/com/yello/server/domain/notice/repository/NoticeRepositoryImpl.java index 8185f4ba..fab23ec4 100644 --- a/src/main/java/com/yello/server/domain/notice/repository/NoticeRepositoryImpl.java +++ b/src/main/java/com/yello/server/domain/notice/repository/NoticeRepositoryImpl.java @@ -1,38 +1,51 @@ package com.yello.server.domain.notice.repository; +import static com.yello.server.domain.notice.entity.QNotice.notice; +import static com.yello.server.global.common.ErrorCode.NOT_FOUND_NOTICE_EXCEPTION; + import com.querydsl.jpa.impl.JPAQueryFactory; import com.yello.server.domain.notice.entity.Notice; import com.yello.server.domain.notice.entity.NoticeType; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - +import com.yello.server.domain.notice.exception.NoticeNotFoundException; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.List; import java.util.Optional; - -import static com.yello.server.domain.notice.entity.QNotice.notice; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; @Repository @RequiredArgsConstructor @Transactional(readOnly = true) public class NoticeRepositoryImpl implements NoticeRepository { - private final NoticeJpaRepository noticeJpaRepository; private final JPAQueryFactory jpaQueryFactory; + private final NoticeJpaRepository noticeJpaRepository; @Override public Optional findTopNotice(NoticeType tag) { ZoneId zoneId = ZoneId.of("Asia/Seoul"); ZonedDateTime zonedDateTime = ZonedDateTime.now(zoneId); return Optional.ofNullable(jpaQueryFactory - .selectFrom(notice) - .where(notice.isAvailable.eq(true) - .and(notice.startDate.loe(zonedDateTime)) - .and(notice.endDate.goe(zonedDateTime)) - .and(notice.tag.eq(tag))) - .orderBy(notice.endDate.desc()) - .fetchFirst()); + .selectFrom(notice) + .where(notice.isAvailable.eq(true) + .and(notice.startDate.loe(zonedDateTime)) + .and(notice.endDate.goe(zonedDateTime)) + .and(notice.tag.eq(tag))) + .orderBy(notice.endDate.desc()) + .fetchFirst()); + } + + @Override + public List findAll() { + return jpaQueryFactory.selectFrom(notice).fetch(); + } + + @Override + public Notice getById(Long id) { + return noticeJpaRepository.findById(id) + .orElseThrow(() -> new NoticeNotFoundException(NOT_FOUND_NOTICE_EXCEPTION)); } @Override @@ -40,4 +53,18 @@ public Notice save(Notice notice) { return noticeJpaRepository.save(notice); } + @Override + public void update(Notice newNotice) { + jpaQueryFactory.update(notice) + .set(notice.imageUrl, newNotice.getImageUrl()) + .set(notice.redirectUrl, newNotice.getRedirectUrl()) + .set(notice.startDate, newNotice.getStartDate()) + .set(notice.endDate, newNotice.getEndDate()) + .set(notice.isAvailable, newNotice.getIsAvailable()) + .set(notice.tag, newNotice.getTag()) + .set(notice.title, newNotice.getTitle()) + .where(notice.id.eq(newNotice.getId())) + .execute(); + } + } diff --git a/src/main/java/com/yello/server/domain/pay/entity/Pay.java b/src/main/java/com/yello/server/domain/pay/entity/Pay.java index a1d73a58..47463c7d 100644 --- a/src/main/java/com/yello/server/domain/pay/entity/Pay.java +++ b/src/main/java/com/yello/server/domain/pay/entity/Pay.java @@ -1,18 +1,20 @@ package com.yello.server.domain.pay.entity; import com.yello.server.domain.user.entity.User; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; @Entity @Getter @@ -29,6 +31,7 @@ public class Pay { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "userId") + @OnDelete(action = OnDeleteAction.CASCADE) private User user; public static Pay of(Integer optionIndex, User user) { diff --git a/src/main/java/com/yello/server/domain/purchase/entity/GatewayConverter.java b/src/main/java/com/yello/server/domain/purchase/entity/GatewayConverter.java index 433c11fa..f8dce446 100644 --- a/src/main/java/com/yello/server/domain/purchase/entity/GatewayConverter.java +++ b/src/main/java/com/yello/server/domain/purchase/entity/GatewayConverter.java @@ -1,7 +1,7 @@ package com.yello.server.domain.purchase.entity; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import lombok.extern.log4j.Log4j2; @Converter diff --git a/src/main/java/com/yello/server/domain/purchase/entity/ProductTypeConverter.java b/src/main/java/com/yello/server/domain/purchase/entity/ProductTypeConverter.java index 752fbffa..de21eed2 100644 --- a/src/main/java/com/yello/server/domain/purchase/entity/ProductTypeConverter.java +++ b/src/main/java/com/yello/server/domain/purchase/entity/ProductTypeConverter.java @@ -1,7 +1,7 @@ package com.yello.server.domain.purchase.entity; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import lombok.extern.log4j.Log4j2; @Converter diff --git a/src/main/java/com/yello/server/domain/purchase/entity/Purchase.java b/src/main/java/com/yello/server/domain/purchase/entity/Purchase.java index 356c4a8c..f1741ca1 100644 --- a/src/main/java/com/yello/server/domain/purchase/entity/Purchase.java +++ b/src/main/java/com/yello/server/domain/purchase/entity/Purchase.java @@ -3,23 +3,25 @@ import com.yello.server.domain.user.entity.User; import com.yello.server.global.common.dto.AuditingTimeEntity; import com.yello.server.global.common.util.ConstantUtil; -import javax.persistence.Column; -import javax.persistence.Convert; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.Table; -import javax.persistence.UniqueConstraint; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; @Entity @Getter @@ -53,6 +55,7 @@ public class Purchase extends AuditingTimeEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "userId") + @OnDelete(action = OnDeleteAction.SET_NULL) private User user; @Column(nullable = false) diff --git a/src/main/java/com/yello/server/domain/purchase/entity/PurchaseStateConverter.java b/src/main/java/com/yello/server/domain/purchase/entity/PurchaseStateConverter.java index 35280400..9ae9c6ad 100644 --- a/src/main/java/com/yello/server/domain/purchase/entity/PurchaseStateConverter.java +++ b/src/main/java/com/yello/server/domain/purchase/entity/PurchaseStateConverter.java @@ -1,7 +1,7 @@ package com.yello.server.domain.purchase.entity; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import lombok.extern.log4j.Log4j2; @Converter diff --git a/src/main/java/com/yello/server/domain/question/entity/Question.java b/src/main/java/com/yello/server/domain/question/entity/Question.java index 31556db1..7f0483a6 100644 --- a/src/main/java/com/yello/server/domain/question/entity/Question.java +++ b/src/main/java/com/yello/server/domain/question/entity/Question.java @@ -1,17 +1,17 @@ package com.yello.server.domain.question.entity; import com.yello.server.domain.keyword.entity.Keyword; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.OneToMany; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; @@ -50,7 +50,7 @@ public Question(String nameHead, String nameFoot, String keywordHead, String key private static String deleteBracket(String target) { val slashIndex = target.indexOf('/'); - return slashIndex!=-1 ? target.substring(slashIndex + 1) : target; + return slashIndex != -1 ? target.substring(slashIndex + 1) : target; } public static Question of(String nameHead, String nameFoot, String keywordHead, String keywordFoot) { @@ -68,18 +68,18 @@ public void addKeyword(Keyword keyword) { public String toNotificationSentence() { final String nameFootPart = deleteBracket(this.nameFoot); - final String nameHeadPart = (this.nameHead!=null) ? MessageFormat.format("{0} ", this.nameHead) : ""; - final String keywordHeadPart = (this.keywordHead!=null) ? MessageFormat.format(" {0}", this.keywordHead) : ""; + final String nameHeadPart = (this.nameHead != null) ? MessageFormat.format("{0} ", this.nameHead) : ""; + final String keywordHeadPart = (this.keywordHead != null) ? MessageFormat.format(" {0}", this.keywordHead) : ""; return MessageFormat.format("{0}너{1}{2} ...", nameHeadPart, nameFootPart, keywordHeadPart); } @Override public boolean equals(Object o) { - if (this==o) { + if (this == o) { return true; } - if (o==null || getClass()!=o.getClass()) { + if (o == null || getClass() != o.getClass()) { return false; } Question question = (Question) o; diff --git a/src/main/java/com/yello/server/domain/question/entity/QuestionGroupType.java b/src/main/java/com/yello/server/domain/question/entity/QuestionGroupType.java index c8e003a6..84a3ded4 100644 --- a/src/main/java/com/yello/server/domain/question/entity/QuestionGroupType.java +++ b/src/main/java/com/yello/server/domain/question/entity/QuestionGroupType.java @@ -3,15 +3,15 @@ import com.yello.server.domain.group.entity.UserGroupType; import com.yello.server.domain.group.entity.UserGroupTypeConverter; -import javax.persistence.Column; -import javax.persistence.Convert; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/src/main/java/com/yello/server/domain/user/entity/GenderConverter.java b/src/main/java/com/yello/server/domain/user/entity/GenderConverter.java index 7039df74..95ded004 100644 --- a/src/main/java/com/yello/server/domain/user/entity/GenderConverter.java +++ b/src/main/java/com/yello/server/domain/user/entity/GenderConverter.java @@ -1,7 +1,7 @@ package com.yello.server.domain.user.entity; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import lombok.extern.log4j.Log4j2; @Converter diff --git a/src/main/java/com/yello/server/domain/user/entity/SocialConverter.java b/src/main/java/com/yello/server/domain/user/entity/SocialConverter.java index c03ad1ba..d4d8a65f 100644 --- a/src/main/java/com/yello/server/domain/user/entity/SocialConverter.java +++ b/src/main/java/com/yello/server/domain/user/entity/SocialConverter.java @@ -1,7 +1,7 @@ package com.yello.server.domain.user.entity; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import lombok.extern.log4j.Log4j2; @Converter diff --git a/src/main/java/com/yello/server/domain/user/entity/SubscribeConverter.java b/src/main/java/com/yello/server/domain/user/entity/SubscribeConverter.java index 2a7080dc..7dc12eac 100644 --- a/src/main/java/com/yello/server/domain/user/entity/SubscribeConverter.java +++ b/src/main/java/com/yello/server/domain/user/entity/SubscribeConverter.java @@ -1,7 +1,7 @@ package com.yello.server.domain.user.entity; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import lombok.extern.log4j.Log4j2; @Converter diff --git a/src/main/java/com/yello/server/domain/user/entity/User.java b/src/main/java/com/yello/server/domain/user/entity/User.java index 4bcc7ff4..c9afcfdb 100644 --- a/src/main/java/com/yello/server/domain/user/entity/User.java +++ b/src/main/java/com/yello/server/domain/user/entity/User.java @@ -5,26 +5,28 @@ import com.yello.server.domain.group.entity.UserGroup; import com.yello.server.domain.user.dto.request.UserUpdateRequest; import com.yello.server.global.common.dto.AuditingTimeEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.Email; import java.time.LocalDateTime; import java.util.Objects; -import javax.persistence.Column; -import javax.persistence.Convert; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.Table; -import javax.persistence.UniqueConstraint; -import javax.validation.constraints.Email; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import org.hibernate.annotations.ColumnDefault; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; @Getter @Entity @@ -68,8 +70,8 @@ public class User extends AuditingTimeEntity { private Gender gender; @Column(nullable = false) - @ColumnDefault("200") - private Integer point; + @Builder.Default + private Integer point = 200; @Column(nullable = false) @Convert(converter = SocialConverter.class) @@ -85,6 +87,7 @@ public class User extends AuditingTimeEntity { private LocalDateTime deletedAt; @ManyToOne(fetch = FetchType.LAZY) + @OnDelete(action = OnDeleteAction.RESTRICT) @JoinColumn(name = "groupId") private UserGroup group; @@ -104,9 +107,9 @@ public class User extends AuditingTimeEntity { private String deviceToken; @Column(nullable = false) - @ColumnDefault("normal") @Convert(converter = SubscribeConverter.class) - private Subscribe subscribe; + @Builder.Default + private Subscribe subscribe = Subscribe.NORMAL; public static User of(SignUpRequest signUpRequest, UserGroup group) { return User.builder() diff --git a/src/main/java/com/yello/server/domain/user/entity/UserData.java b/src/main/java/com/yello/server/domain/user/entity/UserData.java index 208f7958..75a3a04c 100644 --- a/src/main/java/com/yello/server/domain/user/entity/UserData.java +++ b/src/main/java/com/yello/server/domain/user/entity/UserData.java @@ -1,25 +1,29 @@ package com.yello.server.domain.user.entity; -import javax.persistence.Column; -import javax.persistence.Convert; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; @Getter @Entity @Builder @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table public class UserData { @Id @@ -27,6 +31,7 @@ public class UserData { private Long id; @ManyToOne(fetch = FetchType.LAZY) + @OnDelete(action = OnDeleteAction.CASCADE) @JoinColumn(name = "userId") private User user; diff --git a/src/main/java/com/yello/server/domain/user/entity/UserDataTypeConverter.java b/src/main/java/com/yello/server/domain/user/entity/UserDataTypeConverter.java index 2931a976..69173534 100644 --- a/src/main/java/com/yello/server/domain/user/entity/UserDataTypeConverter.java +++ b/src/main/java/com/yello/server/domain/user/entity/UserDataTypeConverter.java @@ -1,6 +1,6 @@ package com.yello.server.domain.user.entity; -import javax.persistence.AttributeConverter; +import jakarta.persistence.AttributeConverter; import lombok.extern.slf4j.Slf4j; @Slf4j diff --git a/src/main/java/com/yello/server/domain/vote/entity/Vote.java b/src/main/java/com/yello/server/domain/vote/entity/Vote.java index a8b3b265..fb30b63f 100644 --- a/src/main/java/com/yello/server/domain/vote/entity/Vote.java +++ b/src/main/java/com/yello/server/domain/vote/entity/Vote.java @@ -3,21 +3,24 @@ import com.yello.server.domain.question.entity.Question; import com.yello.server.domain.user.entity.User; import com.yello.server.global.common.dto.AuditingTimeEntity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import lombok.AccessLevel; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; @Entity @Getter @@ -38,23 +41,26 @@ public class Vote extends AuditingTimeEntity { @Column(nullable = false) private Integer nameHint; - @ColumnDefault("false") @Column(nullable = false) - private Boolean isAnswerRevealed; + @Builder.Default + private Boolean isAnswerRevealed = false; - @ColumnDefault("false") @Column(nullable = false) - private Boolean isRead; + @Builder.Default + private Boolean isRead = false; @ManyToOne(fetch = FetchType.LAZY) + @OnDelete(action = OnDeleteAction.SET_NULL) @JoinColumn(name = "senderId") private User sender; @ManyToOne(fetch = FetchType.LAZY) + @OnDelete(action = OnDeleteAction.SET_NULL) @JoinColumn(name = "receiverId") private User receiver; @ManyToOne(fetch = FetchType.LAZY) + @OnDelete(action = OnDeleteAction.RESTRICT) @JoinColumn(name = "questionId") private Question question; diff --git a/src/main/java/com/yello/server/domain/vote/entity/VoteTypeConverter.java b/src/main/java/com/yello/server/domain/vote/entity/VoteTypeConverter.java index f1f9df85..472d350e 100644 --- a/src/main/java/com/yello/server/domain/vote/entity/VoteTypeConverter.java +++ b/src/main/java/com/yello/server/domain/vote/entity/VoteTypeConverter.java @@ -1,7 +1,7 @@ package com.yello.server.domain.vote.entity; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import lombok.extern.log4j.Log4j2; @Converter diff --git a/src/main/java/com/yello/server/global/common/SuccessCode.java b/src/main/java/com/yello/server/global/common/SuccessCode.java index 524ecb24..ba427a61 100644 --- a/src/main/java/com/yello/server/global/common/SuccessCode.java +++ b/src/main/java/com/yello/server/global/common/SuccessCode.java @@ -54,6 +54,9 @@ public enum SuccessCode { READ_NOTICE_SUCCESS(OK, "공지 조회에 성공하였습니다."), CONFIGURATION_READ_ADMIN_SUCCESS(OK, "어드민 권한으로 설정 조회에 성공하였습니다."), CONFIGURATION_UPDATE_ADMIN_SUCCESS(OK, "어드민 권한으로 설정 수정에 성공하였습니다."), + NOTICE_CREATE_ADMIN_SUCCESS(OK, "어드민 권한으로 공지 생성에 성공하였습니다."), + NOTICE_READ_ADMIN_SUCCESS(OK, "어드민 권한으로 공지 조회에 성공하였습니다."), + NOTICE_UPDATE_DETAIL_ADMIN_SUCCESS(OK, "어드민 권한으로 공지 수정에 성공하였습니다."), /** * 201 CREATED diff --git a/src/main/java/com/yello/server/global/common/dto/AuditingTimeEntity.java b/src/main/java/com/yello/server/global/common/dto/AuditingTimeEntity.java index 6fbc28bd..76221f23 100644 --- a/src/main/java/com/yello/server/global/common/dto/AuditingTimeEntity.java +++ b/src/main/java/com/yello/server/global/common/dto/AuditingTimeEntity.java @@ -1,8 +1,8 @@ package com.yello.server.global.common.dto; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; import java.time.LocalDateTime; -import javax.persistence.EntityListeners; -import javax.persistence.MappedSuperclass; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/com/yello/server/global/common/dto/MultiReadHttpServletRequest.java b/src/main/java/com/yello/server/global/common/dto/MultiReadHttpServletRequest.java index 73dd0dc1..be95d707 100644 --- a/src/main/java/com/yello/server/global/common/dto/MultiReadHttpServletRequest.java +++ b/src/main/java/com/yello/server/global/common/dto/MultiReadHttpServletRequest.java @@ -1,5 +1,9 @@ package com.yello.server.global.common.dto; +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -7,10 +11,6 @@ import java.io.InputStreamReader; import java.util.Enumeration; import java.util.Map; -import javax.servlet.ReadListener; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; import org.apache.tomcat.util.http.fileupload.IOUtils; public class MultiReadHttpServletRequest extends HttpServletRequestWrapper { @@ -65,7 +65,7 @@ public String toString() { .append(headers.get(key)) .append("\n"); }); - + return builder.toString(); } diff --git a/src/main/java/com/yello/server/global/common/entity/GoogleToken.java b/src/main/java/com/yello/server/global/common/entity/GoogleToken.java index 28e19cb1..43bf7ce5 100644 --- a/src/main/java/com/yello/server/global/common/entity/GoogleToken.java +++ b/src/main/java/com/yello/server/global/common/entity/GoogleToken.java @@ -1,10 +1,10 @@ package com.yello.server.global.common.entity; import com.yello.server.global.common.dto.AuditingTimeEntity; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/com/yello/server/global/common/entity/ZonedDateTimeConverter.java b/src/main/java/com/yello/server/global/common/entity/ZonedDateTimeConverter.java new file mode 100644 index 00000000..d8b31b86 --- /dev/null +++ b/src/main/java/com/yello/server/global/common/entity/ZonedDateTimeConverter.java @@ -0,0 +1,28 @@ +package com.yello.server.global.common.entity; + +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +@Converter +public class ZonedDateTimeConverter implements AttributeConverter { + + @Override + public String convertToDatabaseColumn(ZonedDateTime zonedDateTime) { + if (zonedDateTime == null) { + return null; + } + + return zonedDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + + @Override + public ZonedDateTime convertToEntityAttribute(String sqlTimestamp) { + if (sqlTimestamp == null) { + return null; + } + + return ZonedDateTime.parse(sqlTimestamp, DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } +} diff --git a/src/main/java/com/yello/server/global/configuration/QueryDslConfiguration.java b/src/main/java/com/yello/server/global/configuration/QueryDslConfiguration.java index fadbf0eb..24cc3417 100644 --- a/src/main/java/com/yello/server/global/configuration/QueryDslConfiguration.java +++ b/src/main/java/com/yello/server/global/configuration/QueryDslConfiguration.java @@ -1,8 +1,8 @@ package com.yello.server.global.configuration; import com.querydsl.jpa.impl.JPAQueryFactory; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/com/yello/server/global/exception/ControllerExceptionAdvice.java b/src/main/java/com/yello/server/global/exception/ControllerExceptionAdvice.java index dc47dd57..1e54d6aa 100644 --- a/src/main/java/com/yello/server/global/exception/ControllerExceptionAdvice.java +++ b/src/main/java/com/yello/server/global/exception/ControllerExceptionAdvice.java @@ -41,7 +41,7 @@ import com.yello.server.domain.vote.exception.VoteNotFoundException; import com.yello.server.global.common.dto.BaseResponse; import com.yello.server.infrastructure.slack.factory.SlackWebhookMessageFactory; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import net.gpedro.integrations.slack.SlackApi; import net.gpedro.integrations.slack.SlackMessage; import org.springframework.beans.factory.annotation.Qualifier; diff --git a/src/main/java/com/yello/server/global/exception/ExceptionHandlerFilter.java b/src/main/java/com/yello/server/global/exception/ExceptionHandlerFilter.java index 66be1ebf..40153f02 100644 --- a/src/main/java/com/yello/server/global/exception/ExceptionHandlerFilter.java +++ b/src/main/java/com/yello/server/global/exception/ExceptionHandlerFilter.java @@ -7,11 +7,11 @@ import com.yello.server.global.common.ErrorCode; import com.yello.server.global.common.dto.BaseResponse; import com.yello.server.global.common.dto.MultiReadHttpServletRequest; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.springframework.web.filter.OncePerRequestFilter; public class ExceptionHandlerFilter extends OncePerRequestFilter { @@ -23,7 +23,7 @@ protected void doFilterInternal( FilterChain filterChain ) throws ServletException, IOException { MultiReadHttpServletRequest multiReadRequest = new MultiReadHttpServletRequest(request); - + try { filterChain.doFilter(multiReadRequest, response); } catch (CustomException exception) { diff --git a/src/main/java/com/yello/server/infrastructure/client/AppleApiWebClient.java b/src/main/java/com/yello/server/infrastructure/client/AppleApiWebClient.java index a3626bbc..766150f8 100644 --- a/src/main/java/com/yello/server/infrastructure/client/AppleApiWebClient.java +++ b/src/main/java/com/yello/server/infrastructure/client/AppleApiWebClient.java @@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClient; @@ -32,9 +33,9 @@ public ResponseEntity appleGetTransaction( ResponseEntity transactionResponse = getTransactionByWebClient(appleTransaction, APPLE_PRODUCTION_URL); - HttpStatus statusCode = transactionResponse.getStatusCode(); + HttpStatusCode statusCode = transactionResponse.getStatusCode(); - if (transactionResponse==null) { + if (transactionResponse == null) { throw new PurchaseException(NOT_FOUND_TRANSACTION_EXCEPTION); } if (statusCode.equals(HttpStatus.NOT_FOUND)) { diff --git a/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackApplePurchaseNotificationAspect.java b/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackApplePurchaseNotificationAspect.java index b7400a90..37b0f487 100644 --- a/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackApplePurchaseNotificationAspect.java +++ b/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackApplePurchaseNotificationAspect.java @@ -1,7 +1,7 @@ package com.yello.server.infrastructure.slack.aspect; import com.yello.server.infrastructure.slack.factory.SlackWebhookMessageFactory; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import net.gpedro.integrations.slack.SlackApi; import net.gpedro.integrations.slack.SlackMessage; import org.aspectj.lang.ProceedingJoinPoint; diff --git a/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackPurchaseNotificationAspect.java b/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackPurchaseNotificationAspect.java index 1a1d9853..f2f60320 100644 --- a/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackPurchaseNotificationAspect.java +++ b/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackPurchaseNotificationAspect.java @@ -1,7 +1,7 @@ package com.yello.server.infrastructure.slack.aspect; import com.yello.server.infrastructure.slack.factory.SlackWebhookMessageFactory; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import net.gpedro.integrations.slack.SlackApi; import net.gpedro.integrations.slack.SlackMessage; import org.aspectj.lang.ProceedingJoinPoint; diff --git a/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackSignUpNotificationAspect.java b/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackSignUpNotificationAspect.java index 03b50b12..e8c31d78 100644 --- a/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackSignUpNotificationAspect.java +++ b/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackSignUpNotificationAspect.java @@ -1,7 +1,7 @@ package com.yello.server.infrastructure.slack.aspect; import com.yello.server.infrastructure.slack.factory.SlackWebhookMessageFactory; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import net.gpedro.integrations.slack.SlackApi; import net.gpedro.integrations.slack.SlackMessage; import org.aspectj.lang.ProceedingJoinPoint; diff --git a/src/main/java/com/yello/server/infrastructure/slack/factory/SlackWebhookMessageFactory.java b/src/main/java/com/yello/server/infrastructure/slack/factory/SlackWebhookMessageFactory.java index 8d164f94..82b19f0c 100644 --- a/src/main/java/com/yello/server/infrastructure/slack/factory/SlackWebhookMessageFactory.java +++ b/src/main/java/com/yello/server/infrastructure/slack/factory/SlackWebhookMessageFactory.java @@ -8,6 +8,7 @@ import com.yello.server.domain.user.repository.UserRepository; import com.yello.server.global.common.factory.TimeFactory; import com.yello.server.infrastructure.slack.dto.response.SlackAppleNotificationResponse; +import jakarta.servlet.http.HttpServletRequest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -17,7 +18,6 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import javax.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import net.gpedro.integrations.slack.SlackAttachment; import net.gpedro.integrations.slack.SlackField; @@ -39,10 +39,9 @@ public class SlackWebhookMessageFactory { private static final String APPLE_PURCHASE_ALARM_TITLE = "애플이 결제 관련 알림을 보냈습니다."; private static final String APPLE_PURCHASE_ALARM_USERNAME = "애플 뱅크 알림"; - - private final UserRepository userRepository; - private final TokenProvider tokenProvider; private final PurchaseManager purchaseManager; + private final TokenProvider tokenProvider; + private final UserRepository userRepository; private static String getRequestBody(HttpServletRequest request) throws IOException { @@ -52,7 +51,7 @@ private static String getRequestBody(HttpServletRequest request) throws IOExcept try { InputStream inputStream = request.getInputStream(); - if (inputStream!=null) { + if (inputStream != null) { bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); char[] charBuffer = new char[128]; int bytesRead = -1; @@ -63,7 +62,7 @@ private static String getRequestBody(HttpServletRequest request) throws IOExcept } catch (IOException ex) { throw ex; } finally { - if (bufferedReader!=null) { + if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException ex) { @@ -173,10 +172,10 @@ private List generateSlackFieldList( HttpServletRequest request ) throws IOException { final String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION); - final String token = authHeader==null ? "null" : authHeader.substring("Bearer ".length()); - final Long userId = authHeader==null ? -1L : tokenProvider.getUserId(token); + final String token = authHeader == null ? "null" : authHeader.substring("Bearer ".length()); + final Long userId = authHeader == null ? -1L : tokenProvider.getUserId(token); final Optional user = - authHeader==null ? Optional.empty() : userRepository.findById(userId); + authHeader == null ? Optional.empty() : userRepository.findById(userId); final String yelloId = user.isPresent() ? user.get().getYelloId() : "null"; final String deviceToken = user.isPresent() ? user.get().getDeviceToken() : "null"; diff --git a/src/main/resources/static/docs/add-friend.html b/src/main/resources/static/docs/add-friend.html index 70ee9041..64bb0f9c 100644 --- a/src/main/resources/static/docs/add-friend.html +++ b/src/main/resources/static/docs/add-friend.html @@ -4,25 +4,23 @@ - + 친구 추가하기 + - - - + + \ No newline at end of file diff --git a/src/main/resources/static/docs/login.html b/src/main/resources/static/docs/login.html index fd84b612..79046842 100644 --- a/src/main/resources/static/docs/login.html +++ b/src/main/resources/static/docs/login.html @@ -4,25 +4,23 @@ - + 소셜 로그인 + + + +
+
+

공지 조회

+
+
+

요청

+
+
+
GET /api/v1/event HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Vary: Origin
+Vary: Access-Control-Request-Method
+Vary: Access-Control-Request-Headers
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "이벤트 전체 조회에 성공하였습니다.",
+  "data" : [ {
+    "tag" : "LUNCH_EVENT",
+    "startDate" : "2024-01-01T00:00:00+09:00",
+    "endDate" : "2024-12-31T00:00:00+09:00",
+    "title" : "점심 시간 깜짝 선물!",
+    "subTitle" : "평일 12-14시 최대 1회까지 참여 가능",
+    "animationList" : [ {
+      "v" : "로티1"
+    }, {
+      "v" : "로티2"
+    } ],
+    "eventReward" : {
+      "startTime" : "12:00+09:00",
+      "endTime" : "14:00+09:00",
+      "rewardCount" : 1,
+      "eventRewardItem" : [ {
+        "tag" : "POINT",
+        "eventRewardTitle" : "최대 200P",
+        "eventRewardImage" : "https://storage.googleapis.com/yelloworld/image/coin-stack.svg",
+        "maxRewardValue" : 200,
+        "minRewardValue" : 10,
+        "eventRewardProbability" : 10,
+        "randomTag" : "FIXED"
+      }, {
+        "tag" : "TICKET",
+        "eventRewardTitle" : "열람권 1개",
+        "eventRewardImage" : "https://storage.googleapis.com/yelloworld/image/key.svg",
+        "maxRewardValue" : 1,
+        "minRewardValue" : 1,
+        "eventRewardProbability" : 90,
+        "randomTag" : "RANDOM"
+      } ]
+    }
+  }, {
+    "tag" : "ADMOB",
+    "startDate" : "2024-01-01T00:00:00+09:00",
+    "endDate" : "2024-12-31T00:00:00+09:00",
+    "title" : "ADMOB 광고입니다.",
+    "subTitle" : "ADMOB 광고는 영구 사용 가능 설정입니다",
+    "animationList" : [ ],
+    "eventReward" : {
+      "startTime" : "00:00+09:00",
+      "endTime" : "23:59:59.000999999+09:00",
+      "rewardCount" : 1,
+      "eventRewardItem" : [ {
+        "tag" : "ADMOB_POINT",
+        "eventRewardTitle" : "광고 보고 포인트 얻기",
+        "eventRewardImage" : "https://storage.googleapis.com/yelloworld/image/coin-stack.svg",
+        "maxRewardValue" : 50,
+        "minRewardValue" : 50,
+        "eventRewardProbability" : 100,
+        "randomTag" : "FIXED"
+      } ]
+    }
+  } ]
+}
+
+
+
+
+
HTTP/1.1 200 OK
+Vary: Origin
+Vary: Access-Control-Request-Method
+Vary: Access-Control-Request-Headers
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "이벤트 전체 조회에 성공하였습니다.",
+  "data" : [ {
+    "tag" : "LUNCH_EVENT",
+    "startDate" : "2024-01-01T00:00:00+09:00",
+    "endDate" : "2024-12-31T00:00:00+09:00",
+    "title" : "점심 시간 깜짝 선물!",
+    "subTitle" : "평일 12-14시 최대 1회까지 참여 가능",
+    "animationList" : [ {
+      "v" : "로티1"
+    }, {
+      "v" : "로티2"
+    } ],
+    "eventReward" : {
+      "startTime" : "22:00+09:00",
+      "endTime" : "00:00+09:00",
+      "rewardCount" : 1,
+      "eventRewardItem" : [ {
+        "tag" : "POINT",
+        "eventRewardTitle" : "최대 200P",
+        "eventRewardImage" : "https://storage.googleapis.com/yelloworld/image/coin-stack.svg",
+        "maxRewardValue" : 200,
+        "minRewardValue" : 10,
+        "eventRewardProbability" : 40,
+        "randomTag" : "FIXED"
+      }, {
+        "tag" : "TICKET",
+        "eventRewardTitle" : "열람권 1개",
+        "eventRewardImage" : "https://storage.googleapis.com/yelloworld/image/key.svg",
+        "maxRewardValue" : 1,
+        "minRewardValue" : 1,
+        "eventRewardProbability" : 60,
+        "randomTag" : "RANDOM"
+      } ]
+    }
+  }, {
+    "tag" : "ADMOB",
+    "startDate" : "2024-01-01T00:00:00+09:00",
+    "endDate" : "2024-12-31T00:00:00+09:00",
+    "title" : "ADMOB 광고입니다.",
+    "subTitle" : "ADMOB 광고는 영구 사용 가능 설정입니다",
+    "animationList" : [ ],
+    "eventReward" : {
+      "startTime" : "00:00+09:00",
+      "endTime" : "23:59:59.000999999+09:00",
+      "rewardCount" : 1,
+      "eventRewardItem" : [ {
+        "tag" : "ADMOB_POINT",
+        "eventRewardTitle" : "광고 보고 포인트 얻기",
+        "eventRewardImage" : "https://storage.googleapis.com/yelloworld/image/coin-stack.svg",
+        "maxRewardValue" : 50,
+        "minRewardValue" : 50,
+        "eventRewardProbability" : 100,
+        "randomTag" : "FIXED"
+      } ]
+    }
+  } ]
+}
+
+
+
+
+
HTTP/1.1 200 OK
+Vary: Origin
+Vary: Access-Control-Request-Method
+Vary: Access-Control-Request-Headers
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "이벤트 전체 조회에 성공하였습니다.",
+  "data" : [ {
+    "tag" : "LUNCH_EVENT",
+    "startDate" : "2024-01-01T00:00:00+09:00",
+    "endDate" : "2024-12-31T00:00:00+09:00",
+    "title" : "점심 시간 깜짝 선물!",
+    "subTitle" : "평일 12-14시 최대 1회까지 참여 가능",
+    "animationList" : [ {
+      "v" : "로티1"
+    }, {
+      "v" : "로티2"
+    } ],
+    "eventReward" : null
+  }, {
+    "tag" : "ADMOB",
+    "startDate" : "2024-01-01T00:00:00+09:00",
+    "endDate" : "2024-12-31T00:00:00+09:00",
+    "title" : "ADMOB 광고입니다.",
+    "subTitle" : "ADMOB 광고는 영구 사용 가능 설정입니다",
+    "animationList" : [ ],
+    "eventReward" : {
+      "startTime" : "00:00+09:00",
+      "endTime" : "23:59:59.000999999+09:00",
+      "rewardCount" : 1,
+      "eventRewardItem" : [ {
+        "tag" : "ADMOB_POINT",
+        "eventRewardTitle" : "광고 보고 포인트 얻기",
+        "eventRewardImage" : "https://storage.googleapis.com/yelloworld/image/coin-stack.svg",
+        "maxRewardValue" : 50,
+        "minRewardValue" : 50,
+        "eventRewardProbability" : 100,
+        "randomTag" : "FIXED"
+      } ]
+    }
+  } ]
+}
+
+
+
+
+

주의

+
+
    +
  • +

    data: Response[]

    +
  • +
  • +

    Response

    +
  • +
  • +

    tag : "LUNCH_EVENT" | "ADMOB"

    +
    +
      +
    • +

      LUNCH_EVENT에 해당하는 *Response*가 없으면 Render 해주지 말아주세요

      +
    • +
    +
    +
  • +
  • +

    startDate : "2024-01-01T00:00:00+09:00"

    +
  • +
  • +

    endDate : "2024-12-31T00:00:00+09:00"

    +
  • +
  • +

    title : "점심 시간 깜짝 선물!"

    +
  • +
  • +

    subTitle : "평일 12-14시 최대 1회까지 참여 가능"

    +
  • +
  • +

    animationList : [{…​json1…​}, {…​json2…​}]

    +
  • +
  • +

    eventReward: EventReward | null

    +
    +
      +
    • +

      해당 필드가 null일 시, 이벤트 보여주지 않도록 해주세요.

      +
    • +
    +
    +
  • +
+
+
+
+

NOTE

+
+
    +
  • +

    ! LUNCH_EVENT에 해당하는 Response가 없거나, LUNCH_EVENT Response의 eventReward가 null이면, 메인화면 접속시, 이벤트 화면을 띄워주지마세요.

    +
  • +
  • +

    이벤트 참여 요청, 이벤트 보상 반환 API 문서 작성중..

    +
  • +
+
+
+
+

CHANGELOG

+
+
    +
  • +

    2024.02.06 릴리즈

    +
  • +
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/index.html b/src/main/resources/static/docs/index.html index 7b0b4229..bd302be3 100644 --- a/src/main/resources/static/docs/index.html +++ b/src/main/resources/static/docs/index.html @@ -456,6 +456,7 @@

YELL:O API 문서

  • Purchase API
  • Pay API
  • Notice API
  • +
  • Event API
  • @@ -544,7 +545,7 @@

    Vote API

    친구 투표 전체 조회하기, 2024-01-09

  • -

    ⬆️ 친구 투표 전체 조회하기 v2, 2024-01-30

    +

    🆕 친구 투표 전체 조회하기 v2, 2024-01-30

  • 읽지 않은 쪽지 개수 조회하기

    @@ -644,6 +645,16 @@

    Notice API

    +
    +

    Event API

    +
    + +
    +
    diff --git a/src/test/java/com/yello/server/domain/event/medium/EventControllerTest.java b/src/test/java/com/yello/server/domain/event/medium/EventControllerTest.java new file mode 100644 index 00000000..ea3f9ef1 --- /dev/null +++ b/src/test/java/com/yello/server/domain/event/medium/EventControllerTest.java @@ -0,0 +1,364 @@ +package com.yello.server.domain.event.medium; + +import static com.yello.server.domain.event.entity.EventRewardRandomType.FIXED; +import static com.yello.server.domain.event.entity.EventRewardRandomType.RANDOM; +import static com.yello.server.domain.event.entity.EventType.ADMOB; +import static com.yello.server.domain.event.entity.EventType.LUNCH_EVENT; +import static com.yello.server.global.common.util.ConstantUtil.GlobalZoneId; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.modifyHeaders; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yello.server.domain.authorization.filter.JwtExceptionFilter; +import com.yello.server.domain.authorization.filter.JwtFilter; +import com.yello.server.domain.event.controller.EventController; +import com.yello.server.domain.event.dto.response.EventResponse; +import com.yello.server.domain.event.entity.Event; +import com.yello.server.domain.event.entity.EventReward; +import com.yello.server.domain.event.entity.EventRewardMapping; +import com.yello.server.domain.event.entity.EventTime; +import com.yello.server.domain.event.service.EventService; +import com.yello.server.global.exception.ControllerExceptionAdvice; +import com.yello.server.util.TestDataEntityUtil; +import com.yello.server.util.TestDataUtil; +import com.yello.server.util.WithAccessTokenUser; +import java.time.OffsetTime; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.http.HttpHeaders; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.operation.preprocess.OperationPreprocessor; +import org.springframework.restdocs.operation.preprocess.Preprocessors; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@AutoConfigureRestDocs +@WebMvcTest( + controllers = { + EventController.class + }, + excludeFilters = { + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtExceptionFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ControllerExceptionAdvice.class) + }) +@WithAccessTokenUser +@DisplayNameGeneration(ReplaceUnderscores.class) +@DisplayName("Event 컨트롤러에서") +class EventControllerTest { + + final OperationPreprocessor[] excludeRequestHeaders = new OperationPreprocessor[]{ + prettyPrint(), + modifyHeaders().remove("X-CSRF-TOKEN"), + modifyHeaders().remove(HttpHeaders.HOST) + }; + + final OperationPreprocessor[] excludeResponseHeaders = new OperationPreprocessor[]{ + prettyPrint(), + modifyHeaders().remove("X-Content-Type-Options"), + modifyHeaders().remove("X-XSS-Protection"), + modifyHeaders().remove("X-Frame-Options"), + modifyHeaders().remove(HttpHeaders.CACHE_CONTROL), + modifyHeaders().remove(HttpHeaders.PRAGMA), + modifyHeaders().remove(HttpHeaders.EXPIRES), + modifyHeaders().remove(HttpHeaders.CONTENT_LENGTH), + }; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private EventService eventService; + + private TestDataUtil testDataUtil = new TestDataEntityUtil(); + + /** + * TODO Event* TestUtil 작성 및 연결 필요 + */ + @Test + void 이벤트_전체_조회에_성공합니다1() throws Exception { + final EventReward ticket = EventReward.builder() + .tag("POINT") + .maxRewardValue(200L) + .minRewardValue(10L) + .title("최대 200P") + .image("https://storage.googleapis.com/yelloworld/image/coin-stack.svg") + .build(); + final EventReward point = EventReward.builder() + .tag("TICKET") + .maxRewardValue(1L) + .minRewardValue(1L) + .title("열람권 1개") + .image("https://storage.googleapis.com/yelloworld/image/key.svg") + .build(); + + final Event lunchEvent = Event.builder() + .tag(LUNCH_EVENT) + .startDate(ZonedDateTime.of(2024, 1, 1, 0, 0, 0, 0, GlobalZoneId)) + .endDate(ZonedDateTime.of(2024, 12, 31, 0, 0, 0, 0, GlobalZoneId)) + .title("점심 시간 깜짝 선물!") + .subTitle("평일 12-14시 최대 1회까지 참여 가능") + .animation("[{\"v\": \"로티1\"},{\"v\": \"로티2\"}]") + .build(); + + final EventTime eventTime1 = EventTime.builder() + .event(lunchEvent) + .rewardCount(1L) + .startTime(OffsetTime.of(12, 0, 0, 0, ZoneOffset.of("+09:00"))) + .endTime(OffsetTime.of(14, 0, 0, 0, ZoneOffset.of("+09:00"))) + .build(); + + final List rewardList1 = List.of( + EventRewardMapping.builder() + .eventTime(eventTime1) + .eventReward(ticket) + .eventRewardProbability(10) + .randomTag(FIXED) + .build(), + EventRewardMapping.builder() + .eventTime(eventTime1) + .eventReward(point) + .eventRewardProbability(90) + .randomTag(RANDOM) + .build() + ); + + final EventReward admobPoint = EventReward.builder() + .tag("ADMOB_POINT") + .maxRewardValue(50L) + .minRewardValue(50L) + .title("광고 보고 포인트 얻기") + .image("https://storage.googleapis.com/yelloworld/image/coin-stack.svg") + .build(); + final Event admobEvent = Event.builder() + .tag(ADMOB) + .startDate(ZonedDateTime.of(2024, 1, 1, 0, 0, 0, 0, GlobalZoneId)) + .endDate(ZonedDateTime.of(2024, 12, 31, 0, 0, 0, 0, GlobalZoneId)) + .title("ADMOB 광고입니다.") + .subTitle("ADMOB 광고는 영구 사용 가능 설정입니다") + .animation("[]") + .build(); + final EventTime eventTime3 = EventTime.builder() + .event(admobEvent) + .rewardCount(1L) + .startTime(OffsetTime.of(0, 0, 0, 0, ZoneOffset.of("+09:00"))) + .endTime(OffsetTime.of(23, 59, 59, 999999, ZoneOffset.of("+09:00"))) + .build(); + final List rewardList3 = List.of( + EventRewardMapping.builder() + .eventTime(eventTime3) + .eventReward(admobPoint) + .eventRewardProbability(100) + .randomTag(FIXED) + .build() + ); + + final EventResponse response1 = EventResponse.of(lunchEvent, eventTime1, rewardList1); + final EventResponse response3 = EventResponse.of(admobEvent, eventTime3, rewardList3); + final List result = List.of(response1, response3); + + given(eventService.getEvents(anyLong())) + .willReturn(result); + + // when + + // then + mockMvc + .perform( + RestDocumentationRequestBuilders + .get("/api/v1/event") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + ) + .andDo(print()) + .andDo(document("api/v1/event/1", + Preprocessors.preprocessRequest(excludeRequestHeaders), + Preprocessors.preprocessResponse(excludeResponseHeaders) + )) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 이벤트_전체_조회에_성공합니다2() throws Exception { + final EventReward ticket = EventReward.builder() + .tag("POINT") + .maxRewardValue(200L) + .minRewardValue(10L) + .title("최대 200P") + .image("https://storage.googleapis.com/yelloworld/image/coin-stack.svg") + .build(); + final EventReward point = EventReward.builder() + .tag("TICKET") + .maxRewardValue(1L) + .minRewardValue(1L) + .title("열람권 1개") + .image("https://storage.googleapis.com/yelloworld/image/key.svg") + .build(); + + final Event lunchEvent = Event.builder() + .tag(LUNCH_EVENT) + .startDate(ZonedDateTime.of(2024, 1, 1, 0, 0, 0, 0, GlobalZoneId)) + .endDate(ZonedDateTime.of(2024, 12, 31, 0, 0, 0, 0, GlobalZoneId)) + .title("점심 시간 깜짝 선물!") + .subTitle("평일 12-14시 최대 1회까지 참여 가능") + .animation("[{\"v\": \"로티1\"},{\"v\": \"로티2\"}]") + .build(); + + final EventTime eventTime2 = EventTime.builder() + .event(lunchEvent) + .rewardCount(1L) + .startTime(OffsetTime.of(22, 0, 0, 0, ZoneOffset.of("+09:00"))) + .endTime(OffsetTime.of(0, 0, 0, 0, ZoneOffset.of("+09:00"))) + .build(); + + final List rewardList2 = List.of( + EventRewardMapping.builder() + .eventTime(eventTime2) + .eventReward(ticket) + .eventRewardProbability(40) + .randomTag(FIXED) + .build(), + EventRewardMapping.builder() + .eventTime(eventTime2) + .eventReward(point) + .eventRewardProbability(60) + .randomTag(RANDOM) + .build() + ); + + final EventReward admobPoint = EventReward.builder() + .tag("ADMOB_POINT") + .maxRewardValue(50L) + .minRewardValue(50L) + .title("광고 보고 포인트 얻기") + .image("https://storage.googleapis.com/yelloworld/image/coin-stack.svg") + .build(); + final Event admobEvent = Event.builder() + .tag(ADMOB) + .startDate(ZonedDateTime.of(2024, 1, 1, 0, 0, 0, 0, GlobalZoneId)) + .endDate(ZonedDateTime.of(2024, 12, 31, 0, 0, 0, 0, GlobalZoneId)) + .title("ADMOB 광고입니다.") + .subTitle("ADMOB 광고는 영구 사용 가능 설정입니다") + .animation("[]") + .build(); + final EventTime eventTime3 = EventTime.builder() + .event(admobEvent) + .rewardCount(1L) + .startTime(OffsetTime.of(0, 0, 0, 0, ZoneOffset.of("+09:00"))) + .endTime(OffsetTime.of(23, 59, 59, 999999, ZoneOffset.of("+09:00"))) + .build(); + final List rewardList3 = List.of( + EventRewardMapping.builder() + .eventTime(eventTime3) + .eventReward(admobPoint) + .eventRewardProbability(100) + .randomTag(FIXED) + .build() + ); + + final EventResponse response2 = EventResponse.of(lunchEvent, eventTime2, rewardList2); + final EventResponse response3 = EventResponse.of(admobEvent, eventTime3, rewardList3); + final List result = List.of(response2, response3); + + given(eventService.getEvents(anyLong())) + .willReturn(result); + + // when + + // then + mockMvc + .perform( + RestDocumentationRequestBuilders + .get("/api/v1/event") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + ) + .andDo(print()) + .andDo(document("api/v1/event/2", + Preprocessors.preprocessRequest(excludeRequestHeaders), + Preprocessors.preprocessResponse(excludeResponseHeaders) + )) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 이벤트_전체_조회에_성공합니다3() throws Exception { + final Event lunchEvent = Event.builder() + .tag(LUNCH_EVENT) + .startDate(ZonedDateTime.of(2024, 1, 1, 0, 0, 0, 0, GlobalZoneId)) + .endDate(ZonedDateTime.of(2024, 12, 31, 0, 0, 0, 0, GlobalZoneId)) + .title("점심 시간 깜짝 선물!") + .subTitle("평일 12-14시 최대 1회까지 참여 가능") + .animation("[{\"v\": \"로티1\"},{\"v\": \"로티2\"}]") + .build(); + + final EventReward admobPoint = EventReward.builder() + .tag("ADMOB_POINT") + .maxRewardValue(50L) + .minRewardValue(50L) + .title("광고 보고 포인트 얻기") + .image("https://storage.googleapis.com/yelloworld/image/coin-stack.svg") + .build(); + final Event admobEvent = Event.builder() + .tag(ADMOB) + .startDate(ZonedDateTime.of(2024, 1, 1, 0, 0, 0, 0, GlobalZoneId)) + .endDate(ZonedDateTime.of(2024, 12, 31, 0, 0, 0, 0, GlobalZoneId)) + .title("ADMOB 광고입니다.") + .subTitle("ADMOB 광고는 영구 사용 가능 설정입니다") + .animation("[]") + .build(); + final EventTime eventTime3 = EventTime.builder() + .event(admobEvent) + .rewardCount(1L) + .startTime(OffsetTime.of(0, 0, 0, 0, ZoneOffset.of("+09:00"))) + .endTime(OffsetTime.of(23, 59, 59, 999999, ZoneOffset.of("+09:00"))) + .build(); + final List rewardList3 = List.of( + EventRewardMapping.builder() + .eventTime(eventTime3) + .eventReward(admobPoint) + .eventRewardProbability(100) + .randomTag(FIXED) + .build() + ); + + final EventResponse response2 = EventResponse.of(lunchEvent, null, null); + final EventResponse response3 = EventResponse.of(admobEvent, eventTime3, rewardList3); + final List result = List.of(response2, response3); + + given(eventService.getEvents(anyLong())) + .willReturn(result); + + // when + + // then + mockMvc + .perform( + RestDocumentationRequestBuilders + .get("/api/v1/event") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + ) + .andDo(print()) + .andDo(document("api/v1/event/3", + Preprocessors.preprocessRequest(excludeRequestHeaders), + Preprocessors.preprocessResponse(excludeResponseHeaders) + )) + .andExpect(MockMvcResultMatchers.status().isOk()); + } +}