From b93b06ba7040c7a6fd9a45855b2f9a53e9a3d7f4 Mon Sep 17 00:00:00 2001 From: gosu Date: Tue, 11 Jun 2024 16:52:35 +0900 Subject: [PATCH 01/10] =?UTF-8?q?feat=20:=20Exhibit=20=EB=8F=99=EC=A0=81?= =?UTF-8?q?=20=EC=BF=BC=EB=A6=AC=EB=A5=BC=20=ED=86=B5=ED=95=9C=20=ED=83=80?= =?UTF-8?q?=EC=9D=B4=ED=8B=80=20=EA=B2=80=EC=83=89=EC=96=B4=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=EB=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jolvre/exhibition/dao/ExhibitDao.java | 35 --------- .../jolvre/exhibition/dto/ExhibitDTO.java | 31 +++++++- .../repository/ExhibitQueryDslRepository.java | 78 +++++++++++++++++++ .../exhibition/service/ExhibitService.java | 11 +-- 4 files changed, 112 insertions(+), 43 deletions(-) delete mode 100644 src/main/java/com/example/jolvre/exhibition/dao/ExhibitDao.java create mode 100644 src/main/java/com/example/jolvre/exhibition/repository/ExhibitQueryDslRepository.java diff --git a/src/main/java/com/example/jolvre/exhibition/dao/ExhibitDao.java b/src/main/java/com/example/jolvre/exhibition/dao/ExhibitDao.java deleted file mode 100644 index ea53c2d..0000000 --- a/src/main/java/com/example/jolvre/exhibition/dao/ExhibitDao.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.example.jolvre.exhibition.dao; - -import static com.example.jolvre.exhibition.entity.QExhibit.exhibit; - -import com.example.jolvre.exhibition.entity.Exhibit; -import com.example.jolvre.user.entity.QUser; -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.jpa.impl.JPAQueryFactory; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Repository; - -@RequiredArgsConstructor -@Repository -public class ExhibitDao { - private final JPAQueryFactory queryFactory; - - public List findAllByFilter(boolean distribute, String title) { - return queryFactory - .selectFrom(exhibit) - .where(exhibit.distribute.eq(distribute), eqTitle(title)) - .leftJoin(exhibit.user, QUser.user) - .fetchJoin() - .orderBy(exhibit.id.asc()) - .fetch(); - } - - private BooleanExpression eqTitle(String title) { - if (title == null || title.isBlank()) { - return null; - } - - return exhibit.title.contains(title); - } -} diff --git a/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java b/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java index 8b3f5d5..c10ade2 100644 --- a/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java +++ b/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java @@ -4,11 +4,13 @@ import com.example.jolvre.exhibition.entity.Exhibit; import com.example.jolvre.exhibition.entity.ExhibitComment; import com.example.jolvre.user.dto.UserDTO.UserInfoResponse; +import com.querydsl.core.annotations.QueryProjection; import java.util.ArrayList; import java.util.List; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.extern.jackson.Jacksonized; import org.springframework.web.multipart.MultipartFile; @@ -60,8 +62,8 @@ public static class ExhibitUploadRequest { } @Builder - @AllArgsConstructor @Getter + @NoArgsConstructor public static class ExhibitInfoResponse { private Long id; private String title; @@ -82,6 +84,33 @@ public static class ExhibitInfoResponse { private UserInfoResponse userInfoResponse; private DiaryInfoResponses diaryInfoResponses; + @QueryProjection + public ExhibitInfoResponse(Long id, String title, String authorWord, String introduction, String size, + String productionMethod, int price, boolean forSale, String thumbnail, + List imagesUrl, String image3d, boolean distribute, + boolean checkVirtualSpace, + String workType, String background2dImage, String background3dImage, + UserInfoResponse userInfoResponse, DiaryInfoResponses diaryInfoResponses) { + this.id = id; + this.title = title; + this.authorWord = authorWord; + this.introduction = introduction; + this.size = size; + this.productionMethod = productionMethod; + this.price = price; + this.forSale = forSale; + this.thumbnail = thumbnail; + this.imagesUrl = imagesUrl; + this.image3d = image3d; + this.distribute = distribute; + this.checkVirtualSpace = checkVirtualSpace; + this.workType = workType; + this.background2dImage = background2dImage; + this.background3dImage = background3dImage; + this.userInfoResponse = userInfoResponse; + this.diaryInfoResponses = diaryInfoResponses; + } + public static ExhibitInfoResponse toDTO(Exhibit exhibit) { return new ExhibitInfoResponse(exhibit.getId(), exhibit.getTitle(), exhibit.getAuthorWord(), exhibit.getIntroduction(), diff --git a/src/main/java/com/example/jolvre/exhibition/repository/ExhibitQueryDslRepository.java b/src/main/java/com/example/jolvre/exhibition/repository/ExhibitQueryDslRepository.java new file mode 100644 index 0000000..1e3ec32 --- /dev/null +++ b/src/main/java/com/example/jolvre/exhibition/repository/ExhibitQueryDslRepository.java @@ -0,0 +1,78 @@ +package com.example.jolvre.exhibition.repository; + +import static com.example.jolvre.exhibition.entity.QDiary.diary; +import static com.example.jolvre.exhibition.entity.QExhibit.exhibit; +import static com.example.jolvre.exhibition.entity.QExhibitImage.exhibitImage; +import static com.example.jolvre.user.entity.QUser.user; + +import com.example.jolvre.exhibition.dto.ExhibitDTO.ExhibitInfoResponse; +import com.example.jolvre.exhibition.entity.Exhibit; +import com.example.jolvre.exhibition.entity.QExhibit; +import com.example.jolvre.user.entity.User; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQuery; +import com.querydsl.jpa.impl.JPAQueryFactory; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.support.PageableExecutionUtils; +import org.springframework.stereotype.Repository; + +@RequiredArgsConstructor +@Repository +public class ExhibitQueryDslRepository { + private final JPAQueryFactory queryFactory; + + public List findAllByFilter(boolean distribute, String title) { + return queryFactory + .selectFrom(exhibit) + .where(exhibit.distribute.eq(distribute), containTitle(title)) + .orderBy(exhibit.id.asc()) + .fetch(); + } + + public Page findAllByFilter(boolean distribute, String title, Pageable pageable) { + List exhibits = queryFactory + .select(Projections.constructor(ExhibitInfoResponse.class + , QExhibit.exhibit.id + , QExhibit.exhibit.title + , QExhibit.exhibit.thumbnail + )) + .leftJoin(exhibit.user, user) + .fetchJoin() + .leftJoin(exhibit.exhibitImages, exhibitImage) + .leftJoin(exhibit.diaries, diary) + .where(QExhibit.exhibit.distribute.eq(distribute), containTitle(title)) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + + JPAQuery count = queryFactory.select(exhibit.count()) + .from(exhibit) + .leftJoin(exhibit.user, user) + .fetchJoin() + .leftJoin(exhibit.exhibitImages, exhibitImage) + .leftJoin(exhibit.diaries, diary) + .where(exhibit.distribute.eq(distribute), containTitle(title)); + + return PageableExecutionUtils.getPage(exhibits, pageable, count::fetchOne); + } + + private BooleanExpression containTitle(String title) { + if (title == null || title.isBlank()) { + return null; + } + + return exhibit.title.contains(title); + } + + private BooleanExpression eqUser(User user) { + if (user == null) { + return null; + } + + return exhibit.user.eq(user); + } +} diff --git a/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java b/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java index 6a5b40c..15e2ff7 100644 --- a/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java +++ b/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java @@ -2,7 +2,6 @@ import com.example.jolvre.common.error.exhibition.ExhibitNotFoundException; import com.example.jolvre.common.service.S3Service; -import com.example.jolvre.exhibition.dao.ExhibitDao; import com.example.jolvre.exhibition.dto.ExhibitDTO.ExhibitInfoResponse; import com.example.jolvre.exhibition.dto.ExhibitDTO.ExhibitInfoResponses; import com.example.jolvre.exhibition.dto.ExhibitDTO.ExhibitInvitationResponse; @@ -14,6 +13,7 @@ import com.example.jolvre.exhibition.repository.DiaryRepository; import com.example.jolvre.exhibition.repository.ExhibitCommentRepository; import com.example.jolvre.exhibition.repository.ExhibitImageRepository; +import com.example.jolvre.exhibition.repository.ExhibitQueryDslRepository; import com.example.jolvre.exhibition.repository.ExhibitRepository; import com.example.jolvre.user.entity.User; import com.example.jolvre.user.service.UserService; @@ -39,9 +39,9 @@ public class ExhibitService { private final DiaryRepository diaryRepository; private final ExhibitCommentRepository exhibitCommentRepository; private final WebClient webClient; - private final ExhibitDao exhibitDao; + private final ExhibitQueryDslRepository exhibitQueryDslRepository; - @Transactional + @Transactional //todo : 모델서버 api가 구현되면 비동기 구현 public ExhibitUploadResponse uploadExhibit(ExhibitUploadRequest request, Long userId) { User loginUser = userService.getUserById(userId); @@ -79,7 +79,6 @@ public ExhibitUploadResponse uploadExhibit(ExhibitUploadRequest request, Long us log.info("[EXHIBITION] : {}님의 {} 업로드 성공", loginUser.getNickname(), exhibit.getTitle()); return ExhibitUploadResponse.builder().exhibitId(save.getId()).build(); - } @Transactional @@ -91,9 +90,8 @@ public ExhibitInfoResponse getExhibitInfo(Long id) { @Transactional // 배포 설정한 전시만 조회 public ExhibitInfoResponses getAllExhibitInfo() { - return ExhibitInfoResponses.builder() - .exhibitResponses(exhibitRepository.findAllByDistribute(true).stream().map( + .exhibitResponses(exhibitQueryDslRepository.findAllByFilter(true, null).stream().map( ExhibitInfoResponse::toDTO ).collect(Collectors.toList())) .build(); @@ -101,7 +99,6 @@ public ExhibitInfoResponses getAllExhibitInfo() { @Transactional public ExhibitInfoResponses getAllUserExhibitInfo(Long userId) { - User user = userService.getUserById(userId); return ExhibitInfoResponses.builder() From 5cf59cc08fc66dbdd937b6dc744db4e07f14b9f8 Mon Sep 17 00:00:00 2001 From: gosu Date: Tue, 11 Jun 2024 21:29:43 +0900 Subject: [PATCH 02/10] =?UTF-8?q?test=20:=20GroupExhibitService=20Test=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../auth/email/service/MailService.java | 4 +- .../common/firebase/DTO/FCMMessage.java | 56 ++--- .../common/firebase/Entity/UserFcmToken.java | 74 +++---- .../Repository/UserFcmTokenRepository.java | 22 +- .../common/firebase/Service/FCMService.java | 180 ++++++++-------- .../common/firebase/api/FCMController.java | 66 +++--- .../exhibition/service/ExhibitService.java | 7 +- .../group/repository/MemberRepository.java | 3 + .../group/service/GroupExhibitService.java | 17 +- .../jolvre/post/service/CommentService.java | 14 +- .../com/example/jolvre/user/entity/User.java | 6 - .../jolvre/user/service/UserService.java | 3 +- .../java/service/auth/SignUpServiceTest.java | 6 +- .../service/exhibit/DiaryServiceTest.java | 109 ---------- .../service/exhibit/ExhibitServiceTest.java | 192 +++++++++--------- .../service/group/GroupInviteServiceTest.java | 157 -------------- .../service/group/GroupRoleCheckerTest.java | 4 + .../java/service/user/UserServiceTest.java | 34 +++- 19 files changed, 359 insertions(+), 597 deletions(-) delete mode 100644 src/test/java/service/exhibit/DiaryServiceTest.java delete mode 100644 src/test/java/service/group/GroupInviteServiceTest.java create mode 100644 src/test/java/service/group/GroupRoleCheckerTest.java diff --git a/build.gradle b/build.gradle index b557544..e2e6368 100644 --- a/build.gradle +++ b/build.gradle @@ -64,7 +64,7 @@ dependencies { //firebase implementation 'com.google.firebase:firebase-admin:6.8.1' //okhttp - implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.2.2' + implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.2.0' //Query Dsl implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' diff --git a/src/main/java/com/example/jolvre/auth/email/service/MailService.java b/src/main/java/com/example/jolvre/auth/email/service/MailService.java index d76e2ba..fa00849 100644 --- a/src/main/java/com/example/jolvre/auth/email/service/MailService.java +++ b/src/main/java/com/example/jolvre/auth/email/service/MailService.java @@ -1,7 +1,6 @@ package com.example.jolvre.auth.email.service; import com.example.jolvre.common.util.RedisUtil; -import com.example.jolvre.user.repository.UserRepository; import jakarta.mail.MessagingException; import jakarta.mail.internet.MimeMessage; import java.util.Random; @@ -17,10 +16,9 @@ public class MailService { private final JavaMailSender mailSender; private int authNumber; private final RedisUtil redisUtil; - private final UserRepository userRepository; //임의의 6자리 양수를 반환합니다. - public void makeRandomNumber() { + private void makeRandomNumber() { Random r = new Random(); String randomNumber = ""; for (int i = 0; i < 6; i++) { diff --git a/src/main/java/com/example/jolvre/common/firebase/DTO/FCMMessage.java b/src/main/java/com/example/jolvre/common/firebase/DTO/FCMMessage.java index 98118e7..5da9810 100644 --- a/src/main/java/com/example/jolvre/common/firebase/DTO/FCMMessage.java +++ b/src/main/java/com/example/jolvre/common/firebase/DTO/FCMMessage.java @@ -1,28 +1,28 @@ -package com.example.jolvre.common.firebase.DTO; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; - -@Builder -@AllArgsConstructor -@Getter -public class FCMMessage { - private boolean validate_only; - private Message message; - - @Builder - @AllArgsConstructor - @Getter - public static class Message { - private Notification notification; - private String token; - } - - @Builder - @AllArgsConstructor - @Getter - public static class Notification { - private String title; - private String body; - } -} +//package com.example.jolvre.common.firebase.DTO; +//import lombok.AllArgsConstructor; +//import lombok.Builder; +//import lombok.Getter; +// +//@Builder +//@AllArgsConstructor +//@Getter +//public class FCMMessage { +// private boolean validate_only; +// private Message message; +// +// @Builder +// @AllArgsConstructor +// @Getter +// public static class Message { +// private Notification notification; +// private String token; +// } +// +// @Builder +// @AllArgsConstructor +// @Getter +// public static class Notification { +// private String title; +// private String body; +// } +//} diff --git a/src/main/java/com/example/jolvre/common/firebase/Entity/UserFcmToken.java b/src/main/java/com/example/jolvre/common/firebase/Entity/UserFcmToken.java index 1ddabad..1d18106 100644 --- a/src/main/java/com/example/jolvre/common/firebase/Entity/UserFcmToken.java +++ b/src/main/java/com/example/jolvre/common/firebase/Entity/UserFcmToken.java @@ -1,37 +1,37 @@ -package com.example.jolvre.common.firebase.Entity; - -import com.example.jolvre.user.entity.User; -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.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Entity -@Getter -@Setter -@NoArgsConstructor -public class UserFcmToken { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long userFcmTokenId; - - @OneToOne(fetch = FetchType.EAGER) - @JoinColumn(name = "user_id") - private User user; - - private String token; - - @Builder - public UserFcmToken(String token, User user) { - this.token = token; - this.user = user; - } -} +//package com.example.jolvre.common.firebase.Entity; +// +//import com.example.jolvre.user.entity.User; +//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.Builder; +//import lombok.Getter; +//import lombok.NoArgsConstructor; +//import lombok.Setter; +// +//@Entity +//@Getter +//@Setter +//@NoArgsConstructor +//public class UserFcmToken { +// +// @Id +// @GeneratedValue(strategy = GenerationType.IDENTITY) +// private Long userFcmTokenId; +// +// @OneToOne(fetch = FetchType.EAGER) +// @JoinColumn(name = "user_id") +// private User user; +// +// private String token; +// +// @Builder +// public UserFcmToken(String token, User user) { +// this.token = token; +// this.user = user; +// } +//} diff --git a/src/main/java/com/example/jolvre/common/firebase/Repository/UserFcmTokenRepository.java b/src/main/java/com/example/jolvre/common/firebase/Repository/UserFcmTokenRepository.java index 9132db1..3818485 100644 --- a/src/main/java/com/example/jolvre/common/firebase/Repository/UserFcmTokenRepository.java +++ b/src/main/java/com/example/jolvre/common/firebase/Repository/UserFcmTokenRepository.java @@ -1,11 +1,11 @@ -package com.example.jolvre.common.firebase.Repository; -import com.example.jolvre.common.firebase.Entity.UserFcmToken; -import com.example.jolvre.user.entity.User; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface UserFcmTokenRepository extends JpaRepository { - Optional findByUser(User user); - boolean existsByUser(User user); -} \ No newline at end of file +//package com.example.jolvre.common.firebase.Repository; +//import com.example.jolvre.common.firebase.Entity.UserFcmToken; +//import com.example.jolvre.user.entity.User; +//import org.springframework.data.jpa.repository.JpaRepository; +// +//import java.util.Optional; +// +//public interface UserFcmTokenRepository extends JpaRepository { +// Optional findByUser(User user); +// boolean existsByUser(User user); +//} \ No newline at end of file diff --git a/src/main/java/com/example/jolvre/common/firebase/Service/FCMService.java b/src/main/java/com/example/jolvre/common/firebase/Service/FCMService.java index 1a1c35b..a51e302 100644 --- a/src/main/java/com/example/jolvre/common/firebase/Service/FCMService.java +++ b/src/main/java/com/example/jolvre/common/firebase/Service/FCMService.java @@ -1,90 +1,90 @@ -package com.example.jolvre.common.firebase.Service; -import com.example.jolvre.common.error.user.UserNotFoundException; -import com.example.jolvre.common.firebase.DTO.FCMMessage; -import com.example.jolvre.common.firebase.Entity.UserFcmToken; -import com.example.jolvre.common.firebase.Repository.UserFcmTokenRepository; -import com.example.jolvre.user.entity.User; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.auth.oauth2.GoogleCredentials; -import com.google.common.net.HttpHeaders; -import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import okhttp3.*; -import org.springframework.core.io.ClassPathResource; -import org.springframework.stereotype.Service; - -import java.io.IOException; -import java.util.List; - -@Service -@RequiredArgsConstructor -@Slf4j -public class FCMService { - - private final UserFcmTokenRepository userFcmTokenRepository; - private final String API_URL = "https://fcm.googleapis.com/v1/projects/jolvre-cdfe2/messages:send"; - private final ObjectMapper objectMapper; - - @Transactional - public void saveUerFcmToken(String token, User user) { - UserFcmToken userFcmToken = UserFcmToken.builder() - .token(token) - .user(user) - .build(); - - userFcmTokenRepository.save(userFcmToken); - } - - public void sendMessageTo(String targetToken, String title, String body) throws IOException { - String message = makeMessage(targetToken, title, body); - - OkHttpClient client = new OkHttpClient(); - RequestBody requestBody = RequestBody.create(message, MediaType.get("application/json; charset=utf-8")); - - Request request = new Request.Builder() - .url(API_URL) - .post(requestBody) - .addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + getAccessToken()) - .addHeader(HttpHeaders.CONTENT_TYPE, "application/json; UTF-8") - .build(); - - Response response = client.newCall(request).execute(); - - log.info(response.body().string()); - } - - public String getTargetToken(User user) { - UserFcmToken UserFcmToken = userFcmTokenRepository.findByUser(user) - .orElseThrow(UserNotFoundException::new); - return UserFcmToken.getToken(); - } - - public String getAccessToken() throws IOException { - String firebaseConfigPath = "jolvre-cdfe2-418a2fdc3ed8.json"; - GoogleCredentials googleCredentials = GoogleCredentials - .fromStream(new ClassPathResource(firebaseConfigPath).getInputStream()) - .createScoped(List.of("https://www.googleapis.com/auth/cloud-platform")); - - googleCredentials.refreshIfExpired(); - return googleCredentials.getAccessToken().getTokenValue(); - } - - private String makeMessage(String targetToken, String title, String body) throws JsonProcessingException { - FCMMessage fcmMessage = FCMMessage.builder() - .message(FCMMessage.Message.builder() - .token(targetToken) - .notification(FCMMessage.Notification.builder() - .title(title) - .body(body) - .build() - ) - .build() - ) - .validate_only(false) - .build(); - - return objectMapper.writeValueAsString(fcmMessage); - } -} \ No newline at end of file +//package com.example.jolvre.common.firebase.Service; +//import com.example.jolvre.common.error.user.UserNotFoundException; +//import com.example.jolvre.common.firebase.DTO.FCMMessage; +//import com.example.jolvre.common.firebase.Entity.UserFcmToken; +//import com.example.jolvre.common.firebase.Repository.UserFcmTokenRepository; +//import com.example.jolvre.user.entity.User; +//import com.fasterxml.jackson.core.JsonProcessingException; +//import com.fasterxml.jackson.databind.ObjectMapper; +//import com.google.auth.oauth2.GoogleCredentials; +//import com.google.common.net.HttpHeaders; +//import jakarta.transaction.Transactional; +//import lombok.RequiredArgsConstructor; +//import lombok.extern.slf4j.Slf4j; +//import okhttp3.*; +//import org.springframework.core.io.ClassPathResource; +//import org.springframework.stereotype.Service; +// +//import java.io.IOException; +//import java.util.List; +// +//@Service +//@RequiredArgsConstructor +//@Slf4j +//public class FCMService { +// +// private final UserFcmTokenRepository userFcmTokenRepository; +// private final String API_URL = "https://fcm.googleapis.com/v1/projects/jolvre-cdfe2/messages:send"; +// private final ObjectMapper objectMapper; +// +// @Transactional +// public void saveUerFcmToken(String token, User user) { +// UserFcmToken userFcmToken = UserFcmToken.builder() +// .token(token) +// .user(user) +// .build(); +// +// userFcmTokenRepository.save(userFcmToken); +// } +// +// public void sendMessageTo(String targetToken, String title, String body) throws IOException { +// String message = makeMessage(targetToken, title, body); +// +// OkHttpClient client = new OkHttpClient(); +// RequestBody requestBody = RequestBody.create(message, MediaType.get("application/json; charset=utf-8")); +// +// Request request = new Request.Builder() +// .url(API_URL) +// .post(requestBody) +// .addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + getAccessToken()) +// .addHeader(HttpHeaders.CONTENT_TYPE, "application/json; UTF-8") +// .build(); +// +// Response response = client.newCall(request).execute(); +// +// log.info(response.body().string()); +// } +// +// public String getTargetToken(User user) { +// UserFcmToken UserFcmToken = userFcmTokenRepository.findByUser(user) +// .orElseThrow(UserNotFoundException::new); +// return UserFcmToken.getToken(); +// } +// +// public String getAccessToken() throws IOException { +// String firebaseConfigPath = "jolvre-cdfe2-418a2fdc3ed8.json"; +// GoogleCredentials googleCredentials = GoogleCredentials +// .fromStream(new ClassPathResource(firebaseConfigPath).getInputStream()) +// .createScoped(List.of("https://www.googleapis.com/auth/cloud-platform")); +// +// googleCredentials.refreshIfExpired(); +// return googleCredentials.getAccessToken().getTokenValue(); +// } +// +// private String makeMessage(String targetToken, String title, String body) throws JsonProcessingException { +// FCMMessage fcmMessage = FCMMessage.builder() +// .message(FCMMessage.Message.builder() +// .token(targetToken) +// .notification(FCMMessage.Notification.builder() +// .title(title) +// .body(body) +// .build() +// ) +// .build() +// ) +// .validate_only(false) +// .build(); +// +// return objectMapper.writeValueAsString(fcmMessage); +// } +//} \ No newline at end of file diff --git a/src/main/java/com/example/jolvre/common/firebase/api/FCMController.java b/src/main/java/com/example/jolvre/common/firebase/api/FCMController.java index fff36de..5c83827 100644 --- a/src/main/java/com/example/jolvre/common/firebase/api/FCMController.java +++ b/src/main/java/com/example/jolvre/common/firebase/api/FCMController.java @@ -1,33 +1,33 @@ -package com.example.jolvre.common.firebase.api; - -import com.example.jolvre.auth.PrincipalDetails; -import com.example.jolvre.common.firebase.Repository.UserFcmTokenRepository; -import com.example.jolvre.common.firebase.Service.FCMService; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@Tag(name = "Firebase Cloud Message", description = "FCM 푸쉬알람 API") -@RestController -@RequiredArgsConstructor -@RequestMapping("/notification") -public class FCMController { - - private final FCMService fcmService; - private final UserFcmTokenRepository userFcmTokenRepository; - - @PostMapping("/new") - public void saveNotification(@RequestBody String token, - @AuthenticationPrincipal PrincipalDetails principalDetails) { - //유저의 토큰이 이미 존재하는 경우 - if (userFcmTokenRepository.existsByUser(principalDetails.getUser())) { - Long TokenId = userFcmTokenRepository.findByUser(principalDetails.getUser()).get().getUserFcmTokenId(); - userFcmTokenRepository.deleteById(TokenId); - } - fcmService.saveUerFcmToken(token, principalDetails.getUser()); - } -} \ No newline at end of file +//package com.example.jolvre.common.firebase.api; +// +//import com.example.jolvre.auth.PrincipalDetails; +//import com.example.jolvre.common.firebase.Repository.UserFcmTokenRepository; +//import com.example.jolvre.common.firebase.Service.FCMService; +//import io.swagger.v3.oas.annotations.tags.Tag; +//import lombok.RequiredArgsConstructor; +//import org.springframework.security.core.annotation.AuthenticationPrincipal; +//import org.springframework.web.bind.annotation.PostMapping; +//import org.springframework.web.bind.annotation.RequestBody; +//import org.springframework.web.bind.annotation.RequestMapping; +//import org.springframework.web.bind.annotation.RestController; +// +//@Tag(name = "Firebase Cloud Message", description = "FCM 푸쉬알람 API") +//@RestController +//@RequiredArgsConstructor +//@RequestMapping("/notification") +//public class FCMController { +// +// private final FCMService fcmService; +// private final UserFcmTokenRepository userFcmTokenRepository; +// +// @PostMapping("/new") +// public void saveNotification(@RequestBody String token, +// @AuthenticationPrincipal PrincipalDetails principalDetails) { +// //유저의 토큰이 이미 존재하는 경우 +// if (userFcmTokenRepository.existsByUser(principalDetails.getUser())) { +// Long TokenId = userFcmTokenRepository.findByUser(principalDetails.getUser()).get().getUserFcmTokenId(); +// userFcmTokenRepository.deleteById(TokenId); +// } +// fcmService.saveUerFcmToken(token, principalDetails.getUser()); +// } +//} \ No newline at end of file diff --git a/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java b/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java index 15e2ff7..35a8da3 100644 --- a/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java +++ b/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java @@ -26,7 +26,6 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import org.springframework.web.reactive.function.client.WebClient; @Service @RequiredArgsConstructor @@ -38,7 +37,6 @@ public class ExhibitService { private final UserService userService; private final DiaryRepository diaryRepository; private final ExhibitCommentRepository exhibitCommentRepository; - private final WebClient webClient; private final ExhibitQueryDslRepository exhibitQueryDslRepository; @Transactional //todo : 모델서버 api가 구현되면 비동기 구현 @@ -91,7 +89,7 @@ public ExhibitInfoResponse getExhibitInfo(Long id) { @Transactional // 배포 설정한 전시만 조회 public ExhibitInfoResponses getAllExhibitInfo() { return ExhibitInfoResponses.builder() - .exhibitResponses(exhibitQueryDslRepository.findAllByFilter(true, null).stream().map( + .exhibitResponses(exhibitRepository.findAllByDistribute(true).stream().map( ExhibitInfoResponse::toDTO ).collect(Collectors.toList())) .build(); @@ -141,7 +139,8 @@ public Exhibit getExhibitByIdAndUserId(Long exhibitId, Long userId) { @Transactional public void distributeExhibit(Long exhibitId, Long userId) { - Exhibit exhibit = getExhibitByIdAndUserId(exhibitId, userId); + Exhibit exhibit = exhibitRepository.findByIdAndUserId(exhibitId, userId) + .orElseThrow(ExhibitNotFoundException::new); exhibit.startDistribute(); diff --git a/src/main/java/com/example/jolvre/group/repository/MemberRepository.java b/src/main/java/com/example/jolvre/group/repository/MemberRepository.java index 9e3d22f..061d2fd 100644 --- a/src/main/java/com/example/jolvre/group/repository/MemberRepository.java +++ b/src/main/java/com/example/jolvre/group/repository/MemberRepository.java @@ -2,8 +2,11 @@ import com.example.jolvre.group.entity.Member; import java.util.List; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; public interface MemberRepository extends JpaRepository { List findAllByUserId(Long userId); + + Optional findByUserIdAndGroupExhibitId(Long userId, Long groupId); } diff --git a/src/main/java/com/example/jolvre/group/service/GroupExhibitService.java b/src/main/java/com/example/jolvre/group/service/GroupExhibitService.java index d793f9c..01389e9 100644 --- a/src/main/java/com/example/jolvre/group/service/GroupExhibitService.java +++ b/src/main/java/com/example/jolvre/group/service/GroupExhibitService.java @@ -1,6 +1,7 @@ package com.example.jolvre.group.service; import com.example.jolvre.common.error.group.GroupExhibitNotFoundException; +import com.example.jolvre.common.error.user.UserNotFoundException; import com.example.jolvre.common.service.S3Service; import com.example.jolvre.exhibition.entity.Exhibit; import com.example.jolvre.exhibition.service.ExhibitService; @@ -99,7 +100,7 @@ public void addExhibit(Long userId, Long groupId, Long exhibitId) { GroupExhibit group = groupExhibitRepository.findById(groupId) .orElseThrow(GroupExhibitNotFoundException::new); - group.checkMember(user); + checker.isMember(group, user); Exhibit exhibit = exhibitService.getExhibitById(exhibitId); @@ -136,7 +137,7 @@ public GroupExhibitUserResponses getGroupExhibitUsers(Long loginUserId, Long gro List members = group.getMembers(); List groupUserInfo = new ArrayList<>(); - + members.forEach(member -> groupUserInfo.add(GroupExhibitUserResponse.builder() .userInfoResponse(UserInfoResponse.toDTO(member.getUser())) @@ -159,15 +160,11 @@ public void addManager(Long fromUser, Long toUser, Long groupId) { checker.isManager(group, from); // 초대 보내는 사람 -> 매니저 checker.isMember(group, to); // 초대 받는 사람 -> 멤버 - Member member = Member.builder() - .groupExhibit(group) - .user(to) - .groupRole(GroupRole.MANAGER) - .build(); - + Member member = memberRepository.findByUserIdAndGroupExhibitId(toUser, groupId) + .orElseThrow(UserNotFoundException::new); + member.setGroupRole(GroupRole.MANAGER); memberRepository.save(member); - group.addMember(member); - + groupExhibitRepository.save(group); } diff --git a/src/main/java/com/example/jolvre/post/service/CommentService.java b/src/main/java/com/example/jolvre/post/service/CommentService.java index e6f17cb..70c971b 100644 --- a/src/main/java/com/example/jolvre/post/service/CommentService.java +++ b/src/main/java/com/example/jolvre/post/service/CommentService.java @@ -4,7 +4,6 @@ import com.example.jolvre.common.error.comment.CommentNotFoundException; import com.example.jolvre.common.error.post.PostNotFoundException; import com.example.jolvre.common.error.user.UserAccessDeniedException; -import com.example.jolvre.common.firebase.Service.FCMService; import com.example.jolvre.post.dto.commentRequest; import com.example.jolvre.post.dto.commentResponse; import com.example.jolvre.post.entity.Comment; @@ -13,6 +12,8 @@ import com.example.jolvre.post.repository.PostRepository; import com.example.jolvre.user.entity.User; import jakarta.transaction.Transactional; +import java.io.IOException; +import java.util.Objects; import lombok.Builder; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -20,10 +21,6 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import java.io.IOException; -import java.util.Objects; -import java.util.concurrent.ExecutionException; - @Service @Builder @Slf4j @@ -32,7 +29,7 @@ public class CommentService { private final CommentRepository commentRepository; private final PostRepository postRepository; private final PostService postService; - private final FCMService FCMService; +// private final FCMService FCMService; public void writeComment(Long postId, commentRequest request, User user) throws IOException { @@ -66,13 +63,12 @@ public Page findAllComment(Pageable pageable, Long postId) { @Transactional public void deleteComment(Long commentId, User user) { Comment comment = commentRepository.findById(commentId) - .orElseThrow(CommentNotFoundException::new); + .orElseThrow(CommentNotFoundException::new); if (!Objects.equals(comment.getUser().getId(), user.getId())) { log.info("[comment] : 댓글 삭제 권한이 없습니다"); throw new UserAccessDeniedException(); - } - else { + } else { commentRepository.deleteById(commentId); log.info("[comment] : {} 댓글 삭제 완료", commentId); } diff --git a/src/main/java/com/example/jolvre/user/entity/User.java b/src/main/java/com/example/jolvre/user/entity/User.java index 4949f19..e7da404 100644 --- a/src/main/java/com/example/jolvre/user/entity/User.java +++ b/src/main/java/com/example/jolvre/user/entity/User.java @@ -1,10 +1,8 @@ package com.example.jolvre.user.entity; import com.example.jolvre.common.entity.BaseTimeEntity; -import com.example.jolvre.common.firebase.Entity.UserFcmToken; import com.example.jolvre.group.entity.Member; import com.example.jolvre.user.dto.UserDTO.UserUpdateRequest; -import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; @@ -13,7 +11,6 @@ import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; -import jakarta.persistence.OneToOne; import jakarta.persistence.Table; import java.util.List; import lombok.Builder; @@ -73,9 +70,6 @@ public class User extends BaseTimeEntity { @OneToMany(mappedBy = "user") private List members; - @OneToOne(mappedBy = "user", cascade = CascadeType.REMOVE) - private UserFcmToken userFcmToken; - @Builder public User(String password, String name, String nickname, int age, String city, String email, String imageUrl, Role role, String school, SocialType socialType, String socialId, String refreshToken) { diff --git a/src/main/java/com/example/jolvre/user/service/UserService.java b/src/main/java/com/example/jolvre/user/service/UserService.java index 0ea942f..03510f9 100644 --- a/src/main/java/com/example/jolvre/user/service/UserService.java +++ b/src/main/java/com/example/jolvre/user/service/UserService.java @@ -40,6 +40,7 @@ public UserInfoResponse getUserInfo(long userId) { public void updateUser(Long userId, UserUpdateRequest request) { User user = userRepository.findById(userId) .orElseThrow(UserNotFoundException::new); + if (request.getImage() != null) { String updateImageUrl = s3Service.updateImage(request.getImage(), user.getImageUrl()); user.updateImage(updateImageUrl); @@ -60,7 +61,7 @@ public User getUserByNickname(String nickname) { .orElseThrow(UserNotFoundException::new); } - public void updatePassword(Long userId,String password) { + public void updatePassword(Long userId, String password) { User user = userRepository.findById(userId) .orElseThrow(UserNotFoundException::new); diff --git a/src/test/java/service/auth/SignUpServiceTest.java b/src/test/java/service/auth/SignUpServiceTest.java index 62b54f7..0733d45 100644 --- a/src/test/java/service/auth/SignUpServiceTest.java +++ b/src/test/java/service/auth/SignUpServiceTest.java @@ -14,9 +14,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.security.crypto.password.PasswordEncoder; @ExtendWith(MockitoExtension.class) public class SignUpServiceTest { @@ -24,8 +22,6 @@ public class SignUpServiceTest { JwtService jwtService; @Mock UserRepository userRepository; - @Spy - PasswordEncoder passwordEncoder; @InjectMocks SignUpService signUpService; @@ -66,4 +62,6 @@ void checkDuplicateNicknameTest() { Assertions.assertTrue(signUpService.checkDuplicateNickname("test@naver.com").isDuplicate()); } + + } diff --git a/src/test/java/service/exhibit/DiaryServiceTest.java b/src/test/java/service/exhibit/DiaryServiceTest.java deleted file mode 100644 index a6913e9..0000000 --- a/src/test/java/service/exhibit/DiaryServiceTest.java +++ /dev/null @@ -1,109 +0,0 @@ -//package service.exhibit; -// -//import static org.mockito.ArgumentMatchers.any; -//import static org.mockito.BDDMockito.anyLong; -//import static org.mockito.BDDMockito.given; -//import static org.mockito.Mockito.verify; -// -//import com.example.jolvre.common.service.S3Service; -//import com.example.jolvre.exhibition.dto.DiaryDTO.DiaryUploadRequest; -//import com.example.jolvre.exhibition.entity.Diary; -//import com.example.jolvre.exhibition.entity.Exhibit; -//import com.example.jolvre.exhibition.repository.DiaryRepository; -//import com.example.jolvre.exhibition.repository.ExhibitRepository; -//import com.example.jolvre.exhibition.service.DiaryService; -//import com.example.jolvre.exhibition.service.ExhibitService; -//import com.example.jolvre.user.entity.User; -//import com.example.jolvre.user.service.UserService; -//import java.util.Optional; -//import org.junit.jupiter.api.Assertions; -//import org.junit.jupiter.api.DisplayName; -//import org.junit.jupiter.api.Test; -//import org.junit.jupiter.api.extension.ExtendWith; -//import org.mockito.InjectMocks; -//import org.mockito.Mock; -//import org.mockito.junit.jupiter.MockitoExtension; -// -//@ExtendWith(MockitoExtension.class) -//public class DiaryServiceTest { -// @Mock -// S3Service s3Service; -// @Mock -// ExhibitRepository exhibitRepository; -// @Mock -// ExhibitService exhibitService; -// @Mock -// DiaryRepository diaryRepository; -// @Mock -// UserService userService; -// -// @InjectMocks -// DiaryService diaryService; -// -// @Test -// @DisplayName("Upload Test") -// void uploadTest() { -// DiaryUploadRequest request = new DiaryUploadRequest("test", "test", null); -// Exhibit exhibit = Exhibit.builder().build(); -// -// given(exhibitService.getExhibitByIdAndUserId(anyLong(), anyLong())).willReturn(exhibit); -// given(userService.getUserById(anyLong())).willReturn(new User()); -// -// diaryService.uploadDiary(0L, 0L, request); -// -// verify(diaryRepository).save(any()); -// } -// -// @Test -// @DisplayName("Get Diary Test") -// void getDiaryTest() { -// given(diaryRepository.findByIdAndExhibitIdAndUserId(anyLong(), anyLong(), anyLong())).willReturn(Optional.of( -// Diary.builder().title("test").build() -// ) -// ); -// -// Assertions -// .assertEquals("test", diaryService.getDiaryInfo(0L, 0L).getTitle()); -// } -// -//// @Test -//// @DisplayName("Get Diary Test") -//// void getAllDiaryTest() { -//// List diaries = new ArrayList<>(); -//// diaries.add(Diary.builder().title("test").build()); -//// given(diaryRepository.findAllByExhibitIdAndUserId(anyLong(), anyLong())).willReturn(diaries); -//// -//// Assertions.assertEquals("test", diaryService.getAllDiaryInfo(0L) -//// .getDiaryGetResponses().get(0).getTitle()); -//// } -// -//// @Test -//// @DisplayName("Update Diary Test") -//// void updateDiaryTest() { -//// MockMultipartFile file = new MockMultipartFile("test", "test.png", MediaType.IMAGE_PNG_VALUE, -//// "test".getBytes()); -//// DiaryUpdateRequest request = DiaryUpdateRequest.builder() -//// .content("asd") -//// .title("asd") -//// .image(file) -//// .build(); -//// -//// Diary diary = Diary.builder() -//// .user(new User()) -//// .title("asdq") -//// .content("qweqwe") -//// .exhibit(new Exhibit()) -//// .build(); -//// -//// String test = "test"; -//// -//// given(diaryRepository.findByIdAndExhibitIdAndUserId(anyLong(), anyLong(), anyLong())).willReturn( -//// Optional.of(diary)); -//// given(s3Service.updateImage(any(), any())).willReturn(test); -//// -//// diaryService.updateDiary(0L, 0L, 0L, request); -//// verify(diaryRepository).save(any()); -//// } -// -// -//} diff --git a/src/test/java/service/exhibit/ExhibitServiceTest.java b/src/test/java/service/exhibit/ExhibitServiceTest.java index 8422e6b..2a52f32 100644 --- a/src/test/java/service/exhibit/ExhibitServiceTest.java +++ b/src/test/java/service/exhibit/ExhibitServiceTest.java @@ -1,16 +1,16 @@ package service.exhibit; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.anyLong; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.verify; -import com.example.jolvre.common.error.exhibition.ExhibitNotFoundException; import com.example.jolvre.common.service.S3Service; -import com.example.jolvre.exhibition.dto.ExhibitDTO.ExhibitInfoResponse; -import com.example.jolvre.exhibition.dto.ExhibitDTO.ExhibitUpdateRequest; +import com.example.jolvre.exhibition.dto.ExhibitDTO.ExhibitInfoResponses; +import com.example.jolvre.exhibition.dto.ExhibitDTO.ExhibitInvitationResponse; import com.example.jolvre.exhibition.entity.Exhibit; +import com.example.jolvre.exhibition.repository.DiaryRepository; +import com.example.jolvre.exhibition.repository.ExhibitCommentRepository; import com.example.jolvre.exhibition.repository.ExhibitImageRepository; +import com.example.jolvre.exhibition.repository.ExhibitQueryDslRepository; import com.example.jolvre.exhibition.repository.ExhibitRepository; import com.example.jolvre.exhibition.service.ExhibitService; import com.example.jolvre.user.entity.User; @@ -25,124 +25,132 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.http.MediaType; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.web.multipart.MultipartFile; @ExtendWith(MockitoExtension.class) public class ExhibitServiceTest { + + @InjectMocks + ExhibitService exhibitService; @Mock ExhibitRepository exhibitRepository; - @Mock - S3Service s3Service; - + ExhibitImageRepository exhibitImageRepository; @Mock - ExhibitImageRepository imageRepository; + S3Service s3Service; @Mock UserService userService; + @Mock + DiaryRepository diaryRepository; + @Mock + ExhibitCommentRepository exhibitCommentRepository; + @Mock + ExhibitQueryDslRepository exhibitQueryDslRepository; - @InjectMocks - ExhibitService exhibitService; - -// @Test -// @DisplayName("Upload Test") -// void uploadTest() { -// User user = new User(); -// -// given(userService.getUserById(any())).willReturn(user); -// -// ExhibitUploadRequest request = ExhibitUploadRequest.builder() -// .authorWord("a") -// .title("a") -// .price(200) -// .size("a") -// .forSale(true) -// .images(null) -// .introduction("a") -// .thumbnail(null) -// .productionMethod("a").build(); -// -// exhibitService.uploadExhibit(request, 0L); -// -// verify(exhibitRepository).save(any()); -// } + @DisplayName("Get All Exhibit Info By Distribute") @Test - @DisplayName("Get Exhibit Test") - void getExhibitTest() { - Exhibit test = Exhibit.builder().title("test").user(new User()).build(); - given(exhibitRepository.findById(anyLong())).willReturn(Optional.of(test)); + void getAllExhibitInfoTest() { + List exhibits = new ArrayList<>(); + User test = User.builder().build(); + Exhibit exhibit1 = Exhibit.builder() + .user(test) + .build(); + + Exhibit exhibit2 = Exhibit.builder() + .user(test) + .build(); + + exhibit1.startDistribute(); + exhibit2.startDistribute(); + + exhibits.add(exhibit1); - ExhibitInfoResponse response = exhibitService.getExhibitInfo(0L); + given(exhibitRepository.findAllByDistribute(true)).willReturn(exhibits); - Assertions.assertEquals("test", response.getTitle()); + ExhibitInfoResponses exhibitInfos = exhibitService.getAllExhibitInfo(); + + exhibitInfos.getExhibitResponses().forEach( + ex -> Assertions.assertTrue(ex.isDistribute()) + ); } + @DisplayName("Get All Exhibit Info By User") @Test - @DisplayName("Get Exhibit Exception Test") - void getExhibitExceptionTest() { - given(exhibitRepository.findById(anyLong())).willThrow(new ExhibitNotFoundException()); + void getAllExhibitInfoByUseTest() { + List exhibits = new ArrayList<>(); + User test = User.builder().build(); + test.setId(0L); + + Exhibit exhibit1 = Exhibit.builder() + .user(test) + .build(); + + Exhibit exhibit2 = Exhibit.builder() + .user(test) + .build(); - Assertions.assertThrows(ExhibitNotFoundException.class, () -> exhibitService.getExhibitInfo(0L)); + exhibits.add(exhibit1); + exhibits.add(exhibit2); + + given(exhibitRepository.findAllByUserId(0L)).willReturn(exhibits); + given(userService.getUserById(0L)).willReturn(test); + + ExhibitInfoResponses exhibitInfos = exhibitService.getAllUserExhibitInfo(0L); + + exhibitInfos.getExhibitResponses().forEach( + ex -> Assertions.assertEquals(0L, ex.getUserInfoResponse().getId())); } + @DisplayName("Distribute Exhibit Test") @Test - @DisplayName("Get All Exhibit Test") - void getAllExhibitTest() { - User user = new User(); + void distributeExhibitTest() { + User user = User.builder().build(); user.setId(0L); + Exhibit exhibit = Exhibit.builder().build(); + exhibit.setId(0L); - List list = new ArrayList<>(); - list.add(Exhibit.builder().title("test").user(user).build()); + given(exhibitRepository.findByIdAndUserId(0L, 0L)).willReturn(Optional.of(exhibit)); - given(exhibitRepository.findAllByUserId(anyLong())).willReturn(list); - given(userService.getUserById(any())).willReturn(user); + exhibitService.distributeExhibit(0L, 0L); - Assertions.assertEquals("test", - exhibitService.getAllUserExhibitInfo(0L).getExhibitResponses().get(0).getTitle()); + verify(exhibitRepository).save(exhibit); } + @DisplayName("create Invitation Test") @Test - @DisplayName("Update Exhibit Test") - void updateExhibitTest() { - List images = new ArrayList<>(); - String url = "test"; - images.add(url); - MockMultipartFile multipartFile = new MockMultipartFile("test", "test.png", MediaType.IMAGE_PNG_VALUE, - "test".getBytes()); - - List files = new ArrayList<>(); - files.add(multipartFile); - - Exhibit test = Exhibit.builder() - .title("asd") - .authorWord("asd") - .forSale(true) - .price(13) - .size("asdasd") - .thumbnail("asfasf") - .productionMethod("asdasda") - .introduction("asdasdasd") - .user(new User()).build(); - - ExhibitUpdateRequest request = ExhibitUpdateRequest.builder() - .title("qq") - .authorWord("qq") - .forSale(false) - .size("asd") - .thumbnail(multipartFile) - .images(files) - .productionMethod("dasdad") + void createInvitationTest() { + User user = User.builder().build(); + user.setId(0L); + Exhibit exhibit = Exhibit.builder() + .title("test") .build(); + exhibit.setId(0L); - given(s3Service.updateImage(any(), any())).willReturn(url); - given(s3Service.uploadImages(any())).willReturn(images); -// given(exhibitService.getExhibitByIdAndUserId(anyLong(), anyLong())).willReturn(test); - given(exhibitRepository.findByIdAndUserId(anyLong(), anyLong())).willReturn(Optional.of(test)); + given(exhibitRepository.findById(0L)).willReturn(Optional.of(exhibit)); - exhibitService.updateExhibit(0L, 0L, request); + ExhibitInvitationResponse invitation = exhibitService.createInvitation(0L); - verify(exhibitRepository).save(any()); + Assertions.assertEquals("test", invitation.getTitle()); + } + + @DisplayName("Get Exhibit Info By Keyword Test") + void getExhibitInfoByKeywordTest() { + User user = User.builder().build(); + user.setId(0L); + Exhibit exhibit = Exhibit.builder() + .title("test") + .build(); + exhibit.setId(0L); + } + + @DisplayName("Get Exhibit Info By Keyword Null Test") + void getExhibitInfoByKeywordNullTest() { + User user = User.builder().build(); + user.setId(0L); + Exhibit exhibit = Exhibit.builder() + .title("test") + .build(); + exhibit.setId(0L); } } + diff --git a/src/test/java/service/group/GroupInviteServiceTest.java b/src/test/java/service/group/GroupInviteServiceTest.java deleted file mode 100644 index 8966160..0000000 --- a/src/test/java/service/group/GroupInviteServiceTest.java +++ /dev/null @@ -1,157 +0,0 @@ -//package service.group; -// -//import static org.mockito.ArgumentMatchers.any; -//import static org.mockito.BDDMockito.given; -//import static org.mockito.Mockito.times; -//import static org.mockito.Mockito.verify; -// -//import com.example.jolvre.common.error.user.UserAccessDeniedException; -//import com.example.jolvre.group.GroupRoleChecker; -//import com.example.jolvre.group.dto.GroupInviteDTO.InviteResponses; -//import com.example.jolvre.group.entity.GroupExhibit; -//import com.example.jolvre.group.entity.GroupInviteState; -//import com.example.jolvre.group.entity.InviteState; -//import com.example.jolvre.group.entity.Manager; -//import com.example.jolvre.group.entity.Member; -//import com.example.jolvre.group.repository.GroupExhibitRepository; -//import com.example.jolvre.group.repository.GroupInviteStateRepository; -//import com.example.jolvre.group.repository.MemberRepository; -//import com.example.jolvre.group.service.GroupInviteService; -//import com.example.jolvre.user.entity.User; -//import com.example.jolvre.user.service.UserService; -//import java.util.ArrayList; -//import java.util.List; -//import java.util.Optional; -//import org.junit.jupiter.api.Assertions; -//import org.junit.jupiter.api.DisplayName; -//import org.junit.jupiter.api.Test; -//import org.junit.jupiter.api.extension.ExtendWith; -//import org.mockito.InjectMocks; -//import org.mockito.Mock; -//import org.mockito.Spy; -//import org.mockito.junit.jupiter.MockitoExtension; -// -//@ExtendWith(MockitoExtension.class) -//public class GroupInviteServiceTest { -// -// @Mock -// UserService userService; -// @Mock -// GroupExhibitRepository groupExhibitRepository; -// @Mock -// GroupInviteStateRepository groupInviteStateRepository; -// @Mock -// MemberRepository memberRepository; -// @Spy -// GroupRoleChecker checker; -// -// @InjectMocks -// GroupInviteService groupInviteService; -// -// @Test -// @DisplayName("Invite User Test") -// void inviteUserTest() { -// User from = User.builder().build(); -// User to = User.builder().build(); -// -// GroupExhibit group = GroupExhibit.builder().name("test").build(); -// group.addMember(Member.builder().user(from).build()); -// group.addManger(Manager.builder().user(from).build()); -// -// given(userService.getUserById(0L)).willReturn(from); -// given(userService.getUserByNickname("TEST")).willReturn(to); -// given(groupExhibitRepository.findById(any())).willReturn(Optional.of(group)); -// -// groupInviteService.inviteUser(0L, "TEST", 0L); -// -// verify(groupInviteStateRepository).save(any()); -// } -// -// @Test -// @DisplayName("Invite User Exception (to is Member) Test") -// void inviteUserToIsMemberExceptionTest() { -// User from = User.builder().build(); -// User to = User.builder().build(); -// -// GroupExhibit group = GroupExhibit.builder().name("test").build(); -// -// group.addMember(Member.builder().user(from).build()); -// group.addManger(Manager.builder().user(from).build()); -// group.addMember(Member.builder().user(to).build()); -// -// given(userService.getUserById(0L)).willReturn(from); -// given(userService.getUserByNickname("TEST")).willReturn(to); -// given(groupExhibitRepository.findById(any())).willReturn(Optional.of(group)); -// -// Assertions.assertThrows(UserAccessDeniedException.class, () -> -// groupInviteService.inviteUser(0L, "TEST", 0L)); -// } -// -// @Test -// @DisplayName("Invite User Exception (from is not Manager) Test") -// void inviteUserFromIsNotManagerExceptionTest() { -// User from = User.builder().build(); -// User to = User.builder().build(); -// -// GroupExhibit group = GroupExhibit.builder().name("test").build(); -// group.addMember(Member.builder().user(from).build()); -// -// given(userService.getUserById(0L)).willReturn(from); -// given(userService.getUserByNickname("TEST")).willReturn(to); -// given(groupExhibitRepository.findById(any())).willReturn(Optional.of(group)); -// -// Assertions.assertThrows(UserAccessDeniedException.class, () -> -// groupInviteService.inviteUser(0L, "TEST", 0L)); -// } -// -// @Test -// @DisplayName("Get All Invite Test") -// void getAllInviteTest() { -// GroupInviteState test = GroupInviteState.builder() -// .groupExhibit(new GroupExhibit()) -// .user(new User()) -// .inviteState(InviteState.ACCEPT).build(); -// -// List tests = new ArrayList<>(); -// tests.add(test); -// -// given(groupInviteStateRepository.findAllByUserId(any())).willReturn(tests); -// -// InviteResponses responses = groupInviteService.getAllInvite(0L); -// String state = responses.getInviteResponses().get(0).getInviteState(); -// -// Assertions.assertEquals(InviteState.ACCEPT.toString(), state); -// } -// -// @Test -// @DisplayName("Check Invite Status Test (Accept)") -// void checkInviteStatusAcceptTest() { -// GroupInviteState test = GroupInviteState.builder() -// .inviteState(InviteState.PEND) -// .user(new User()) -// .groupExhibit(new GroupExhibit()) -// .build(); -// -// given(groupInviteStateRepository.findById(any())).willReturn(Optional.of(test)); -// -// groupInviteService.checkInviteStatus(0L, InviteState.ACCEPT.toString()); -// -// verify(groupExhibitRepository).save(any()); -// } -// -// @Test -// @DisplayName("Check Invite Status Test (Refuse)") -// void checkInviteStatusRefuseTest() { -// GroupInviteState test = GroupInviteState.builder() -// .inviteState(InviteState.PEND) -// .user(new User()) -// .groupExhibit(new GroupExhibit()) -// .build(); -// -// given(groupInviteStateRepository.findById(any())).willReturn(Optional.of(test)); -// -// groupInviteService.checkInviteStatus(0L, InviteState.REFUSE.toString()); -// -// verify(groupExhibitRepository, times(0)).save(any()); -// } -//} diff --git a/src/test/java/service/group/GroupRoleCheckerTest.java b/src/test/java/service/group/GroupRoleCheckerTest.java new file mode 100644 index 0000000..d3ba493 --- /dev/null +++ b/src/test/java/service/group/GroupRoleCheckerTest.java @@ -0,0 +1,4 @@ +package service.group; + +public class GroupRoleCheckerTest { +} diff --git a/src/test/java/service/user/UserServiceTest.java b/src/test/java/service/user/UserServiceTest.java index dbdd513..ce2866c 100644 --- a/src/test/java/service/user/UserServiceTest.java +++ b/src/test/java/service/user/UserServiceTest.java @@ -1,5 +1,6 @@ package service.user; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.BDDMockito.any; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.verify; @@ -19,6 +20,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; @ExtendWith(MockitoExtension.class) public class UserServiceTest { @@ -52,9 +55,13 @@ void getUserExceptionTest() { Assertions.assertThrows(UserNotFoundException.class, () -> userService.getUserInfo(1L)); } - @DisplayName("Update User Test") + @DisplayName("Update User Test , Image is Null") @Test void updateUserTest() { + MockMultipartFile multipartFile = new MockMultipartFile("test", + "test.png", MediaType.IMAGE_PNG_VALUE, + "test".getBytes()); + User test = User.builder() .name("고수") .nickname("고수") @@ -65,9 +72,10 @@ void updateUserTest() { UserUpdateRequest request = UserUpdateRequest.builder() .name("test") .nickname("test") + .image(multipartFile) .build(); - given(userRepository.findById(any(Long.class))).willReturn(Optional.of(test)); + given(userRepository.findById(anyLong())).willReturn(Optional.of(test)); given(s3Service.updateImage(any(), any())).willReturn(any()); userService.updateUser(0L, request); @@ -75,6 +83,28 @@ void updateUserTest() { verify(userRepository).save(any()); } + @DisplayName("Update User Test , Image is Null") + @Test + void updateUserImageIsNullTest() { + User test = User.builder() + .name("고수") + .nickname("고수") + .city("고수") + .age(20) + .imageUrl("고수") + .build(); + UserUpdateRequest request = UserUpdateRequest.builder() + .name("test") + .nickname("test") + .build(); + + given(userRepository.findById(anyLong())).willReturn(Optional.of(test)); + + userService.updateUser(0L, request); + + verify(userRepository).save(any()); + } + @DisplayName("Update User Exception Test") @Test void updateUserExceptionTest() { From 70b413773841ebe8a8455f15faa676cb841ff222 Mon Sep 17 00:00:00 2001 From: gosu Date: Tue, 11 Jun 2024 22:17:20 +0900 Subject: [PATCH 03/10] =?UTF-8?q?test=20:=20GroupRoleChecker=20Test=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jolvre/group/GroupRoleChecker.java | 2 +- .../group/GroupExhibitServiceTest.java | 360 ++++++++++-------- .../service/group/GroupRoleCheckerTest.java | 105 +++++ 3 files changed, 302 insertions(+), 165 deletions(-) diff --git a/src/main/java/com/example/jolvre/group/GroupRoleChecker.java b/src/main/java/com/example/jolvre/group/GroupRoleChecker.java index f0f3b16..af6bb03 100644 --- a/src/main/java/com/example/jolvre/group/GroupRoleChecker.java +++ b/src/main/java/com/example/jolvre/group/GroupRoleChecker.java @@ -17,7 +17,7 @@ public void isMember(GroupExhibit group, User user) { } public void isNotMember(GroupExhibit group, User user) { - if (group.checkMember(user) && group.checkManager(user)) { + if (group.checkMember(user) || group.checkManager(user)) { throw new UserAccessDeniedException(); } } diff --git a/src/test/java/service/group/GroupExhibitServiceTest.java b/src/test/java/service/group/GroupExhibitServiceTest.java index 745b59a..e03c144 100644 --- a/src/test/java/service/group/GroupExhibitServiceTest.java +++ b/src/test/java/service/group/GroupExhibitServiceTest.java @@ -1,164 +1,196 @@ -//package service.group; -// -//import static org.mockito.ArgumentMatchers.any; -//import static org.mockito.ArgumentMatchers.anyLong; -//import static org.mockito.BDDMockito.given; -//import static org.mockito.Mockito.verify; -// -//import com.example.jolvre.exhibition.entity.Exhibit; -//import com.example.jolvre.exhibition.service.ExhibitService; -//import com.example.jolvre.group.GroupRoleChecker; -//import com.example.jolvre.group.dto.GroupExhibitDTO.GroupExhibitCreateRequest; -//import com.example.jolvre.group.dto.GroupExhibitDTO.GroupExhibitInfoResponse; -//import com.example.jolvre.group.dto.GroupExhibitDTO.GroupExhibitInfoResponses; -//import com.example.jolvre.group.dto.GroupExhibitDTO.GroupExhibitUserResponses; -//import com.example.jolvre.group.entity.GroupExhibit; -//import com.example.jolvre.group.entity.Member; -//import com.example.jolvre.group.repository.GroupExhibitRepository; -//import com.example.jolvre.group.repository.MemberRepository; -//import com.example.jolvre.group.service.GroupExhibitService; -//import com.example.jolvre.user.entity.User; -//import com.example.jolvre.user.service.UserService; -//import java.util.ArrayList; -//import java.util.List; -//import java.util.Optional; -//import org.junit.jupiter.api.Assertions; -//import org.junit.jupiter.api.DisplayName; -//import org.junit.jupiter.api.Test; -//import org.junit.jupiter.api.extension.ExtendWith; -//import org.mockito.InjectMocks; -//import org.mockito.Mock; -//import org.mockito.junit.jupiter.MockitoExtension; -// -//@ExtendWith(MockitoExtension.class) -//public class GroupExhibitServiceTest { -// @Mock -// GroupExhibitRepository groupExhibitRepository; -// @Mock -// ManagerRepository managerRepository; -// @Mock -// MemberRepository memberRepository; -// @Mock -// UserService userService; -// @Mock -// ExhibitService exhibitService; -// @Mock -// GroupRoleChecker checker; -// -// @InjectMocks -// GroupExhibitService groupExhibitService; -// -// @Test -// @DisplayName("Create Group Exhibit") -// void createGroupExhibit() { -// GroupExhibitCreateRequest request = GroupExhibitCreateRequest.builder() -// .name("test") -// .build(); -// -// groupExhibitService.createGroupExhibit(0L, request); -// -// verify(groupExhibitRepository).save(any()); -// } -// -// @Test -// @DisplayName("Get All Group Exhibit") -// void getAllGroupExhibit() { -// GroupExhibit test1 = GroupExhibit.builder().name("test1").build(); -// GroupExhibit test2 = GroupExhibit.builder().name("test2").build(); -// GroupExhibit test3 = GroupExhibit.builder().name("test3").build(); -// -// List groupExhibits = new ArrayList<>(); -// groupExhibits.add(test1); -// groupExhibits.add(test2); -// groupExhibits.add(test3); -// -// given(groupExhibitRepository.findAll()).willReturn(groupExhibits); -// -// GroupExhibitInfoResponses responses = groupExhibitService.getAllGroupExhibitInfo(); -// -// GroupExhibitInfoResponse group = responses.getGroupExhibitResponses().get(0); -// -// Assertions.assertEquals(test1.getName(), group.getName()); -// } -// -// @Test -// @DisplayName("Get Group Exhibit") -// void getGroupExhibit() { -// GroupExhibit test = GroupExhibit.builder().name("test").build(); -// -// given(groupExhibitRepository.findById(any())).willReturn(Optional.of(test)); -// -// GroupExhibitInfoResponse response = groupExhibitService.getGroupExhibitInfo(0L); -// -// Assertions.assertEquals(test.getName(), response.getName()); -// } -// -// @Test -// @DisplayName("Get All USer Group Exhibit") -// void getAllUserGroupExhibit() { -// GroupExhibit test = GroupExhibit.builder().name("test").build(); -// Member member = Member.builder().groupExhibit(test).build(); -// List members = new ArrayList<>(); -// members.add(member); -// -// given(memberRepository.findAllByUserId(anyLong())).willReturn(members); -// -// GroupExhibitInfoResponses responses = groupExhibitService.getAllUserGroupExhibitInfo(0L); -// String name = responses.getGroupExhibitResponses().get(0).getName(); -// -// Assertions.assertEquals(test.getName(), name); -// } -// -// @Test -// @DisplayName("Get Group Exhibit Users") -// void getGroupExhibitUsers() { -// -// Member member1 = Member.builder().user(User.builder().name("test1").build()).build(); -// Member member2 = Member.builder().user(User.builder().name("test2").build()).build(); -// Manager manager = Manager.builder().user(User.builder().name("test3").build()).build(); -// -// GroupExhibit test = GroupExhibit.builder().name("test").build(); -// test.addMember(member1); -// test.addMember(member2); -// test.addManger(manager); -// -// given(groupExhibitRepository.findById(any())).willReturn(Optional.of(test)); -// -// GroupExhibitUserResponses responses = groupExhibitService.getGroupExhibitUsers(0L, 0L); -// String username = responses.getGroupExhibitUserResponses().get(0).getUserInfoResponse().getName(); -// -// Assertions.assertEquals("test3", username); -// } -// -// @Test -// @DisplayName("Add Exhibit") -// void addExhibit() { -// GroupExhibit test = GroupExhibit.builder().name("test").build(); -// Exhibit exhibit = Exhibit.builder().build(); -// User user = User.builder().build(); -// -// given(groupExhibitRepository.findById(anyLong())).willReturn(Optional.of(test)); -// given(exhibitService.getExhibitById(anyLong())).willReturn(exhibit); -// given(userService.getUserById(anyLong())).willReturn(user); -// -// groupExhibitService.addExhibit(0L, 0L, 0L); -// -// verify(groupExhibitRepository).save(any()); -// } -// -// @Test -// @DisplayName("Add Manager") -// void addManager() { -// User fromUser = User.builder().name("from").build(); -// User toUser = User.builder().name("to").build(); -// GroupExhibit test = GroupExhibit.builder().name("test").build(); -// -// given(userService.getUserById(0L)).willReturn(fromUser); -// given(userService.getUserById(1L)).willReturn(toUser); -// given(groupExhibitRepository.findById(anyLong())).willReturn(Optional.of(test)); -// -// groupExhibitService.addManager(0L, 1L, 0L); -// -// verify(groupExhibitRepository).save(any()); -// } -//} +package service.group; + +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willThrow; +import static org.mockito.Mockito.verify; + +import com.example.jolvre.common.error.user.UserAccessDeniedException; +import com.example.jolvre.common.service.S3Service; +import com.example.jolvre.exhibition.entity.Exhibit; +import com.example.jolvre.exhibition.service.ExhibitService; +import com.example.jolvre.group.GroupRoleChecker; +import com.example.jolvre.group.dto.GroupExhibitDTO.GroupExhibitUserResponses; +import com.example.jolvre.group.dto.GroupExhibitDTO.GroupInvitationResponse; +import com.example.jolvre.group.entity.GroupExhibit; +import com.example.jolvre.group.entity.GroupRole; +import com.example.jolvre.group.entity.Member; +import com.example.jolvre.group.repository.GroupExhibitRepository; +import com.example.jolvre.group.repository.MemberRepository; +import com.example.jolvre.group.repository.RegisteredExhibitRepository; +import com.example.jolvre.group.service.GroupExhibitService; +import com.example.jolvre.user.entity.User; +import com.example.jolvre.user.service.UserService; +import java.util.Optional; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class GroupExhibitServiceTest { + @Mock + GroupExhibitRepository groupExhibitRepository; + @Mock + MemberRepository memberRepository; + @Mock + RegisteredExhibitRepository registeredExhibitRepository; + @Mock + UserService userService; + @Mock + ExhibitService exhibitService; + @Mock + GroupRoleChecker checker; + @Mock + S3Service s3Service; + + @InjectMocks + GroupExhibitService groupExhibitService; + + @DisplayName("Add Exhibit Test") + @Test + void addExhibitTest() { + User test = User.builder().build(); + + Member manager = Member.builder().user(test).groupRole(GroupRole.MEMBER).build(); + + Exhibit exhibit = Exhibit.builder() + .title("test") + .user(test) + .build(); + + GroupExhibit group = GroupExhibit.builder() + .build(); + group.addMember(manager); + + given(userService.getUserById(0L)).willReturn(test); + given(exhibitService.getExhibitById(0L)).willReturn(exhibit); + given(groupExhibitRepository.findById(0L)).willReturn(Optional.of(group)); + + groupExhibitService.addExhibit(0L, 0L, 0L); + + verify(groupExhibitRepository).save(group); + } + + @DisplayName("Add Manager Test") + @Test + void addManagerTest() { + User from = User.builder().build(); + User to = User.builder().build(); + + GroupExhibit group = GroupExhibit.builder().build(); + + Member manager = Member.builder() + .user(from) + .groupRole(GroupRole.MANAGER) + .build(); + + Member member = Member.builder() + .user(to) + .groupRole(GroupRole.MEMBER) + .build(); + + group.addMember(manager); + group.addMember(member); + + given(userService.getUserById(0L)).willReturn(from); + given(userService.getUserById(1L)).willReturn(to); + given(groupExhibitRepository.findById(0L)).willReturn(Optional.of(group)); + given(memberRepository.findByUserIdAndGroupExhibitId(1L, 0L)).willReturn(Optional.of(member)); + + groupExhibitService.addManager(0L, 1L, 0L); + + verify(groupExhibitRepository).save(group); + } + + @DisplayName("Add Manager Exception Test (Access Denied) (From User is not Manager)") + @Test + void addManagerExceptionFromIsNotManagerTest() { + User from = User.builder().build(); + User to = User.builder().build(); + + GroupExhibit group = GroupExhibit.builder().build(); + + Member manager = Member.builder() + .user(from) + .groupRole(GroupRole.MEMBER) // 초대하는 사람은 매니저여야 함 + .build(); + + Member member = Member.builder() + .user(to) + .groupRole(GroupRole.MEMBER) + .build(); + + group.addMember(manager); + group.addMember(member); + + given(userService.getUserById(0L)).willReturn(from); + given(userService.getUserById(1L)).willReturn(to); + given(groupExhibitRepository.findById(0L)).willReturn(Optional.of(group)); + + willThrow(new UserAccessDeniedException()).given(checker).isManager(group, from); + + Assertions.assertThrows(UserAccessDeniedException.class, + () -> groupExhibitService.addManager(0L, 1L, 0L)); + } + + @DisplayName("Add Manager Exception Test (Access Denied) (To User is not Member)") + @Test + void addManagerExceptionToIsNotMemberTest() { + User from = User.builder().build(); + User to = User.builder().build(); // to 가 멤버여야함 + + GroupExhibit group = GroupExhibit.builder().build(); + + Member manager = Member.builder() + .user(from) + .groupRole(GroupRole.MANAGER) // 초대하는 사람은 매니저여야 함 + .build(); + + group.addMember(manager); + + given(userService.getUserById(0L)).willReturn(from); + given(userService.getUserById(1L)).willReturn(to); + given(groupExhibitRepository.findById(0L)).willReturn(Optional.of(group)); + + willThrow(new UserAccessDeniedException()).given(checker).isMember(group, to); + + Assertions.assertThrows(UserAccessDeniedException.class, + () -> groupExhibitService.addManager(0L, 1L, 0L)); + } + + @DisplayName("Get Group Exhibit Users Test") + @Test + void getGroupExhibitUsersTest() { + User user = User.builder().name("test").build(); + Member member = Member.builder().user(user).groupRole(GroupRole.MEMBER).build(); + + GroupExhibit group = GroupExhibit.builder().build(); + group.addMember(member); + + given(groupExhibitRepository.findById(0L)).willReturn(Optional.of(group)); + given(userService.getUserById(0L)).willReturn(user); + + GroupExhibitUserResponses responses = groupExhibitService.getGroupExhibitUsers(0L, 0L); + + responses.getGroupExhibitUserResponses().forEach( + groupMember -> Assertions.assertEquals("test", groupMember.getUserInfoResponse().getName()) + ); + } + + @DisplayName("Create Invitation Test") + @Test + void createInvitationTest() { + GroupExhibit group = GroupExhibit.builder() + .name("test") + .build(); + + given(groupExhibitRepository.findById(0L)).willReturn(Optional.of(group)); + + GroupInvitationResponse response = groupExhibitService.createInvitation(0L); + + Assertions.assertEquals("test", response.getName()); + } +} diff --git a/src/test/java/service/group/GroupRoleCheckerTest.java b/src/test/java/service/group/GroupRoleCheckerTest.java index d3ba493..1a5b020 100644 --- a/src/test/java/service/group/GroupRoleCheckerTest.java +++ b/src/test/java/service/group/GroupRoleCheckerTest.java @@ -1,4 +1,109 @@ package service.group; +import com.example.jolvre.common.error.user.UserAccessDeniedException; +import com.example.jolvre.group.GroupRoleChecker; +import com.example.jolvre.group.entity.GroupExhibit; +import com.example.jolvre.group.entity.GroupRole; +import com.example.jolvre.group.entity.Member; +import com.example.jolvre.user.entity.User; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + public class GroupRoleCheckerTest { + GroupRoleChecker groupRoleChecker = new GroupRoleChecker(); + + GroupExhibit group = new GroupExhibit(); + + User memberUser = new User(); + User managerUser = new User(); + User user = new User(); + + Member member; + Member manager; + + @BeforeEach + void init() { + + memberUser.setId(0L); + managerUser.setId(1L); + user.setId(2L); + + this.member = Member.builder() + .user(memberUser) + .groupRole(GroupRole.MEMBER) + .build(); + + this.manager = Member.builder() + .user(managerUser) + .groupRole(GroupRole.MANAGER) + .build(); + + group.addMember(member); + group.addMember(manager); + + } + + @DisplayName("Is Member Test (Member , Manager)") + @Test + void isMemberTest() { + groupRoleChecker.isMember(group, memberUser); + groupRoleChecker.isMember(group, managerUser); + } + + @DisplayName("Is Member Exception Test (User)") + @Test + void isMemberExceptionTest() { + Assertions.assertThrows(UserAccessDeniedException.class, + () -> groupRoleChecker.isMember(group, user)); + } + + @DisplayName("Is Not Member Test (User)") + @Test + void isNotMemberTest() { + groupRoleChecker.isNotMember(group, user); + } + + @DisplayName("Is Not Member Exception Test (Member , Manager)") + @Test + void isNotMemberExceptionTest() { + Assertions.assertThrows(UserAccessDeniedException.class, + () -> groupRoleChecker.isNotMember(group, memberUser)); + + Assertions.assertThrows(UserAccessDeniedException.class, + () -> groupRoleChecker.isNotMember(group, managerUser)); + + } + + @DisplayName("Is Manager Test (Manager)") + @Test + void isManagerTest() { + groupRoleChecker.isManager(group, managerUser); + } + + @DisplayName("Is Manager Exception Test (Member , User)") + @Test + void isManagerExceptionTest() { + Assertions.assertThrows(UserAccessDeniedException.class, + () -> groupRoleChecker.isManager(group, memberUser)); + + Assertions.assertThrows(UserAccessDeniedException.class, + () -> groupRoleChecker.isManager(group, user)); + } + + @DisplayName("Is Not Manager Test (Member , User)") + @Test + void isNotManagerTest() { + groupRoleChecker.isNotManager(group, memberUser); + groupRoleChecker.isNotManager(group, user); + } + + @DisplayName("Is Not Manager Exception Test (Manager)") + @Test + void isNotManagerExceptionTest() { + Assertions.assertThrows(UserAccessDeniedException.class, + () -> groupRoleChecker.isNotManager(group, managerUser)); + } } + From c23d5e7de50966f0df784b5835e6140bd1ee25c4 Mon Sep 17 00:00:00 2001 From: gosu Date: Wed, 12 Jun 2024 12:01:25 +0900 Subject: [PATCH 04/10] =?UTF-8?q?test=20:=20GroupInviteService=20Test=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jolvre/exhibition/dto/ExhibitDTO.java | 6 + .../repository/ExhibitQueryDslRepository.java | 15 +- .../exhibition/service/ExhibitService.java | 12 +- .../service/group/GroupInviteServiceTest.java | 143 ++++++++++++++++++ 4 files changed, 162 insertions(+), 14 deletions(-) create mode 100644 src/test/java/service/group/GroupInviteServiceTest.java diff --git a/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java b/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java index c10ade2..dd901e4 100644 --- a/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java +++ b/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java @@ -84,6 +84,12 @@ public static class ExhibitInfoResponse { private UserInfoResponse userInfoResponse; private DiaryInfoResponses diaryInfoResponses; + public ExhibitInfoResponse(Long id, String title, String thumbnail) { + this.id = id; + this.title = title; + this.thumbnail = thumbnail; + } + @QueryProjection public ExhibitInfoResponse(Long id, String title, String authorWord, String introduction, String size, String productionMethod, int price, boolean forSale, String thumbnail, diff --git a/src/main/java/com/example/jolvre/exhibition/repository/ExhibitQueryDslRepository.java b/src/main/java/com/example/jolvre/exhibition/repository/ExhibitQueryDslRepository.java index 1e3ec32..a4dc525 100644 --- a/src/main/java/com/example/jolvre/exhibition/repository/ExhibitQueryDslRepository.java +++ b/src/main/java/com/example/jolvre/exhibition/repository/ExhibitQueryDslRepository.java @@ -7,7 +7,6 @@ import com.example.jolvre.exhibition.dto.ExhibitDTO.ExhibitInfoResponse; import com.example.jolvre.exhibition.entity.Exhibit; -import com.example.jolvre.exhibition.entity.QExhibit; import com.example.jolvre.user.entity.User; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; @@ -36,15 +35,13 @@ public List findAllByFilter(boolean distribute, String title) { public Page findAllByFilter(boolean distribute, String title, Pageable pageable) { List exhibits = queryFactory .select(Projections.constructor(ExhibitInfoResponse.class - , QExhibit.exhibit.id - , QExhibit.exhibit.title - , QExhibit.exhibit.thumbnail + , exhibit.id + , exhibit.title + , exhibit.thumbnail )) - .leftJoin(exhibit.user, user) - .fetchJoin() - .leftJoin(exhibit.exhibitImages, exhibitImage) - .leftJoin(exhibit.diaries, diary) - .where(QExhibit.exhibit.distribute.eq(distribute), containTitle(title)) + .from(exhibit) + .where(exhibit.distribute.eq(distribute), containTitle(title)) + .orderBy(exhibit.id.desc()) .offset(pageable.getOffset()) .limit(pageable.getPageSize()) .fetch(); diff --git a/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java b/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java index 35a8da3..ccef84d 100644 --- a/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java +++ b/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java @@ -190,10 +190,12 @@ public ExhibitInvitationResponse createInvitation(Long exhibitId) { } public Page getExhibitInfoByKeyword(String keyword, Pageable pageable) { - if (keyword == null) { - return exhibitRepository.findAllByDistribute(true, pageable).map(ExhibitInfoResponse::toDTO); - } - return exhibitRepository.findByDistributeAndTitleContaining(true, keyword, pageable) - .map(ExhibitInfoResponse::toDTO); +// if (keyword == null) { +// return exhibitRepository.findAllByDistribute(true, pageable).map(ExhibitInfoResponse::toDTO); +// } +// return exhibitRepository.findByDistributeAndTitleContaining(true, keyword, pageable) +// .map(ExhibitInfoResponse::toDTO); + + return exhibitQueryDslRepository.findAllByFilter(true, keyword, pageable); } } diff --git a/src/test/java/service/group/GroupInviteServiceTest.java b/src/test/java/service/group/GroupInviteServiceTest.java new file mode 100644 index 0000000..3d4e583 --- /dev/null +++ b/src/test/java/service/group/GroupInviteServiceTest.java @@ -0,0 +1,143 @@ +package service.group; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.verify; + +import com.example.jolvre.common.error.group.GroupInviteDuplicateException; +import com.example.jolvre.group.GroupRoleChecker; +import com.example.jolvre.group.entity.GroupExhibit; +import com.example.jolvre.group.entity.GroupInviteState; +import com.example.jolvre.group.entity.GroupRole; +import com.example.jolvre.group.entity.InviteState; +import com.example.jolvre.group.entity.Member; +import com.example.jolvre.group.repository.GroupExhibitRepository; +import com.example.jolvre.group.repository.GroupInviteStateRepository; +import com.example.jolvre.group.repository.MemberRepository; +import com.example.jolvre.group.service.GroupInviteService; +import com.example.jolvre.user.entity.User; +import com.example.jolvre.user.service.UserService; +import java.util.Optional; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class GroupInviteServiceTest { + + @InjectMocks + GroupInviteService groupInviteService; + @Mock + UserService userService; + @Mock + GroupExhibitRepository groupExhibitRepository; + @Mock + GroupInviteStateRepository groupInviteStateRepository; + @Mock + MemberRepository memberRepository; + + @Mock + GroupRoleChecker checker; + + @DisplayName("Invite User Test") + @Test + void inviteUserTest() { + User fromUser = User.builder() + .nickname("from") + .build(); + Member manager = Member.builder() + .user(fromUser) + .groupRole(GroupRole.MANAGER) + .build(); + + User toUser = User.builder() + .nickname("to") + .build(); + + GroupExhibit group = GroupExhibit.builder() + .build(); + + group.addMember(manager); + + given(userService.getUserById(0L)).willReturn(fromUser); + given(userService.getUserByNickname("to")).willReturn(toUser); + given(groupExhibitRepository.findById(0L)).willReturn(Optional.of(group)); + + groupInviteService.inviteUser(0L, "to", 0L); + + verify(groupInviteStateRepository).save(any()); + } + + @DisplayName("Invite User Test (Duplicate Invite)") + @Test + void inviteUserExceptionTest() { + User fromUser = User.builder() + .nickname("from") + .build(); + Member manager = Member.builder() + .user(fromUser) + .groupRole(GroupRole.MANAGER) + .build(); + + User toUser = User.builder() + .nickname("to") + .build(); + toUser.setId(0L); + + GroupExhibit group = GroupExhibit.builder() + .build(); + + group.addMember(manager); + + given(userService.getUserById(0L)).willReturn(fromUser); + given(userService.getUserByNickname("to")).willReturn(toUser); + given(groupExhibitRepository.findById(0L)).willReturn(Optional.of(group)); + given(groupInviteStateRepository.existsByGroupExhibitIdAndUserId(0L, 0L)) + .willThrow(new GroupInviteDuplicateException()); //이미 초대된 멤버 + + Assertions.assertThrows(GroupInviteDuplicateException.class, + () -> groupInviteService.inviteUser(0L, "to", 0L)); + } + + @DisplayName("Check Invite Status Accept Test") + @Test + void checkInviteStatusAcceptTest() { + User user = User.builder().build(); + GroupExhibit group = GroupExhibit.builder().build(); + + GroupInviteState state = GroupInviteState.builder() + .inviteState(InviteState.PEND) + .user(user) + .groupExhibit(group) + .build(); + + given(groupInviteStateRepository.findByIdAndUserId(0L, 0L)).willReturn(Optional.of(state)); + + groupInviteService.checkInviteStatus(0L, InviteState.ACCEPT, 0L); + + verify(groupExhibitRepository).save(group); + } + + @DisplayName("Check Invite Status Refuse Test") + @Test + void checkInviteStatusRefuseTest() { + User user = User.builder().build(); + GroupExhibit group = GroupExhibit.builder().build(); + + GroupInviteState state = GroupInviteState.builder() + .inviteState(InviteState.PEND) + .user(user) + .groupExhibit(group) + .build(); + + given(groupInviteStateRepository.findByIdAndUserId(0L, 0L)).willReturn(Optional.of(state)); + + groupInviteService.checkInviteStatus(0L, InviteState.REFUSE, 0L); + + verify(groupInviteStateRepository).delete(state); + } +} From a8b96065964f92948a59bff4645ba772ecbd846b Mon Sep 17 00:00:00 2001 From: gosu Date: Fri, 14 Jun 2024 10:59:49 +0900 Subject: [PATCH 05/10] =?UTF-8?q?[style]=20:=20=EB=A1=9C=EA=B9=85=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/jolvre/auth/api/AuthController.java | 4 ++++ .../jolvre/auth/api/SignUpController.java | 6 +++++- .../JwtAuthenticationProcessingFilter.java | 3 +-- .../jolvre/exhibition/api/DiaryController.java | 8 +++++--- .../api/ExhibitionCommentController.java | 9 +++++---- .../exhibition/api/ExhibitionController.java | 9 +++++++-- .../jolvre/exhibition/dto/ExhibitDTO.java | 16 ++++++++++------ .../repository/ExhibitQueryDslRepository.java | 17 ++++++++--------- .../exhibition/service/ExhibitService.java | 5 ++--- .../group/api/GroupExhibitController.java | 7 +++++-- .../jolvre/group/api/GroupInviteController.java | 4 ++++ 11 files changed, 56 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/example/jolvre/auth/api/AuthController.java b/src/main/java/com/example/jolvre/auth/api/AuthController.java index 55906ca..adc0131 100644 --- a/src/main/java/com/example/jolvre/auth/api/AuthController.java +++ b/src/main/java/com/example/jolvre/auth/api/AuthController.java @@ -55,6 +55,7 @@ public ResponseEntity refresh(@RequestBody RefreshRequest request @GetMapping("/pw/email/{email}") public ResponseEntity sendPwFindAuthEmail(@PathVariable String email) { mailService.sendFindPwEmail(email); + log.info("[EMAIL] {}님 비밀번호 찾기 메일 발송 완료", email); return ResponseEntity.ok().build(); } @@ -63,6 +64,7 @@ public ResponseEntity sendPwFindAuthEmail(@PathVariable String email) { public ResponseEntity verifyPwFindAuthEmail(@RequestBody EmailVerifyRequest request) { FindPwEmailVerifyResponse response = mailVerifyService.CheckFindPwAuthNum(request.getEmail(), request.getAuthNum()); + log.info("[EMAIL] {}님 비밀번호 찾기 메일 검증 완료", request.getEmail()); return ResponseEntity.ok().body(response); } @@ -72,6 +74,8 @@ public ResponseEntity verifyPwFindAuthEmail(@RequestB public ResponseEntity updatePw(@AuthenticationPrincipal PrincipalDetails principalDetails, @RequestBody PasswordUpdateRequest request) { userService.updatePassword(principalDetails.getId(), request.getPassword()); + log.info("[EMAIL] {}님 비밀번호 찾기 메일 검증 완료", principalDetails.getUser().getEmail()); + return ResponseEntity.ok().build(); } } diff --git a/src/main/java/com/example/jolvre/auth/api/SignUpController.java b/src/main/java/com/example/jolvre/auth/api/SignUpController.java index 5f713a3..392a2d0 100644 --- a/src/main/java/com/example/jolvre/auth/api/SignUpController.java +++ b/src/main/java/com/example/jolvre/auth/api/SignUpController.java @@ -40,8 +40,8 @@ public class SignUpController { @Operation(summary = "회원 가입") @PostMapping public ResponseEntity signUpBasic(@Valid @RequestBody BasicSignUpRequest request) { - log.info("[AUTH] : 기본 회원가입"); TokenResponse response = signUpService.signUpBasic(request); + log.info("[AUTH] {}님 기본 회원가입 완료", request.getEmail()); return ResponseEntity.ok(response); } @@ -62,6 +62,7 @@ public ResponseEntity signUpOauth(@AuthenticationPrincipal PrincipalDeta @GetMapping("/check/nickname/{nickname}") public ResponseEntity checkDuplicateNickname(@PathVariable String nickname) { DuplicateNicknameResponse response = signUpService.checkDuplicateNickname(nickname); + log.info("[AUTH] {} 닉네임 중복 체크 완료", nickname); return ResponseEntity.ok(response); } @@ -70,6 +71,7 @@ public ResponseEntity checkDuplicateNickname(@PathVar @GetMapping("/check/email/{email}") public ResponseEntity checkDuplicateEmail(@PathVariable String email) { DuplicateEmailResponse response = signUpService.checkDuplicateEmail(email); + log.info("[AUTH] {} 닉네임 중복 체크 완료", email); return ResponseEntity.ok(response); } @@ -78,6 +80,7 @@ public ResponseEntity checkDuplicateEmail(@PathVariable @GetMapping("/email/{email}") public ResponseEntity sendSignUpAuthEmail(@PathVariable String email) { mailService.sendSignUpEmail(email); + log.info("[EMAIL] {}님 회원가입 인증 메일 발송 완료", email); return ResponseEntity.ok().body(null); } @@ -87,6 +90,7 @@ public ResponseEntity sendSignUpAuthEmail(@PathVariable Strin public ResponseEntity verifySingUpAuthEmail(@RequestBody EmailVerifyRequest request) { SignUpEmailVerifyResponse response = mailVerifyService.CheckSignUpAuthNum(request.getEmail(), request.getAuthNum()); + log.info("[EMAIL] {}님 회원가입 인증 메일 검증 완료", request.getEmail()); return ResponseEntity.ok().body(response); } diff --git a/src/main/java/com/example/jolvre/auth/jwt/filter/JwtAuthenticationProcessingFilter.java b/src/main/java/com/example/jolvre/auth/jwt/filter/JwtAuthenticationProcessingFilter.java index 45b342a..be4422b 100644 --- a/src/main/java/com/example/jolvre/auth/jwt/filter/JwtAuthenticationProcessingFilter.java +++ b/src/main/java/com/example/jolvre/auth/jwt/filter/JwtAuthenticationProcessingFilter.java @@ -75,7 +75,7 @@ public void checkRefreshTokenAndReIssueAccessToken(HttpServletResponse response, reIssuedRefreshToken); }); } - + /** * [리프레시 토큰 재발급 & DB에 리프레시 토큰 업데이트 메소드] jwtService.createRefreshToken()으로 리프레시 토큰 재발급 후 DB에 재발급한 리프레시 토큰 업데이트 후 @@ -95,7 +95,6 @@ private String reIssueRefreshToken(User user) { */ public void checkAccessTokenAndAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - log.info("[AUTH] : checkAccessTokenAndAuthentication() 호출"); jwtService.extractAccessToken(request) .filter(jwtService::isTokenValid) .ifPresent(accessToken -> jwtService.extractEmail(accessToken) diff --git a/src/main/java/com/example/jolvre/exhibition/api/DiaryController.java b/src/main/java/com/example/jolvre/exhibition/api/DiaryController.java index f8f24f2..5c2e1ae 100644 --- a/src/main/java/com/example/jolvre/exhibition/api/DiaryController.java +++ b/src/main/java/com/example/jolvre/exhibition/api/DiaryController.java @@ -36,8 +36,9 @@ public class DiaryController { public ResponseEntity uploadDiary(@AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long exhibitId, @ModelAttribute DiaryUploadRequest request) { - diaryService.uploadDiary(principalDetails.getId(), exhibitId, request); + diaryService.uploadDiary(principalDetails.getId(), exhibitId, request); + log.info("[Diary] {}님 일기장 업로드 성공", principalDetails.getUser().getEmail()); return ResponseEntity.ok().build(); } @@ -64,8 +65,9 @@ public ResponseEntity getDiary( public ResponseEntity updateDiary(@PathVariable Long diaryId, @PathVariable Long exhibitId, @AuthenticationPrincipal PrincipalDetails principalDetails, @ModelAttribute DiaryUpdateRequest request) { - diaryService.updateDiary(diaryId, exhibitId, principalDetails.getId(), request); + diaryService.updateDiary(diaryId, exhibitId, principalDetails.getId(), request); + log.info("[Diary] {}님 일기장 업데이트 성공 , Diary Id = {}", principalDetails.getUser().getEmail(), diaryId); return ResponseEntity.ok().build(); } @@ -75,7 +77,7 @@ public ResponseEntity deleteDiary(@PathVariable Long diaryId, @PathVariabl @AuthenticationPrincipal PrincipalDetails principalDetails) { diaryService.deleteDiary(diaryId, exhibitId, principalDetails.getId()); - + log.info("[Diary] {}님 일기장 삭제 성공 , Diary Id = {}", principalDetails.getUser().getEmail(), diaryId); return ResponseEntity.ok().build(); } diff --git a/src/main/java/com/example/jolvre/exhibition/api/ExhibitionCommentController.java b/src/main/java/com/example/jolvre/exhibition/api/ExhibitionCommentController.java index 7a6be05..88b673e 100644 --- a/src/main/java/com/example/jolvre/exhibition/api/ExhibitionCommentController.java +++ b/src/main/java/com/example/jolvre/exhibition/api/ExhibitionCommentController.java @@ -32,7 +32,7 @@ public ResponseEntity uploadComment(@PathVariable Long exhibitId, @AuthenticationPrincipal PrincipalDetails principalDetails, @RequestBody ExhibitCommentUploadRequest request) { exhibitCommentService.uploadComment(exhibitId, principalDetails.getId(), request); - + log.info("[EXHIBIT COMMENT] {}님 전시 코멘트 업로드", principalDetails.getUser().getEmail()); return ResponseEntity.ok().build(); } @@ -51,16 +51,17 @@ public ResponseEntity updateComment(@PathVariable Long exhibitId, @AuthenticationPrincipal PrincipalDetails principalDetails, @RequestBody ExhibitCommentUpdateRequest request) { exhibitCommentService.updateComment(commentId, principalDetails.getId(), request); - + log.info("[EXHIBIT COMMENT] {}님 전시 코멘트 업데이트 , Comment Id = {}", principalDetails.getUser().getEmail(), + commentId); return ResponseEntity.ok().build(); } @Operation(summary = "코멘트 삭제", description = "해당 전시에 특정 코멘트를 삭제한다") @DeleteMapping("/{exhibitId}/comment/{commentId}") - public ResponseEntity deleteComment(@PathVariable Long exhibitId, - @PathVariable Long commentId, + public ResponseEntity deleteComment(@PathVariable Long commentId, @AuthenticationPrincipal PrincipalDetails principalDetails) { exhibitCommentService.deleteComment(commentId, principalDetails.getId()); + log.info("[EXHIBIT COMMENT] {}님 전시 코멘트 삭제, Comment Id = {}", principalDetails.getUser().getEmail(), commentId); return ResponseEntity.ok().build(); } diff --git a/src/main/java/com/example/jolvre/exhibition/api/ExhibitionController.java b/src/main/java/com/example/jolvre/exhibition/api/ExhibitionController.java index 647a27c..7bb3b78 100644 --- a/src/main/java/com/example/jolvre/exhibition/api/ExhibitionController.java +++ b/src/main/java/com/example/jolvre/exhibition/api/ExhibitionController.java @@ -41,7 +41,8 @@ public class ExhibitionController { public ResponseEntity uploadExhibit(@ModelAttribute ExhibitUploadRequest request, @AuthenticationPrincipal PrincipalDetails principalDetails) { ExhibitUploadResponse response = exhibitService.uploadExhibit(request, principalDetails.getId()); - + log.info("[EXHIBIT] {}님 전시 업로드 Exhibit Id = {}", principalDetails.getUser().getEmail(), + response.getExhibitId()); return ResponseEntity.ok().body(response); } @@ -59,6 +60,7 @@ public ResponseEntity getAllUserExhibit( public void deleteExhibit(@AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long exhibitId) { exhibitService.deleteExhibit(exhibitId, principalDetails.getId()); + log.info("[EXHIBIT] {}님 전시 삭제 Exhibit Id = {}", principalDetails.getUser().getNickname(), exhibitId); } @Operation(summary = "전시 업데이트") @@ -67,13 +69,16 @@ public void updateExhibit(@AuthenticationPrincipal PrincipalDetails principalDet @PathVariable Long exhibitId, @ModelAttribute ExhibitUpdateRequest request) { exhibitService.updateExhibit(exhibitId, principalDetails.getId(), request); + log.info("[EXHIBIT] {}님 전시 업데이트 Exhibit Id = {}", principalDetails.getUser().getEmail(), exhibitId); } + @Operation(summary = "전시 배포") @PostMapping("/user/{exhibitId}/distribute") public ResponseEntity distributeExhibit(@AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long exhibitId) { exhibitService.distributeExhibit(exhibitId, principalDetails.getId()); + log.info("[EXHIBIT] {}님 전시 배포 , Exhibit Id = {}", principalDetails.getUser().getEmail(), exhibitId); return ResponseEntity.ok().build(); } @@ -101,7 +106,7 @@ public ResponseEntity getExhibit(@PathVariable Long exhibit return ResponseEntity.ok().body(response); } - + @Operation(summary = "초대장 생성", description = "해당 전시에 맞는 초대장을 생성해준다") @GetMapping("/{exhibitId}/invitation") public ResponseEntity createInvitation(@PathVariable Long exhibitId) { diff --git a/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java b/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java index dd901e4..1416ad7 100644 --- a/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java +++ b/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java @@ -1,10 +1,11 @@ package com.example.jolvre.exhibition.dto; import com.example.jolvre.exhibition.dto.DiaryDTO.DiaryInfoResponses; +import com.example.jolvre.exhibition.entity.Diary; import com.example.jolvre.exhibition.entity.Exhibit; import com.example.jolvre.exhibition.entity.ExhibitComment; import com.example.jolvre.user.dto.UserDTO.UserInfoResponse; -import com.querydsl.core.annotations.QueryProjection; +import com.example.jolvre.user.entity.User; import java.util.ArrayList; import java.util.List; import lombok.AllArgsConstructor; @@ -63,6 +64,7 @@ public static class ExhibitUploadRequest { @Builder @Getter + @AllArgsConstructor @NoArgsConstructor public static class ExhibitInfoResponse { private Long id; @@ -84,19 +86,21 @@ public static class ExhibitInfoResponse { private UserInfoResponse userInfoResponse; private DiaryInfoResponses diaryInfoResponses; - public ExhibitInfoResponse(Long id, String title, String thumbnail) { + + public ExhibitInfoResponse(Long id, String title, String thumbnail, User user, List diaries) { this.id = id; this.title = title; this.thumbnail = thumbnail; + this.userInfoResponse = UserInfoResponse.toDTO(user); + this.diaryInfoResponses = DiaryInfoResponses.toDTO(diaries); } - @QueryProjection public ExhibitInfoResponse(Long id, String title, String authorWord, String introduction, String size, String productionMethod, int price, boolean forSale, String thumbnail, List imagesUrl, String image3d, boolean distribute, boolean checkVirtualSpace, String workType, String background2dImage, String background3dImage, - UserInfoResponse userInfoResponse, DiaryInfoResponses diaryInfoResponses) { + User user, List diaries) { this.id = id; this.title = title; this.authorWord = authorWord; @@ -113,8 +117,8 @@ public ExhibitInfoResponse(Long id, String title, String authorWord, String intr this.workType = workType; this.background2dImage = background2dImage; this.background3dImage = background3dImage; - this.userInfoResponse = userInfoResponse; - this.diaryInfoResponses = diaryInfoResponses; + this.userInfoResponse = UserInfoResponse.toDTO(user); + this.diaryInfoResponses = DiaryInfoResponses.toDTO(diaries); } public static ExhibitInfoResponse toDTO(Exhibit exhibit) { diff --git a/src/main/java/com/example/jolvre/exhibition/repository/ExhibitQueryDslRepository.java b/src/main/java/com/example/jolvre/exhibition/repository/ExhibitQueryDslRepository.java index a4dc525..ce3cfb8 100644 --- a/src/main/java/com/example/jolvre/exhibition/repository/ExhibitQueryDslRepository.java +++ b/src/main/java/com/example/jolvre/exhibition/repository/ExhibitQueryDslRepository.java @@ -8,7 +8,6 @@ import com.example.jolvre.exhibition.dto.ExhibitDTO.ExhibitInfoResponse; import com.example.jolvre.exhibition.entity.Exhibit; import com.example.jolvre.user.entity.User; -import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -33,18 +32,18 @@ public List findAllByFilter(boolean distribute, String title) { } public Page findAllByFilter(boolean distribute, String title, Pageable pageable) { - List exhibits = queryFactory - .select(Projections.constructor(ExhibitInfoResponse.class - , exhibit.id - , exhibit.title - , exhibit.thumbnail - )) - .from(exhibit) + List exhibits = queryFactory + .selectFrom(exhibit) + .leftJoin(exhibit.user, user).fetchJoin() + .leftJoin(exhibit.diaries, diary) + .leftJoin(exhibit.exhibitImages, exhibitImage) .where(exhibit.distribute.eq(distribute), containTitle(title)) .orderBy(exhibit.id.desc()) .offset(pageable.getOffset()) .limit(pageable.getPageSize()) .fetch(); + + List exhibitsResponse = exhibits.stream().map(ExhibitInfoResponse::toDTO).toList(); JPAQuery count = queryFactory.select(exhibit.count()) .from(exhibit) @@ -54,7 +53,7 @@ public Page findAllByFilter(boolean distribute, String titl .leftJoin(exhibit.diaries, diary) .where(exhibit.distribute.eq(distribute), containTitle(title)); - return PageableExecutionUtils.getPage(exhibits, pageable, count::fetchOne); + return PageableExecutionUtils.getPage(exhibitsResponse, pageable, count::fetchOne); } private BooleanExpression containTitle(String title) { diff --git a/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java b/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java index ccef84d..69cbb00 100644 --- a/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java +++ b/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java @@ -74,8 +74,7 @@ public ExhibitUploadResponse uploadExhibit(ExhibitUploadRequest request, Long us exhibitImageRepository.saveAll(exhibitImages); } - log.info("[EXHIBITION] : {}님의 {} 업로드 성공", loginUser.getNickname(), exhibit.getTitle()); - + return ExhibitUploadResponse.builder().exhibitId(save.getId()).build(); } @@ -195,7 +194,7 @@ public Page getExhibitInfoByKeyword(String keyword, Pageabl // } // return exhibitRepository.findByDistributeAndTitleContaining(true, keyword, pageable) // .map(ExhibitInfoResponse::toDTO); - +// return exhibitQueryDslRepository.findAllByFilter(true, keyword, pageable); } } diff --git a/src/main/java/com/example/jolvre/group/api/GroupExhibitController.java b/src/main/java/com/example/jolvre/group/api/GroupExhibitController.java index 9df9a2d..d89458c 100644 --- a/src/main/java/com/example/jolvre/group/api/GroupExhibitController.java +++ b/src/main/java/com/example/jolvre/group/api/GroupExhibitController.java @@ -44,7 +44,7 @@ public ResponseEntity createGroup(@ModelAttribute GroupExhibitCreateReques , @AuthenticationPrincipal PrincipalDetails principalDetails) { groupExhibitService.createGroupExhibit(principalDetails.getId(), request); - + log.info("[GROUP EXHIBIT] {}님 단체 전시 생성", principalDetails.getUser().getNickname()); return ResponseEntity.ok().build(); } @@ -79,7 +79,7 @@ public ResponseEntity addExhibit(@AuthenticationPrincipal PrincipalDetails @PathVariable Long groupId, @PathVariable Long exhibitId ) { groupExhibitService.addExhibit(principalDetails.getId(), groupId, exhibitId); - + log.info("[GROUP EXHIBIT] {}님 단체 전시 전시 추가 , Group Id = {}", principalDetails.getUser().getNickname(), groupId); return ResponseEntity.ok().build(); } @@ -100,6 +100,7 @@ public ResponseEntity deleteGroupExhibit(@AuthenticationPrincipal Principa @PathVariable Long groupId) { groupExhibitService.deleteGroup(groupId, principalDetails.getId()); + log.info("[GROUP EXHIBIT] {}님 단체 전시 삭제 , Group Id = {}", principalDetails.getUser().getNickname(), groupId); return ResponseEntity.ok().build(); } @@ -111,6 +112,7 @@ public ResponseEntity addManager(@AuthenticationPrincipal PrincipalDetails @PathVariable Long groupId ) { groupExhibitService.addManager(principalDetails.getId(), toUserId, groupId); + log.info("[GROUP EXHIBIT] {}님 매니저 추가 Group Id = {}", principalDetails.getUser().getNickname(), groupId); return ResponseEntity.ok().build(); } @@ -122,6 +124,7 @@ public ResponseEntity updateGroupExhibit(@AuthenticationPrincipal Principa @ModelAttribute GroupUpdateRequest request) { groupExhibitService.updateGroup(groupId, principalDetails.getId(), request); + log.info("[GROUP EXHIBIT] {}님 단체 전시 수정, Group Id = {}", principalDetails.getUser().getNickname(), groupId); return ResponseEntity.ok().build(); } diff --git a/src/main/java/com/example/jolvre/group/api/GroupInviteController.java b/src/main/java/com/example/jolvre/group/api/GroupInviteController.java index d05712c..43474b6 100644 --- a/src/main/java/com/example/jolvre/group/api/GroupInviteController.java +++ b/src/main/java/com/example/jolvre/group/api/GroupInviteController.java @@ -32,6 +32,8 @@ public ResponseEntity inviteUser(@AuthenticationPrincipal PrincipalDetails pr @PathVariable Long groupId, @RequestBody InviteRequest request) { groupInviteService.inviteUser(principalDetails.getId(), request.getNickname(), groupId); + log.info("[GROUP EXHIBIT] {}님 단체 전시 유저 초대 , Group Id = {}", principalDetails.getUser().getEmail(), groupId); + return ResponseEntity.ok().build(); } @@ -49,6 +51,8 @@ public ResponseEntity checkInvite(@PathVariable Long inviteId, @PathVariable InviteState inviteState, @AuthenticationPrincipal PrincipalDetails principalDetails) { groupInviteService.checkInviteStatus(inviteId, inviteState, principalDetails.getId()); + log.info("[GROUP EXHIBIT] {}님 단체 전시 초대 확인 = {} , Invite Id = {}", principalDetails.getUser().getEmail(), + inviteState, inviteId); return ResponseEntity.ok().build(); } From eaa65caff06654c697f5833862197c55a28c645c Mon Sep 17 00:00:00 2001 From: gosu Date: Fri, 14 Jun 2024 11:00:15 +0900 Subject: [PATCH 06/10] =?UTF-8?q?[infra]=20:=20Application=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/application-actuator.properties | 9 ---- src/main/resources/application-aws.properties | 7 --- src/main/resources/application-dev.properties | 53 +++++++++++++++++++ .../resources/application-email.properties | 9 ---- .../resources/application-prod.properties | 48 +++++++++++++++++ .../resources/application-redis.properties | 2 - .../resources/application-swagger.properties | 0 src/main/resources/application.properties | 24 +-------- 8 files changed, 103 insertions(+), 49 deletions(-) delete mode 100644 src/main/resources/application-actuator.properties delete mode 100644 src/main/resources/application-aws.properties create mode 100644 src/main/resources/application-dev.properties delete mode 100644 src/main/resources/application-email.properties create mode 100644 src/main/resources/application-prod.properties delete mode 100644 src/main/resources/application-redis.properties delete mode 100644 src/main/resources/application-swagger.properties diff --git a/src/main/resources/application-actuator.properties b/src/main/resources/application-actuator.properties deleted file mode 100644 index 85ad896..0000000 --- a/src/main/resources/application-actuator.properties +++ /dev/null @@ -1,9 +0,0 @@ -management.endpoints.web.base-path=/management -# 1. Endpoint all disable -management.endpoints.enabled-by-default=false -# 2. Enable specific endpoints -management.endpoint.info.enabled=true -management.endpoint.health.enabled=true -# 3. Exclude all endpoint for JMX and Expose specific endpoints -management.endpoints.jmx.exposure.exclude=* -management.endpoints.web.exposure.include=info, health \ No newline at end of file diff --git a/src/main/resources/application-aws.properties b/src/main/resources/application-aws.properties deleted file mode 100644 index e177706..0000000 --- a/src/main/resources/application-aws.properties +++ /dev/null @@ -1,7 +0,0 @@ -#S3 -cloud.aws.s3.bucket=${AWS_BUCKET} -cloud.aws.credentials.access-key=${AWS_ACCESS_KEY} -cloud.aws.credentials.secret-key=${AWS_SECRET_KEY} -cloud.aws.region.static=ap-northeast-3 -cloud.aws.region.auto=false -cloud.aws.stack.auto=false \ No newline at end of file diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties new file mode 100644 index 0000000..3ddff32 --- /dev/null +++ b/src/main/resources/application-dev.properties @@ -0,0 +1,53 @@ +spring.datasource.driver-class-name=${DB_CLASS} +spring.datasource.url=${DB_URL} +spring.datasource.username=${DB_USERNAME} +spring.datasource.password=${DB_PASSWORD} +#JPA +spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=update +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.generate-ddl=true +spring.jpa.properties.hibernate.default_batch_fetch_size=100 +#jwt +jwt.secretKey=${JWT_SECRET_KEY} +jwt.access.expiration=3600000 +jwt.access.header=Authorization +jwt.refresh.expiration=1209600000 +jwt.refresh.header=Authorization-refresh +#verifyStudent +verify.student.apiKey=${VERIFY_STUDENT_APIKEY} +#File +spring.servlet.multipart.maxFileSize=20MB +spring.servlet.multipart.maxRequestSize=20MB +#Actoator +management.endpoints.web.base-path=/management +management.endpoints.enabled-by-default=false +management.endpoint.info.enabled=true +management.endpoint.health.enabled=true +management.endpoints.jmx.exposure.exclude=* +management.endpoints.web.exposure.include=info, health +#Aws S3 +cloud.aws.s3.bucket=${AWS_BUCKET} +cloud.aws.credentials.access-key=${AWS_ACCESS_KEY} +cloud.aws.credentials.secret-key=${AWS_SECRET_KEY} +cloud.aws.region.static=ap-northeast-3 +cloud.aws.region.auto=false +cloud.aws.stack.auto=false +#Email +spring.mail.host=smtp.gmail.com +spring.mail.port=587 +spring.mail.username=${MAIL_USERNAME} +spring.mail.password=${MAIL_PASSWORD} +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.debug=true +spring.mail.properties.mail.smtp.starttls.enable=true +spring.mail.properties.mail.mime.charset=UTF-8 +spring.mail.properties.mail.transport.protocol=smtp +#Redis +spring.data.redis.host=${REDIS_HOST} +spring.data.redis.port=${REDIS_PORT} + + + + + diff --git a/src/main/resources/application-email.properties b/src/main/resources/application-email.properties deleted file mode 100644 index 8859818..0000000 --- a/src/main/resources/application-email.properties +++ /dev/null @@ -1,9 +0,0 @@ -spring.mail.host=smtp.gmail.com -spring.mail.port=587 -spring.mail.username=${MAIL_USERNAME} -spring.mail.password=${MAIL_PASSWORD} -spring.mail.properties.mail.smtp.auth=true -spring.mail.properties.mail.debug=true -spring.mail.properties.mail.smtp.starttls.enable=true -spring.mail.properties.mail.mime.charset=UTF-8 -spring.mail.properties.mail.transport.protocol=smtp diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties new file mode 100644 index 0000000..edb3308 --- /dev/null +++ b/src/main/resources/application-prod.properties @@ -0,0 +1,48 @@ +spring.datasource.driver-class-name=${DB_CLASS} +spring.datasource.url=${DB_URL} +spring.datasource.username=${DB_USERNAME} +spring.datasource.password=${DB_PASSWORD} +#JPA +spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=update +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.generate-ddl=true +spring.jpa.properties.hibernate.default_batch_fetch_size=100 +#jwt +jwt.secretKey=${JWT_SECRET_KEY} +jwt.access.expiration=3600000 +jwt.access.header=Authorization +jwt.refresh.expiration=1209600000 +jwt.refresh.header=Authorization-refresh +#verifyStudent +verify.student.apiKey=${VERIFY_STUDENT_APIKEY} +#File +spring.servlet.multipart.maxFileSize=20MB +spring.servlet.multipart.maxRequestSize=20MB +#Actoator +management.endpoints.web.base-path=/management +management.endpoints.enabled-by-default=false +management.endpoint.info.enabled=true +management.endpoint.health.enabled=true +management.endpoints.jmx.exposure.exclude=* +management.endpoints.web.exposure.include=info, health +#Aws S3 +cloud.aws.s3.bucket=${AWS_BUCKET} +cloud.aws.credentials.access-key=${AWS_ACCESS_KEY} +cloud.aws.credentials.secret-key=${AWS_SECRET_KEY} +cloud.aws.region.static=ap-northeast-3 +cloud.aws.region.auto=false +cloud.aws.stack.auto=false +#Email +spring.mail.host=smtp.gmail.com +spring.mail.port=587 +spring.mail.username=${MAIL_USERNAME} +spring.mail.password=${MAIL_PASSWORD} +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.debug=true +spring.mail.properties.mail.smtp.starttls.enable=true +spring.mail.properties.mail.mime.charset=UTF-8 +spring.mail.properties.mail.transport.protocol=smtp +#Redis +spring.data.redis.host=${REDIS_HOST} +spring.data.redis.port=${REDIS_PORT} diff --git a/src/main/resources/application-redis.properties b/src/main/resources/application-redis.properties deleted file mode 100644 index 82adf74..0000000 --- a/src/main/resources/application-redis.properties +++ /dev/null @@ -1,2 +0,0 @@ -spring.data.redis.host=${REDIS_HOST} -spring.data.redis.port=${REDIS_PORT} diff --git a/src/main/resources/application-swagger.properties b/src/main/resources/application-swagger.properties deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8fb9a74..98bb3bb 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,26 +1,6 @@ spring.application.name=Graduate_Minions -spring.profiles.include=oauth,swagger,email,redis,actuator,aws -spring.datasource.driver-class-name=${DB_CLASS} -spring.datasource.url=${DB_URL} -spring.datasource.username=${DB_USERNAME} -spring.datasource.password=${DB_PASSWORD} -#JPA -spring.jpa.show-sql=true -spring.jpa.hibernate.ddl-auto=update -spring.jpa.properties.hibernate.format_sql=true -spring.jpa.generate-ddl=true -spring.jpa.properties.hibernate.default_batch_fetch_size=100 -#jwt -jwt.secretKey=${JWT_SECRET_KEY} -jwt.access.expiration=3600000 -jwt.access.header=Authorization -jwt.refresh.expiration=1209600000 -jwt.refresh.header=Authorization-refresh -#verifyStudent -verify.student.apiKey=${VERIFY_STUDENT_APIKEY} -#File -spring.servlet.multipart.maxFileSize=20MB -spring.servlet.multipart.maxRequestSize=20MB +spring.profiles.active=dev +spring.profiles.include=oauth From 927c6596f583e91ff0aac5c4ae04d50af2e86d85 Mon Sep 17 00:00:00 2001 From: gosu Date: Wed, 19 Jun 2024 17:48:46 +0900 Subject: [PATCH 07/10] =?UTF-8?q?feat=20:=20=EB=B9=84=EB=8F=99=EA=B8=B0=20?= =?UTF-8?q?=EC=A0=84=EC=8B=9C=20=EC=97=85=EB=A1=9C=EB=93=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 ++ .../exhibition/api/ExhibitionController.java | 10 ++++ .../jolvre/exhibition/dto/ExhibitDTO.java | 2 +- .../exhibition/service/ExhibitService.java | 50 ++++++++++++++++++- .../com/example/jolvre/external/ModelApi.java | 15 ++++++ src/main/resources/application-dev.properties | 3 +- src/main/resources/application.properties | 2 +- 7 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/example/jolvre/external/ModelApi.java diff --git a/build.gradle b/build.gradle index e2e6368..bc23ecc 100644 --- a/build.gradle +++ b/build.gradle @@ -72,6 +72,10 @@ dependencies { annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" + //feign + implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' + implementation platform("org.springframework.cloud:spring-cloud-dependencies:2023.0.1") + } tasks.named('test') { diff --git a/src/main/java/com/example/jolvre/exhibition/api/ExhibitionController.java b/src/main/java/com/example/jolvre/exhibition/api/ExhibitionController.java index 7bb3b78..f95df1b 100644 --- a/src/main/java/com/example/jolvre/exhibition/api/ExhibitionController.java +++ b/src/main/java/com/example/jolvre/exhibition/api/ExhibitionController.java @@ -46,6 +46,16 @@ public ResponseEntity uploadExhibit(@ModelAttribute Exhib return ResponseEntity.ok().body(response); } + @Operation(summary = "비동기 전시 업로드") + @PostMapping(path = "/user/async", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity uploadAsyncExhibit(@ModelAttribute ExhibitUploadRequest request, + @AuthenticationPrincipal PrincipalDetails principalDetails) { + ExhibitUploadResponse response = exhibitService.uploadExhibitAsync(request, principalDetails.getId()); + log.info("[EXHIBIT] {}님 전시 업로드 Exhibit Id = {}", principalDetails.getUser().getEmail(), + response.getExhibitId()); + return ResponseEntity.ok().body(response); + } + @Operation(summary = "유저 전체 전시 조회 (유저탭에서)") @GetMapping("/user") public ResponseEntity getAllUserExhibit( diff --git a/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java b/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java index 1416ad7..d1ed791 100644 --- a/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java +++ b/src/main/java/com/example/jolvre/exhibition/dto/ExhibitDTO.java @@ -59,9 +59,9 @@ public static class ExhibitUploadRequest { private String backgroundImage2d; private MultipartFile thumbnail; private List images; - } + @Builder @Getter @AllArgsConstructor diff --git a/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java b/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java index 69cbb00..f38f84f 100644 --- a/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java +++ b/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java @@ -15,11 +15,13 @@ import com.example.jolvre.exhibition.repository.ExhibitImageRepository; import com.example.jolvre.exhibition.repository.ExhibitQueryDslRepository; import com.example.jolvre.exhibition.repository.ExhibitRepository; +import com.example.jolvre.external.ModelApi; import com.example.jolvre.user.entity.User; import com.example.jolvre.user.service.UserService; import jakarta.transaction.Transactional; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -38,8 +40,9 @@ public class ExhibitService { private final DiaryRepository diaryRepository; private final ExhibitCommentRepository exhibitCommentRepository; private final ExhibitQueryDslRepository exhibitQueryDslRepository; + private final ModelApi modelApi; - @Transactional //todo : 모델서버 api가 구현되면 비동기 구현 + @Transactional public ExhibitUploadResponse uploadExhibit(ExhibitUploadRequest request, Long userId) { User loginUser = userService.getUserById(userId); @@ -74,7 +77,50 @@ public ExhibitUploadResponse uploadExhibit(ExhibitUploadRequest request, Long us exhibitImageRepository.saveAll(exhibitImages); } - + + return ExhibitUploadResponse.builder().exhibitId(save.getId()).build(); + } + + public ExhibitUploadResponse uploadExhibitAsync(ExhibitUploadRequest request, Long userId) { + User loginUser = userService.getUserById(userId); + + Exhibit exhibit = Exhibit.builder() + .title(request.getTitle()) + .authorWord(request.getAuthorWord()) + .introduction(request.getIntroduction()) + .productionMethod(request.getProductionMethod()) + .forSale(request.isForSale()) + .price(request.getPrice()) + .size(request.getSize()) + .thumbnail(s3Service.uploadImage(request.getThumbnail())) + .user(loginUser) + .workType(request.getWorkType()) + .checkVirtualSpace(request.isCheckVirtualSpace()) + .background2dImage(request.getBackgroundImage2d()) + .background3dImage(request.getBackgroundImage3d()) + .build(); + + Exhibit save = exhibitRepository.save(exhibit); + if (request.getImages() != null) { + List exhibitImages = new ArrayList<>(); + + s3Service.uploadImages(request.getImages()).forEach( + url -> { + ExhibitImage image = ExhibitImage.builder().url(url).build(); + exhibit.addImage(image); + exhibitImages.add(image); + } + ); + + exhibitImageRepository.saveAll(exhibitImages); + } + + CompletableFuture uCompletableFuture = CompletableFuture.supplyAsync(() -> { + save.setImage3d(modelApi.get3DModelUrl(request.getThumbnail())); + exhibitRepository.save(save); + return null; + }); + return ExhibitUploadResponse.builder().exhibitId(save.getId()).build(); } diff --git a/src/main/java/com/example/jolvre/external/ModelApi.java b/src/main/java/com/example/jolvre/external/ModelApi.java new file mode 100644 index 0000000..56bdea7 --- /dev/null +++ b/src/main/java/com/example/jolvre/external/ModelApi.java @@ -0,0 +1,15 @@ +package com.example.jolvre.external; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.multipart.MultipartFile; + +@Component +@FeignClient(name = "3D Model API", url = "https://model.com/") +public interface ModelApi { + @GetMapping("/model/async") + String get3DModelUrl(@RequestBody MultipartFile image); +} + diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 3ddff32..ab092cb 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -46,7 +46,8 @@ spring.mail.properties.mail.transport.protocol=smtp #Redis spring.data.redis.host=${REDIS_HOST} spring.data.redis.port=${REDIS_PORT} - +#Model API +model.api.url=${MODEL_API_URL} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 98bb3bb..89957c1 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ spring.application.name=Graduate_Minions -spring.profiles.active=dev +spring.profiles.active=dev,prod spring.profiles.include=oauth From a374215593d1415c79a0d4fff05d5eb619d9cedb Mon Sep 17 00:00:00 2001 From: gosu Date: Wed, 19 Jun 2024 18:33:07 +0900 Subject: [PATCH 08/10] =?UTF-8?q?feat=20:=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 레디스 캐싱 --- .../jolvre/GraduateMinionsApplication.java | 2 ++ .../jolvre/common/config/RedisConfig.java | 21 ++++++++++++ .../example/jolvre/common/util/RedisUtil.java | 15 ++++++++ .../exhibition/api/ExhibitLikeController.java | 26 ++++++++++++++ .../jolvre/exhibition/entity/Exhibit.java | 7 ++-- .../service/ExhibitLikeService.java | 32 +++++++++++++++++ .../exhibition/service/ExhibitService.java | 30 +++++++--------- .../com/example/jolvre/external/ModelApi.java | 34 +++++++++++-------- 8 files changed, 130 insertions(+), 37 deletions(-) create mode 100644 src/main/java/com/example/jolvre/exhibition/api/ExhibitLikeController.java create mode 100644 src/main/java/com/example/jolvre/exhibition/service/ExhibitLikeService.java diff --git a/src/main/java/com/example/jolvre/GraduateMinionsApplication.java b/src/main/java/com/example/jolvre/GraduateMinionsApplication.java index 8f96e83..8496357 100644 --- a/src/main/java/com/example/jolvre/GraduateMinionsApplication.java +++ b/src/main/java/com/example/jolvre/GraduateMinionsApplication.java @@ -4,12 +4,14 @@ import java.util.TimeZone; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.scheduling.annotation.EnableAsync; @EnableAsync @EnableJpaAuditing @SpringBootApplication +@EnableFeignClients public class GraduateMinionsApplication { public static void main(String[] args) { SpringApplication.run(GraduateMinionsApplication.class, args); diff --git a/src/main/java/com/example/jolvre/common/config/RedisConfig.java b/src/main/java/com/example/jolvre/common/config/RedisConfig.java index 7fe2d8b..7bf4c42 100644 --- a/src/main/java/com/example/jolvre/common/config/RedisConfig.java +++ b/src/main/java/com/example/jolvre/common/config/RedisConfig.java @@ -5,6 +5,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { @@ -17,4 +19,23 @@ public class RedisConfig { public RedisConnectionFactory redisConnectionFactory() { return new LettuceConnectionFactory(host, port); } + + @Bean + public RedisTemplate redisTemplate() { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory()); + + // 일반적인 key:value의 경우 시리얼라이저 + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + + // Hash를 사용할 경우 시리얼라이저 + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashValueSerializer(new StringRedisSerializer()); + + // 모든 경우 + redisTemplate.setDefaultSerializer(new StringRedisSerializer()); + + return redisTemplate; + } } diff --git a/src/main/java/com/example/jolvre/common/util/RedisUtil.java b/src/main/java/com/example/jolvre/common/util/RedisUtil.java index 8be098b..25fd887 100644 --- a/src/main/java/com/example/jolvre/common/util/RedisUtil.java +++ b/src/main/java/com/example/jolvre/common/util/RedisUtil.java @@ -1,7 +1,9 @@ package com.example.jolvre.common.util; import java.time.Duration; +import java.util.concurrent.TimeUnit; import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Service; @@ -18,9 +20,22 @@ public String getData(String key) {//지정된 키(key)에 해당하는 데이 public void setData(String key, String value) {//지정된 키(key)에 값을 저장하는 메서드 ValueOperations valueOperations = redisTemplate.opsForValue(); + redisTemplate.expire(key, 8, TimeUnit.HOURS); valueOperations.set(key, value); } + public Object getHashData(String key, Object hashKey) { + HashOperations hashOperations = redisTemplate.opsForHash(); + return hashOperations.get(key, hashKey); + } + + public void setHashData(String key, String hashKey, String value) { + HashOperations hashOperations = redisTemplate.opsForHash(); + redisTemplate.expire(key, 6, TimeUnit.HOURS); + hashOperations.put(key, hashKey, value); + + } + public void setDataExpire(String key, String value, long duration) {//지정된 키(key)에 값을 저장하고, 지정된 시간(duration) 후에 데이터가 만료되도록 설정하는 메서드 ValueOperations valueOperations = redisTemplate.opsForValue(); diff --git a/src/main/java/com/example/jolvre/exhibition/api/ExhibitLikeController.java b/src/main/java/com/example/jolvre/exhibition/api/ExhibitLikeController.java new file mode 100644 index 0000000..6f47810 --- /dev/null +++ b/src/main/java/com/example/jolvre/exhibition/api/ExhibitLikeController.java @@ -0,0 +1,26 @@ +package com.example.jolvre.exhibition.api; + +import com.example.jolvre.auth.PrincipalDetails; +import com.example.jolvre.exhibition.service.ExhibitLikeService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/exhibit/like") +public class ExhibitLikeController { + private final ExhibitLikeService exhibitLikeService; + + @PostMapping("/{exhibitId}") + public ResponseEntity likeUpExhibit(@AuthenticationPrincipal PrincipalDetails principalDetails, + @PathVariable Long exhibitId) { + exhibitLikeService.likeUpExhibit(exhibitId, principalDetails.getId()); + + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/com/example/jolvre/exhibition/entity/Exhibit.java b/src/main/java/com/example/jolvre/exhibition/entity/Exhibit.java index 4c15810..cd99b56 100644 --- a/src/main/java/com/example/jolvre/exhibition/entity/Exhibit.java +++ b/src/main/java/com/example/jolvre/exhibition/entity/Exhibit.java @@ -41,7 +41,7 @@ public class Exhibit extends BaseTimeEntity { private String title; @Column - private int up; //추천수 + private int likes = 0; //추천수 @Column(length = 1000) private String authorWord; //작가의 한마디 @@ -98,7 +98,6 @@ public Exhibit(User user, String title, String authorWord, String introduction, this.productionMethod = productionMethod; this.price = price; this.forSale = forSale; - this.up = 0; this.distribute = false; this.thumbnail = thumbnail; this.checkVirtualSpace = checkVirtualSpace; @@ -132,8 +131,8 @@ public void addImage3D(String imageUrl) { this.image3d = imageUrl; } - public void up() { - this.up += 1; + public void likeUp() { + this.likes += 1; } public void startDistribute() { diff --git a/src/main/java/com/example/jolvre/exhibition/service/ExhibitLikeService.java b/src/main/java/com/example/jolvre/exhibition/service/ExhibitLikeService.java new file mode 100644 index 0000000..79bac79 --- /dev/null +++ b/src/main/java/com/example/jolvre/exhibition/service/ExhibitLikeService.java @@ -0,0 +1,32 @@ +package com.example.jolvre.exhibition.service; + +import com.example.jolvre.common.error.exhibition.ExhibitNotFoundException; +import com.example.jolvre.common.util.RedisUtil; +import com.example.jolvre.exhibition.entity.Exhibit; +import com.example.jolvre.exhibition.repository.ExhibitRepository; +import com.example.jolvre.user.service.UserService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ExhibitLikeService { + private final ExhibitRepository exhibitRepository; + private final UserService userService; + private final RedisUtil redisUtil; + + //전시 좋아요 (한 전시당 8시간마다 좋아요 가능) + public void likeUpExhibit(Long exhibitId, Long userId) { + String redisKey = "LIKE_" + exhibitId + userId; + + if (redisUtil.getData(redisKey) != null) { + return; + } + + Exhibit exhibit = exhibitRepository.findById(exhibitId).orElseThrow(ExhibitNotFoundException::new); + exhibit.likeUp(); + exhibitRepository.save(exhibit); + + redisUtil.setData(redisKey, String.valueOf(exhibit.getLikes())); + } +} diff --git a/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java b/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java index f38f84f..b093f06 100644 --- a/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java +++ b/src/main/java/com/example/jolvre/exhibition/service/ExhibitService.java @@ -15,7 +15,6 @@ import com.example.jolvre.exhibition.repository.ExhibitImageRepository; import com.example.jolvre.exhibition.repository.ExhibitQueryDslRepository; import com.example.jolvre.exhibition.repository.ExhibitRepository; -import com.example.jolvre.external.ModelApi; import com.example.jolvre.user.entity.User; import com.example.jolvre.user.service.UserService; import jakarta.transaction.Transactional; @@ -40,8 +39,7 @@ public class ExhibitService { private final DiaryRepository diaryRepository; private final ExhibitCommentRepository exhibitCommentRepository; private final ExhibitQueryDslRepository exhibitQueryDslRepository; - private final ModelApi modelApi; - + @Transactional public ExhibitUploadResponse uploadExhibit(ExhibitUploadRequest request, Long userId) { @@ -116,7 +114,7 @@ public ExhibitUploadResponse uploadExhibitAsync(ExhibitUploadRequest request, Lo } CompletableFuture uCompletableFuture = CompletableFuture.supplyAsync(() -> { - save.setImage3d(modelApi.get3DModelUrl(request.getThumbnail())); +// save.setImage3d(model3D.get3DModelUrl(request.getThumbnail())); //여기다 모델 서버 연결 exhibitRepository.save(save); return null; }); @@ -124,7 +122,7 @@ public ExhibitUploadResponse uploadExhibitAsync(ExhibitUploadRequest request, Lo return ExhibitUploadResponse.builder().exhibitId(save.getId()).build(); } - @Transactional + @Transactional //상세 전시 조회 public ExhibitInfoResponse getExhibitInfo(Long id) { Exhibit exhibit = exhibitRepository.findById(id).orElseThrow(ExhibitNotFoundException::new); @@ -140,7 +138,7 @@ public ExhibitInfoResponses getAllExhibitInfo() { .build(); } - @Transactional + @Transactional //해당 유저에 모든 전시 조회 public ExhibitInfoResponses getAllUserExhibitInfo(Long userId) { User user = userService.getUserById(userId); @@ -160,7 +158,7 @@ public ExhibitInfoResponses getAllExhibitInfoByWorkType(String workType) { .build(); } - @Transactional + @Transactional // 전시 삭제 public void deleteExhibit(Long exhibitId, Long userId) { exhibitImageRepository.deleteAllByExhibitId(exhibitId); diaryRepository.deleteAllByExhibitId(exhibitId); @@ -171,18 +169,18 @@ public void deleteExhibit(Long exhibitId, Long userId) { exhibitRepository.delete(exhibit); } - @Transactional + @Transactional // 전시 아이디를 통한 전시 엔티티 조회 public Exhibit getExhibitById(Long id) { return exhibitRepository.findById(id).orElseThrow(ExhibitNotFoundException::new); } - @Transactional + @Transactional // 유저 아이디 + 전시 아이디 를 통한 전시 엔티티 조회 public Exhibit getExhibitByIdAndUserId(Long exhibitId, Long userId) { return exhibitRepository.findByIdAndUserId(exhibitId, userId) .orElseThrow(ExhibitNotFoundException::new); } - @Transactional + @Transactional //전시 배포 처리 public void distributeExhibit(Long exhibitId, Long userId) { Exhibit exhibit = exhibitRepository.findByIdAndUserId(exhibitId, userId) .orElseThrow(ExhibitNotFoundException::new); @@ -192,7 +190,7 @@ public void distributeExhibit(Long exhibitId, Long userId) { exhibitRepository.save(exhibit); } - @Transactional + @Transactional //전시 업데이트 public void updateExhibit(Long exhibitId, Long userId, ExhibitUpdateRequest request) { Exhibit exhibit = exhibitRepository.findByIdAndUserId(exhibitId, userId).orElseThrow( ExhibitNotFoundException::new); @@ -221,7 +219,7 @@ public void updateExhibit(Long exhibitId, Long userId, ExhibitUpdateRequest requ exhibitRepository.save(exhibit); } - @Transactional + @Transactional //초대장 생성 public ExhibitInvitationResponse createInvitation(Long exhibitId) { Exhibit exhibit = exhibitRepository.findById(exhibitId).orElseThrow( ExhibitNotFoundException::new); @@ -234,13 +232,9 @@ public ExhibitInvitationResponse createInvitation(Long exhibitId) { } + // 키워드 기반 전시 조회 public Page getExhibitInfoByKeyword(String keyword, Pageable pageable) { -// if (keyword == null) { -// return exhibitRepository.findAllByDistribute(true, pageable).map(ExhibitInfoResponse::toDTO); -// } -// return exhibitRepository.findByDistributeAndTitleContaining(true, keyword, pageable) -// .map(ExhibitInfoResponse::toDTO); -// return exhibitQueryDslRepository.findAllByFilter(true, keyword, pageable); } + } diff --git a/src/main/java/com/example/jolvre/external/ModelApi.java b/src/main/java/com/example/jolvre/external/ModelApi.java index 56bdea7..c2fc00c 100644 --- a/src/main/java/com/example/jolvre/external/ModelApi.java +++ b/src/main/java/com/example/jolvre/external/ModelApi.java @@ -1,15 +1,19 @@ -package com.example.jolvre.external; - -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.multipart.MultipartFile; - -@Component -@FeignClient(name = "3D Model API", url = "https://model.com/") -public interface ModelApi { - @GetMapping("/model/async") - String get3DModelUrl(@RequestBody MultipartFile image); -} - +//package com.example.jolvre.external; +// +//import org.springframework.cloud.openfeign.FeignClient; +//import org.springframework.stereotype.Component; +//import org.springframework.web.bind.annotation.GetMapping; +//import org.springframework.web.bind.annotation.RequestBody; +//import org.springframework.web.multipart.MultipartFile; +// +//@Component +//public class ModelApi { +// +// @Component +// @FeignClient +// public interface Model3D { +// @GetMapping("/model/async") +// String get3DModelUrl(@RequestBody MultipartFile image); +// } +//} +// From 2e5e21203ef00cea4e3abb7f9af8ed62fb6350c1 Mon Sep 17 00:00:00 2001 From: gosu Date: Wed, 19 Jun 2024 18:52:10 +0900 Subject: [PATCH 09/10] =?UTF-8?q?refactor=20:=20uri=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기존 - 단수형 변경 - 복수형 --- .../exhibition/api/DiaryController.java | 14 ++++++------- .../exhibition/api/ExhibitLikeController.java | 4 ++-- .../api/ExhibitionCommentController.java | 2 +- .../exhibition/api/ExhibitionController.java | 18 ++++++++--------- .../group/api/GroupExhibitController.java | 20 +++++++++---------- .../group/api/GroupInviteController.java | 10 ++++------ .../jolvre/user/api/UserController.java | 6 +++--- 7 files changed, 36 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/example/jolvre/exhibition/api/DiaryController.java b/src/main/java/com/example/jolvre/exhibition/api/DiaryController.java index 5c2e1ae..4c6b649 100644 --- a/src/main/java/com/example/jolvre/exhibition/api/DiaryController.java +++ b/src/main/java/com/example/jolvre/exhibition/api/DiaryController.java @@ -27,12 +27,12 @@ @RestController @Slf4j @RequiredArgsConstructor -@RequestMapping("/api/v1/diary") +@RequestMapping("/api/v1/") public class DiaryController { private final DiaryService diaryService; @Operation(summary = "일기장 업로드") - @PostMapping(path = "/{exhibitId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @PostMapping(path = "/exhibit/{exhibitId}/diaries", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity uploadDiary(@AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long exhibitId, @ModelAttribute DiaryUploadRequest request) { @@ -43,7 +43,7 @@ public ResponseEntity uploadDiary(@AuthenticationPrincipal PrincipalDetail } @Operation(summary = "모든 일기장 조회") - @GetMapping("/{exhibitId}") + @GetMapping("/exhibit/{exhibitId}/diaries") public ResponseEntity getAllDiary( @PathVariable Long exhibitId) { DiaryInfoResponses responses = diaryService.getAllDiaryInfo(exhibitId); @@ -52,7 +52,7 @@ public ResponseEntity getAllDiary( } @Operation(summary = "일기장 상세 조회") - @GetMapping("/{exhibitId}/{diaryId}") + @GetMapping("/exhibit/{exhibitId}/diaries/{diaryId}") public ResponseEntity getDiary( @PathVariable Long diaryId, @PathVariable Long exhibitId) { DiaryInfoResponse responses = diaryService.getDiaryInfo(diaryId, exhibitId); @@ -61,7 +61,7 @@ public ResponseEntity getDiary( } @Operation(summary = "일기장 업데이트") - @PatchMapping(path = "/user/{exhibitId}/{diaryId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @PatchMapping(path = "/exhibit/{exhibitId}/diaries/{diaryId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity updateDiary(@PathVariable Long diaryId, @PathVariable Long exhibitId, @AuthenticationPrincipal PrincipalDetails principalDetails, @ModelAttribute DiaryUpdateRequest request) { @@ -72,7 +72,7 @@ public ResponseEntity updateDiary(@PathVariable Long diaryId, @PathVariabl } @Operation(summary = "일기장 삭제") - @DeleteMapping("/user/{exhibitId}/{diaryId}") + @DeleteMapping("/exhibit/{exhibitId}/diaries/{diaryId}") public ResponseEntity deleteDiary(@PathVariable Long diaryId, @PathVariable Long exhibitId, @AuthenticationPrincipal PrincipalDetails principalDetails) { @@ -82,7 +82,7 @@ public ResponseEntity deleteDiary(@PathVariable Long diaryId, @PathVariabl } @Operation(summary = "일기장 모든 사진 조회", description = "해당 전시의 모든 일기장 사진을 조회합니다") - @GetMapping("/images/{exhibitId}") + @GetMapping("/diary/{exhibitId}/diaries/images") public ResponseEntity getDiaryImages(@PathVariable Long exhibitId) { DiaryImagesResponse response = diaryService.getDiaryImages(exhibitId); diff --git a/src/main/java/com/example/jolvre/exhibition/api/ExhibitLikeController.java b/src/main/java/com/example/jolvre/exhibition/api/ExhibitLikeController.java index 6f47810..fb340f8 100644 --- a/src/main/java/com/example/jolvre/exhibition/api/ExhibitLikeController.java +++ b/src/main/java/com/example/jolvre/exhibition/api/ExhibitLikeController.java @@ -12,11 +12,11 @@ @RestController @RequiredArgsConstructor -@RequestMapping("/api/v1/exhibit/like") +@RequestMapping("/api/v1/exhibits") public class ExhibitLikeController { private final ExhibitLikeService exhibitLikeService; - @PostMapping("/{exhibitId}") + @PostMapping("/{exhibitId}/like") public ResponseEntity likeUpExhibit(@AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long exhibitId) { exhibitLikeService.likeUpExhibit(exhibitId, principalDetails.getId()); diff --git a/src/main/java/com/example/jolvre/exhibition/api/ExhibitionCommentController.java b/src/main/java/com/example/jolvre/exhibition/api/ExhibitionCommentController.java index 88b673e..2c63f3a 100644 --- a/src/main/java/com/example/jolvre/exhibition/api/ExhibitionCommentController.java +++ b/src/main/java/com/example/jolvre/exhibition/api/ExhibitionCommentController.java @@ -22,7 +22,7 @@ @RestController @RequiredArgsConstructor @Slf4j -@RequestMapping("/api/v1/exhibit") +@RequestMapping("/api/v1/exhibits") public class ExhibitionCommentController { private final ExhibitCommentService exhibitCommentService; diff --git a/src/main/java/com/example/jolvre/exhibition/api/ExhibitionController.java b/src/main/java/com/example/jolvre/exhibition/api/ExhibitionController.java index f95df1b..77f0713 100644 --- a/src/main/java/com/example/jolvre/exhibition/api/ExhibitionController.java +++ b/src/main/java/com/example/jolvre/exhibition/api/ExhibitionController.java @@ -32,12 +32,12 @@ @RestController @Slf4j @RequiredArgsConstructor -@RequestMapping("/api/v1/exhibit") +@RequestMapping("/api/v1/exhibits") public class ExhibitionController { private final ExhibitService exhibitService; @Operation(summary = "전시 업로드") - @PostMapping(path = "/user", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity uploadExhibit(@ModelAttribute ExhibitUploadRequest request, @AuthenticationPrincipal PrincipalDetails principalDetails) { ExhibitUploadResponse response = exhibitService.uploadExhibit(request, principalDetails.getId()); @@ -47,7 +47,7 @@ public ResponseEntity uploadExhibit(@ModelAttribute Exhib } @Operation(summary = "비동기 전시 업로드") - @PostMapping(path = "/user/async", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @PostMapping(path = "/async", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity uploadAsyncExhibit(@ModelAttribute ExhibitUploadRequest request, @AuthenticationPrincipal PrincipalDetails principalDetails) { ExhibitUploadResponse response = exhibitService.uploadExhibitAsync(request, principalDetails.getId()); @@ -56,8 +56,8 @@ public ResponseEntity uploadAsyncExhibit(@ModelAttribute return ResponseEntity.ok().body(response); } - @Operation(summary = "유저 전체 전시 조회 (유저탭에서)") - @GetMapping("/user") + @Operation(summary = "해당 유저의 모든 전시 조회 (유저탭에서)") + @GetMapping("/me") public ResponseEntity getAllUserExhibit( @AuthenticationPrincipal PrincipalDetails principalDetails) { ExhibitInfoResponses response = exhibitService.getAllUserExhibitInfo(principalDetails.getId()); @@ -66,7 +66,7 @@ public ResponseEntity getAllUserExhibit( } @Operation(summary = "전시 삭제") - @DeleteMapping("/user/{exhibitId}") + @DeleteMapping("/me/{exhibitId}") public void deleteExhibit(@AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long exhibitId) { exhibitService.deleteExhibit(exhibitId, principalDetails.getId()); @@ -74,7 +74,7 @@ public void deleteExhibit(@AuthenticationPrincipal PrincipalDetails principalDet } @Operation(summary = "전시 업데이트") - @PatchMapping(path = "/user/{exhibitId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @PatchMapping(path = "/me/{exhibitId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public void updateExhibit(@AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long exhibitId, @ModelAttribute ExhibitUpdateRequest request) { @@ -84,7 +84,7 @@ public void updateExhibit(@AuthenticationPrincipal PrincipalDetails principalDet @Operation(summary = "전시 배포") - @PostMapping("/user/{exhibitId}/distribute") + @PostMapping("/me/{exhibitId}/distribute") public ResponseEntity distributeExhibit(@AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long exhibitId) { exhibitService.distributeExhibit(exhibitId, principalDetails.getId()); @@ -102,7 +102,7 @@ public ResponseEntity getAllExhibit() { } @Operation(summary = "전체 작품 종류별 전시 조회 (전시탭에서)") - @GetMapping("/exhibits/{workType}") + @GetMapping("/{workType}") public ResponseEntity getAllExhibit(@PathVariable String workType) { ExhibitInfoResponses responses = exhibitService.getAllExhibitInfoByWorkType(workType); diff --git a/src/main/java/com/example/jolvre/group/api/GroupExhibitController.java b/src/main/java/com/example/jolvre/group/api/GroupExhibitController.java index d89458c..4466436 100644 --- a/src/main/java/com/example/jolvre/group/api/GroupExhibitController.java +++ b/src/main/java/com/example/jolvre/group/api/GroupExhibitController.java @@ -34,7 +34,7 @@ @RestController @Slf4j @RequiredArgsConstructor -@RequestMapping("/api/v1/group") +@RequestMapping("/api/v1/groups") public class GroupExhibitController { private final GroupExhibitService groupExhibitService; @@ -49,7 +49,7 @@ public ResponseEntity createGroup(@ModelAttribute GroupExhibitCreateReques } @Operation(summary = "단체 전시 조회 (단체 전시 탭에서)") - @GetMapping("/groups") + @GetMapping() public ResponseEntity getAllGroupExhibit() { GroupExhibitInfoResponses responses = groupExhibitService.getAllGroupExhibitInfo(); @@ -57,7 +57,7 @@ public ResponseEntity getAllGroupExhibit() { } @Operation(summary = "단체 전시 상세 조회") - @GetMapping("/groups/{groupId}") + @GetMapping("/{groupId}") public ResponseEntity getGroupExhibit(@PathVariable Long groupId) { GroupExhibitInfoResponse response = groupExhibitService.getGroupExhibitInfo(groupId); @@ -65,7 +65,7 @@ public ResponseEntity getGroupExhibit(@PathVariable Lo } @Operation(summary = "유저의 단체 전시 조회(유저 탭에서)") - @GetMapping("/user") + @GetMapping("/me") public ResponseEntity getAllUserGroupExhibit( @AuthenticationPrincipal PrincipalDetails principalDetails) { GroupExhibitInfoResponses responses = groupExhibitService.getAllUserGroupExhibitInfo(principalDetails.getId()); @@ -74,7 +74,7 @@ public ResponseEntity getAllUserGroupExhibit( } @Operation(summary = "단체 전시 전시 추가") - @PostMapping("/{groupId}/exhibit/{exhibitId}") + @PostMapping("/{groupId}/exhibits/{exhibitId}") public ResponseEntity addExhibit(@AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long groupId, @PathVariable Long exhibitId ) { @@ -84,7 +84,7 @@ public ResponseEntity addExhibit(@AuthenticationPrincipal PrincipalDetails } @Operation(summary = "단체 전시 회원 조회") - @GetMapping("/groups/{groupId}/users") + @GetMapping("{groupId}/members") public ResponseEntity getGroupExhibitUsers( @AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long groupId) { @@ -95,7 +95,7 @@ public ResponseEntity getGroupExhibitUsers( } @Operation(summary = "단체 전시 삭제", description = "단체 전시를 삭제합니다") - @DeleteMapping("/groups/{groupId}") + @DeleteMapping("/{groupId}") public ResponseEntity deleteGroupExhibit(@AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long groupId) { @@ -118,7 +118,7 @@ public ResponseEntity addManager(@AuthenticationPrincipal PrincipalDetails } @Operation(summary = "단체 전시 수정", description = "단체 전시를 수정합니다") - @PatchMapping(path = "/groups/{groupId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @PatchMapping(path = "/{groupId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity updateGroupExhibit(@AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long groupId, @ModelAttribute GroupUpdateRequest request) { @@ -130,7 +130,7 @@ public ResponseEntity updateGroupExhibit(@AuthenticationPrincipal Principa } @Operation(summary = "단체 전시 초대장 생성", description = "단체 전시 초대장을 생성한다") - @GetMapping("/groups/{groupId}/invitaion") + @GetMapping("/{groupId}/invitaion") public ResponseEntity createInvitation(@PathVariable Long groupId) { GroupInvitationResponse response = groupExhibitService.createInvitation(groupId); @@ -138,7 +138,7 @@ public ResponseEntity createInvitation(@PathVariable Lo } @Operation(summary = "키워드를 통한 조회", description = "키워드를 통해 단체 전시회 정보를 가져온다") - @GetMapping("/groups/keyword") + @GetMapping("/keyword") public ResponseEntity> searchByKeyword( @RequestParam(required = false) String keyword, @RequestParam(value = "page", defaultValue = "1") int page, diff --git a/src/main/java/com/example/jolvre/group/api/GroupInviteController.java b/src/main/java/com/example/jolvre/group/api/GroupInviteController.java index 43474b6..f8bbf55 100644 --- a/src/main/java/com/example/jolvre/group/api/GroupInviteController.java +++ b/src/main/java/com/example/jolvre/group/api/GroupInviteController.java @@ -15,19 +15,17 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Tag(name = "Group Invite", description = "단체전시 초대 API") @RestController @Slf4j @RequiredArgsConstructor -@RequestMapping("/api/v1/group/invite") public class GroupInviteController { private final GroupInviteService groupInviteService; - @Operation(summary = "유저 초대1") - @PostMapping("/{groupId}") + @Operation(summary = "유저 초대") + @PostMapping("/api/v1/groups/{groupId}/invite") public ResponseEntity inviteUser(@AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long groupId, @RequestBody InviteRequest request) { @@ -38,7 +36,7 @@ public ResponseEntity inviteUser(@AuthenticationPrincipal PrincipalDetails pr } @Operation(summary = "자신의 초대 현황 조회") - @GetMapping("/user") + @GetMapping("/api/v1/me/invites") public ResponseEntity getAllInvite(@AuthenticationPrincipal PrincipalDetails principalDetails) { InviteResponses responses = groupInviteService.getAllInvite(principalDetails.getId()); @@ -46,7 +44,7 @@ public ResponseEntity getAllInvite(@AuthenticationPrincipal Pri } @Operation(summary = "자신의 초대 수락 Or 거절") - @PostMapping("/user/{inviteId}/{inviteState}") + @PostMapping("/api/v1/me/invites/{inviteId}/{inviteState}") public ResponseEntity checkInvite(@PathVariable Long inviteId, @PathVariable InviteState inviteState, @AuthenticationPrincipal PrincipalDetails principalDetails) { diff --git a/src/main/java/com/example/jolvre/user/api/UserController.java b/src/main/java/com/example/jolvre/user/api/UserController.java index 668bc06..b8b0900 100644 --- a/src/main/java/com/example/jolvre/user/api/UserController.java +++ b/src/main/java/com/example/jolvre/user/api/UserController.java @@ -19,7 +19,7 @@ @Tag(name = "User", description = "유저 API") @RestController -@RequestMapping("/api/v1/user") +@RequestMapping("/api/v1/users") @Slf4j @RequiredArgsConstructor public class UserController { @@ -27,7 +27,7 @@ public class UserController { private final UserService userService; @Operation(summary = "유저 정보 조회") - @GetMapping + @GetMapping("/me") public ResponseEntity getUserInfo(@AuthenticationPrincipal PrincipalDetails principalDetails) { log.info("[USER] : {} 님 정보 조회", principalDetails.getId()); @@ -35,7 +35,7 @@ public ResponseEntity getUserInfo(@AuthenticationPrincipal Pri } @Operation(summary = "유저 정보 수정") - @PatchMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @PatchMapping(path = "/me", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity updateUser(@ModelAttribute UserUpdateRequest request , @AuthenticationPrincipal PrincipalDetails principalDetails) { log.info("[USER] : {} 님 정보 수정", principalDetails.getId()); From 47e1d2a8931f5b1b21cf9e82b55ca3efb2277ad3 Mon Sep 17 00:00:00 2001 From: gosu Date: Wed, 19 Jun 2024 18:58:53 +0900 Subject: [PATCH 10/10] =?UTF-8?q?feat=20:=20=EC=A0=84=EC=8B=9C=20=EC=A2=8B?= =?UTF-8?q?=EC=95=84=EC=9A=94=20=EA=B8=B0=EB=8A=A5=20swagger=20=EB=AA=85?= =?UTF-8?q?=EC=84=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/jolvre/common/error/ErrorCode.java | 1 + .../exhibition/ExhibitLikeDuplicationException.java | 10 ++++++++++ .../jolvre/exhibition/api/ExhibitLikeController.java | 4 ++++ .../exhibition/api/ExhibitionCommentController.java | 2 ++ .../jolvre/exhibition/service/ExhibitLikeService.java | 3 ++- 5 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/example/jolvre/common/error/exhibition/ExhibitLikeDuplicationException.java diff --git a/src/main/java/com/example/jolvre/common/error/ErrorCode.java b/src/main/java/com/example/jolvre/common/error/ErrorCode.java index d760716..b8d0aeb 100644 --- a/src/main/java/com/example/jolvre/common/error/ErrorCode.java +++ b/src/main/java/com/example/jolvre/common/error/ErrorCode.java @@ -17,6 +17,7 @@ public enum ErrorCode { USER_ALREADY_EXIST("U03", "User is already exists.", HttpStatus.BAD_REQUEST.value()), //Exhibit EXHIBIT_NOT_FOUND("E01", "Exhibit is not found", HttpStatus.BAD_REQUEST.value()), + EXHIBIT_LIKE_DUPLICATION("E02", "ExhibitLike is Duplicate", HttpStatus.BAD_REQUEST.value()), //Diary DIARY_NOT_FOUND("D01", "Diary is not found", HttpStatus.BAD_REQUEST.value()), //Group Exhibit diff --git a/src/main/java/com/example/jolvre/common/error/exhibition/ExhibitLikeDuplicationException.java b/src/main/java/com/example/jolvre/common/error/exhibition/ExhibitLikeDuplicationException.java new file mode 100644 index 0000000..1224397 --- /dev/null +++ b/src/main/java/com/example/jolvre/common/error/exhibition/ExhibitLikeDuplicationException.java @@ -0,0 +1,10 @@ +package com.example.jolvre.common.error.exhibition; + +import com.example.jolvre.common.error.EntityNotFoundException; +import com.example.jolvre.common.error.ErrorCode; + +public class ExhibitLikeDuplicationException extends EntityNotFoundException { + public ExhibitLikeDuplicationException() { + super(ErrorCode.EXHIBIT_LIKE_DUPLICATION); + } +} diff --git a/src/main/java/com/example/jolvre/exhibition/api/ExhibitLikeController.java b/src/main/java/com/example/jolvre/exhibition/api/ExhibitLikeController.java index fb340f8..bb0b099 100644 --- a/src/main/java/com/example/jolvre/exhibition/api/ExhibitLikeController.java +++ b/src/main/java/com/example/jolvre/exhibition/api/ExhibitLikeController.java @@ -2,6 +2,8 @@ import com.example.jolvre.auth.PrincipalDetails; import com.example.jolvre.exhibition.service.ExhibitLikeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; @@ -10,12 +12,14 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +@Tag(name = "EXHIBIT LIKE", description = "전시 좋아요를 관리합니다") @RestController @RequiredArgsConstructor @RequestMapping("/api/v1/exhibits") public class ExhibitLikeController { private final ExhibitLikeService exhibitLikeService; + @Operation(description = "전시 좋아요 기능", summary = "전시 좋아요수를 증가시킵니다") @PostMapping("/{exhibitId}/like") public ResponseEntity likeUpExhibit(@AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long exhibitId) { diff --git a/src/main/java/com/example/jolvre/exhibition/api/ExhibitionCommentController.java b/src/main/java/com/example/jolvre/exhibition/api/ExhibitionCommentController.java index 2c63f3a..0ff2b60 100644 --- a/src/main/java/com/example/jolvre/exhibition/api/ExhibitionCommentController.java +++ b/src/main/java/com/example/jolvre/exhibition/api/ExhibitionCommentController.java @@ -6,6 +6,7 @@ import com.example.jolvre.exhibition.dto.ExhibitDTO.ExhibitCommentUploadRequest; import com.example.jolvre.exhibition.service.ExhibitCommentService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; @@ -19,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +@Tag(name = "EXHIBIT COMMENT", description = "전시 댓글을 관리합니다") @RestController @RequiredArgsConstructor @Slf4j diff --git a/src/main/java/com/example/jolvre/exhibition/service/ExhibitLikeService.java b/src/main/java/com/example/jolvre/exhibition/service/ExhibitLikeService.java index 79bac79..3b4cccc 100644 --- a/src/main/java/com/example/jolvre/exhibition/service/ExhibitLikeService.java +++ b/src/main/java/com/example/jolvre/exhibition/service/ExhibitLikeService.java @@ -1,5 +1,6 @@ package com.example.jolvre.exhibition.service; +import com.example.jolvre.common.error.exhibition.ExhibitLikeDuplicationException; import com.example.jolvre.common.error.exhibition.ExhibitNotFoundException; import com.example.jolvre.common.util.RedisUtil; import com.example.jolvre.exhibition.entity.Exhibit; @@ -20,7 +21,7 @@ public void likeUpExhibit(Long exhibitId, Long userId) { String redisKey = "LIKE_" + exhibitId + userId; if (redisUtil.getData(redisKey) != null) { - return; + throw new ExhibitLikeDuplicationException(); } Exhibit exhibit = exhibitRepository.findById(exhibitId).orElseThrow(ExhibitNotFoundException::new);