Skip to content

Commit

Permalink
[OING-219] refactor: MemberPost/MemberPostRealEmoji save 로직 리팩터링 (#201)
Browse files Browse the repository at this point in the history
* refactor: refactor save logic in MemberPostRealEmoji

* refactor: refactor save logic in MemberPost

* refact: refact service code in post module

* feat: add RedisLocalConfig

* test: add registerRealEmojiAtPost test
  • Loading branch information
Ji-soo708 authored Mar 22, 2024
1 parent 4e24e98 commit 606798b
Show file tree
Hide file tree
Showing 15 changed files with 289 additions and 233 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.oing.config.support;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Profile("local")
@Configuration
public class RedisLocalConfig {

@Value("${spring.data.redis.host}")
private String redisHost;

@Value("${spring.data.redis.port}")
private int redisPort;

@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(new RedisStandaloneConfiguration(redisHost, redisPort));
}

@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());

/* Java 기본 직렬화가 아닌 JSON 직렬화 설정 */
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

return redisTemplate;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public void sendDailyRemainingNotification() {
LocalDate today = LocalDate.now();
List<Member> allMembers = memberService.findAllMember();
HashSet<String> targetFcmTokens = new HashSet<>();
HashSet<String> postedMemberIds = new HashSet<>(memberPostService.getMemberIdsPostedToday(today));
HashSet<String> postedMemberIds = new HashSet<>(memberPostService.findMemberIdsPostedToday(today));
allMembers.stream()
.filter(member -> !postedMemberIds.contains(member.getId())) //오늘 업로드한 사람이 아닌 사람들은
.forEach(member -> targetFcmTokens.addAll(memberDeviceService.getFcmTokensByMemberId(member.getId())));
Expand Down
45 changes: 38 additions & 7 deletions gateway/src/test/java/com/oing/restapi/WidgetApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.oing.domain.Member;
import com.oing.domain.MemberPost;
import com.oing.domain.SocialLoginProvider;
import com.oing.dto.request.CreatePostRequest;
import com.oing.dto.request.JoinFamilyRequest;
import com.oing.dto.response.DeepLinkResponse;
import com.oing.dto.response.FamilyResponse;
Expand All @@ -23,8 +24,8 @@
import org.springframework.test.web.servlet.MockMvc;

import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
Expand Down Expand Up @@ -149,9 +150,24 @@ void setUp() throws Exception {
"3",
"testPos3"
);
memberPostService.save(testPost1);
memberPostService.save(testPost2);
memberPostService.save(testPost3);
CreatePostRequest request1 = new CreatePostRequest(
"https://storage.com/bucket/images/1",
"testPos1",
ZonedDateTime.now()
);
CreatePostRequest request2 = new CreatePostRequest(
"https://storage.com/bucket/images/2",
"testPos2",
ZonedDateTime.now()
);
CreatePostRequest request3 = new CreatePostRequest(
"https://storage.com/bucket/images/3",
"testPos3",
ZonedDateTime.now()
);
memberPostService.createMemberPost(request1, TEST_MEMBER1.getId(), TEST_FAMILY_ID);
memberPostService.createMemberPost(request2, TEST_MEMBER2.getId(), TEST_FAMILY_ID);
memberPostService.createMemberPost(request3, TEST_MEMBER3.getId(), "something_other");


// when & then
Expand Down Expand Up @@ -195,9 +211,24 @@ void setUp() throws Exception {
"3",
"testPos3"
);
memberPostService.save(testPost1);
memberPostService.save(testPost2);
memberPostService.save(testPost3);
CreatePostRequest request1 = new CreatePostRequest(
"https://storage.com/bucket/images/1",
"testPos1",
ZonedDateTime.now()
);
CreatePostRequest request2 = new CreatePostRequest(
"https://storage.com/bucket/images/2",
"testPos2",
ZonedDateTime.now()
);
CreatePostRequest request3 = new CreatePostRequest(
"https://storage.com/bucket/images/3",
"testPos3",
ZonedDateTime.now()
);
memberPostService.createMemberPost(request1, TEST_MEMBER1.getId(), TEST_FAMILY_ID);
memberPostService.createMemberPost(request2, TEST_MEMBER2.getId(), TEST_FAMILY_ID);
memberPostService.createMemberPost(request3, TEST_MEMBER3.getId(), "something_other");


// when & then
Expand Down
45 changes: 2 additions & 43 deletions post/src/main/java/com/oing/controller/MemberPostController.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@
import com.oing.dto.response.PostResponse;
import com.oing.dto.response.PreSignedUrlResponse;
import com.oing.exception.AuthorizationFailedException;
import com.oing.exception.DuplicatePostUploadException;
import com.oing.exception.InvalidUploadTimeException;
import com.oing.restapi.MemberPostApi;
import com.oing.service.MemberBridge;
import com.oing.service.MemberPostService;
import com.oing.util.IdentityGenerator;
import com.oing.util.PreSignedUrlGenerator;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
Expand All @@ -23,8 +20,6 @@
import org.springframework.stereotype.Controller;

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZonedDateTime;

/**
* no5ing-server
Expand All @@ -37,7 +32,6 @@
@Controller
public class MemberPostController implements MemberPostApi {

private final IdentityGenerator identityGenerator;
private final PreSignedUrlGenerator preSignedUrlGenerator;
private final MemberPostService memberPostService;
private final MemberBridge memberBridge;
Expand Down Expand Up @@ -73,48 +67,13 @@ public PaginationResponse<PostResponse> fetchDailyFeeds(Integer page, Integer si
key = "#loginFamilyId.concat(':').concat(T(java.time.format.DateTimeFormatter).ofPattern('yyyy-MM').format(#request.uploadTime()))")
public PostResponse createPost(CreatePostRequest request, String loginFamilyId, String loginMemberId) {
log.info("Member {} is trying to create post", loginMemberId);
String postId = identityGenerator.generateIdentity();
ZonedDateTime uploadTime = request.uploadTime();

validateUserHasNotCreatedPostToday(loginMemberId, loginFamilyId, uploadTime);
validateUploadTime(loginMemberId, uploadTime);

String postImgKey = preSignedUrlGenerator.extractImageKey(request.imageUrl());
MemberPost post = new MemberPost(postId, loginMemberId, loginFamilyId, request.imageUrl(),
postImgKey, request.content());
MemberPost savedPost = memberPostService.save(post);
log.info("Member {} has created post {}", loginMemberId, postId);
MemberPost savedPost = memberPostService.createMemberPost(request, loginMemberId, loginFamilyId);
log.info("Member {} has created post {}", loginMemberId, savedPost.getId());

return PostResponse.from(savedPost);
}

private void validateUserHasNotCreatedPostToday(String memberId, String familyId, ZonedDateTime uploadTime) {
LocalDate today = uploadTime.toLocalDate();
if (memberPostService.hasUserCreatedPostToday(memberId, familyId, today)) {
log.warn("Member {} has already created a post today", memberId);
throw new DuplicatePostUploadException();
}
}

/**
* 업로드 시간이 허용 가능한 범위 내에 있는지 검증합니다.
* 범위는 서버의 로컬 시간을 기준으로 전 날의 오후 12시부터 다음 날의 오후 12시까지로 정의됩니다.
*
* @param uploadTime 검증할 업로드 시간입니다.
* @throws InvalidUploadTimeException 업로드 시간이 허용 가능한 범위를 벗어난 경우 발생하는 예외입니다.
*/
private void validateUploadTime(String memberId, ZonedDateTime uploadTime) {
ZonedDateTime serverTime = ZonedDateTime.now();

ZonedDateTime lowerBound = serverTime.minusDays(1).with(LocalTime.of(12, 0));
ZonedDateTime upperBound = serverTime.plusDays(1).with(LocalTime.of(12, 0));

if (uploadTime.isBefore(lowerBound) || uploadTime.isAfter(upperBound)) {
log.warn("Member {} is attempting to upload a post at an invalid time", memberId);
throw new InvalidUploadTimeException();
}
}

@Override
public PostResponse getPost(String postId, String loginMemberId) {
String postFamilyId = memberPostService.getMemberPostById(postId).getFamilyId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class MemberPostReactionController implements MemberPostReactionApi {
public DefaultResponse createPostReaction(String postId, String loginMemberId, PostReactionRequest request) {
log.info("Member {} is trying to create post reaction", loginMemberId);
Emoji emoji = Emoji.fromString(request.content());
MemberPost post = memberPostService.findMemberPostById(postId);
MemberPost post = memberPostService.getMemberPostById(postId);

validatePostReactionForAddition(post, loginMemberId, emoji);
String reactionId = identityGenerator.generateIdentity();
Expand All @@ -60,7 +60,7 @@ private void validatePostReactionForAddition(MemberPost post, String loginMember
public DefaultResponse deletePostReaction(String postId, String loginMemberId, PostReactionRequest request) {
log.info("Member {} is trying to delete post reaction {}", loginMemberId, request.content());
Emoji emoji = Emoji.fromString(request.content());
MemberPost post = memberPostService.findMemberPostById(postId);
MemberPost post = memberPostService.getMemberPostById(postId);

validatePostReactionForDeletion(post, loginMemberId, emoji);
MemberPostReaction reaction = memberPostReactionService.findReaction(post, loginMemberId, emoji);
Expand All @@ -80,7 +80,7 @@ private void validatePostReactionForDeletion(MemberPost post, String memberId, E
@Override
@Transactional
public PostReactionSummaryResponse getPostReactionSummary(String postId, String loginMemberId) {
MemberPost post = memberPostService.findMemberPostById(postId);
MemberPost post = memberPostService.getMemberPostById(postId);
validateFamilyMember(loginMemberId, post);

List<PostReactionSummaryResponse.PostReactionSummaryResponseElement> results = post.getReactions()
Expand All @@ -103,7 +103,7 @@ public PostReactionSummaryResponse getPostReactionSummary(String postId, String
@Override
@Transactional
public ArrayResponse<PostReactionResponse> getPostReactions(String postId, String loginMemberId) {
MemberPost post = memberPostService.findMemberPostById(postId);
MemberPost post = memberPostService.getMemberPostById(postId);
validateFamilyMember(loginMemberId, post);
return ArrayResponse.of(
post.getReactions().stream()
Expand All @@ -115,9 +115,9 @@ public ArrayResponse<PostReactionResponse> getPostReactions(String postId, Strin
@Override
@Transactional
public PostReactionMemberResponse getPostReactionMembers(String postId, String loginMemberId) {
MemberPost post = memberPostService.findMemberPostById(postId);
MemberPost post = memberPostService.getMemberPostById(postId);
validateFamilyMember(loginMemberId, post);
List<MemberPostReaction> reactions = memberPostReactionService.getMemberPostReactionsByPostId(postId);
List<MemberPostReaction> reactions = memberPostReactionService.findMemberPostReactionsByPostId(postId);
List<Emoji> emojiList = Emoji.getEmojiList();

Map<String, List<String>> emojiMemberIdsMap = reactions.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
import com.oing.service.MemberBridge;
import com.oing.service.MemberPostRealEmojiService;
import com.oing.service.MemberPostService;
import com.oing.service.MemberRealEmojiService;
import com.oing.util.IdentityGenerator;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -29,10 +27,8 @@
@Controller
public class MemberPostRealEmojiController implements MemberPostRealEmojiApi {

private final IdentityGenerator identityGenerator;
private final MemberPostService memberPostService;
private final MemberPostRealEmojiService memberPostRealEmojiService;
private final MemberRealEmojiService memberRealEmojiService;
private final MemberBridge memberBridge;

/**
Expand All @@ -45,31 +41,19 @@ public class MemberPostRealEmojiController implements MemberPostRealEmojiApi {
*/
@Transactional
@Override
public PostRealEmojiResponse createPostRealEmoji(String postId, String loginFamilyId, String loginMemberId, PostRealEmojiRequest request) {
public PostRealEmojiResponse registerRealEmojiAtPost(
String postId, String loginFamilyId, String loginMemberId, PostRealEmojiRequest request
) {
log.info("Member {} is trying to create post real emoji", loginMemberId);
MemberPost post = memberPostService.getMemberPostById(postId);
if (!memberBridge.isInSameFamily(loginMemberId, post.getMemberId())) {
log.warn("Unauthorized access attempt: Member {} is attempting to access post real emoji", loginMemberId);
throw new AuthorizationFailedException();
}
MemberPostRealEmoji addedPostRealEmoji = memberPostRealEmojiService.registerRealEmojiAtPost(request, loginMemberId,
loginFamilyId, post);

MemberRealEmoji realEmoji = memberRealEmojiService.getMemberRealEmojiByIdAndFamilyId(request.realEmojiId(), loginFamilyId);
validatePostRealEmojiForAddition(post, loginMemberId, realEmoji);
MemberPostRealEmoji postRealEmoji = new MemberPostRealEmoji(identityGenerator.generateIdentity(), realEmoji,
post, loginMemberId);
MemberPostRealEmoji addedPostRealEmoji = memberPostRealEmojiService.savePostRealEmoji(postRealEmoji);
post.addRealEmoji(postRealEmoji);
log.info("Member {} has created post real emoji {}", loginMemberId, realEmoji.getId());
log.info("Member {} has created post real emoji {}", loginMemberId, addedPostRealEmoji.getId());

return PostRealEmojiResponse.from(addedPostRealEmoji);
}

private void validatePostRealEmojiForAddition(MemberPost post, String memberId, MemberRealEmoji emoji) {
if (memberPostRealEmojiService.isMemberPostRealEmojiExists(post, memberId, emoji)) {
throw new RealEmojiAlreadyExistsException();
}
}

/**
* 게시물에 등록된 리얼 이모지를 삭제합니다
* @param postId 게시물 ID
Expand Down Expand Up @@ -100,7 +84,7 @@ public DefaultResponse deletePostRealEmoji(String postId, String realEmojiId, St
@Override
@Transactional
public PostRealEmojiSummaryResponse getPostRealEmojiSummary(String postId, String loginMemberId) {
MemberPost post = memberPostService.findMemberPostById(postId);
MemberPost post = memberPostService.getMemberPostById(postId);
validateFamilyMember(loginMemberId, post);
List<PostRealEmojiSummaryResponse.PostRealEmojiSummaryResponseElement> results = post.getRealEmojis()
.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public interface MemberPostRealEmojiApi {

@Operation(summary = "게시물에 리얼 이모지 등록", description = "게시물에 리얼 이모지를 추가합니다.")
@PostMapping
PostRealEmojiResponse createPostRealEmoji(
PostRealEmojiResponse registerRealEmojiAtPost(
@Parameter(description = "게시물 ID", example = "01HGW2N7EHJVJ4CJ999RRS2E97")
@PathVariable
String postId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,12 @@
public class MemberPostCommentService {
private final MemberPostCommentRepository memberPostCommentRepository;

/**
* 게시물의 댓글을 저장합니다
* @param memberPostComment 댓글
* @return 저장된 댓글
*/

@Transactional
public MemberPostComment savePostComment(MemberPostComment memberPostComment) {
return memberPostCommentRepository.save(memberPostComment);
}

/**
* 게시물의 댓글을 조회합니다
* @param postId 게시글 ID
* @param commentId 댓글 ID
* @return 댓글
* @throws MemberPostCommentNotFoundException 댓글이 존재하지 않거나 게시글 ID가 댓글의 ID와 일치하지 않을 경우
*/
@Transactional
public MemberPostComment getMemberPostComment(String postId, String commentId) {
MemberPostComment memberPostComment = memberPostCommentRepository
.findById(commentId)
Expand All @@ -46,24 +34,11 @@ public MemberPostComment getMemberPostComment(String postId, String commentId) {
return memberPostComment;
}

/**
* 게시물의 댓글을 삭제합니다
* @param memberPostComment 댓글
*/
@Transactional
public void deletePostComment(MemberPostComment memberPostComment) {
memberPostCommentRepository.delete(memberPostComment);
}

/**
* 게시글의 댓글들을 조회합니다.
* @param page 페이지
* @param size 페이지당 댓글 수
* @param postId 게시글 ID
* @param asc 오름차순 여부
* @return 댓글들 조회 결과
*/
@Transactional
public PaginationDTO<MemberPostComment> searchPostComments(int page, int size, String postId, boolean asc) {
QueryResults<MemberPostComment> results = memberPostCommentRepository
.searchPostComments(page, size, postId, asc);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public MemberPostReaction findReaction(MemberPost post, String memberId, Emoji e
.orElseThrow(EmojiNotFoundException::new);
}

public List<MemberPostReaction> getMemberPostReactionsByPostId(String postId) {
public List<MemberPostReaction> findMemberPostReactionsByPostId(String postId) {
return memberPostReactionRepository.findAllByPostId(postId);
}

Expand Down
Loading

0 comments on commit 606798b

Please sign in to comment.