Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

채팅 알림서비스 구현 및 시큐리티 적용 #113

Merged
merged 7 commits into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;
import kr.co.fastcampus.yanabada.common.response.ResponseBody;
import kr.co.fastcampus.yanabada.common.security.PrincipalDetails;
import kr.co.fastcampus.yanabada.domain.chat.dto.ReceivedChatMessage;
import kr.co.fastcampus.yanabada.domain.chat.dto.request.ChatRoomModifyRequest;
import kr.co.fastcampus.yanabada.domain.chat.dto.request.ChatRoomSaveRequest;
Expand All @@ -17,6 +18,7 @@
import org.springframework.data.web.PageableDefault;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand Down Expand Up @@ -55,34 +57,36 @@ public ResponseBody<ChatRoomInfoResponse> getOrAddChatRoom(

@GetMapping
public ResponseBody<List<ChatRoomSummaryResponse>> getChatRooms(
@AuthenticationPrincipal PrincipalDetails principalDetails
) {
Long memberId = 1L;
return ResponseBody.ok(chatService.getChatRooms(memberId));
return ResponseBody.ok(chatService.getChatRooms(principalDetails.id()));
}

@GetMapping("/{chatRoomCode}")
public ResponseBody<ChatMessagePageResponse> getChatRoom(
@AuthenticationPrincipal PrincipalDetails principalDetails,
@PathVariable("chatRoomCode") String chatRoomCode,
@PageableDefault(size = 20, sort = "sendDateTime", direction = Sort.Direction.DESC)
Pageable pageable
) {
Long memberId = 1L;
return ResponseBody.ok(chatService.getChatRoomMessages(memberId, chatRoomCode, pageable));
return ResponseBody.ok(
chatService.getChatRoomMessages(principalDetails.id(), chatRoomCode, pageable)
);
}

@PutMapping
public ResponseBody<ChatRoomModifyResponse> modifyChatRoom(
@AuthenticationPrincipal PrincipalDetails principalDetails,
@RequestBody ChatRoomModifyRequest request
) {
Long memberId = 1L;
return ResponseBody.ok(chatService.updateChatRoom(memberId, request));
return ResponseBody.ok(chatService.updateChatRoom(principalDetails.id(), request));
}

@DeleteMapping
public ResponseBody<ChatRoomModifyResponse> modifyOrDeleteChatRoom(
@AuthenticationPrincipal PrincipalDetails principalDetails,
@RequestBody ChatRoomModifyRequest request
) {
Long memberId = 1L;
return ResponseBody.ok(chatService.modifyOrDeleteChatRoom(memberId, request));
return ResponseBody.ok(chatService.modifyOrDeleteChatRoom(principalDetails.id(), request));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import kr.co.fastcampus.yanabada.domain.chat.repository.ChatRoomRepository;
import kr.co.fastcampus.yanabada.domain.member.entity.Member;
import kr.co.fastcampus.yanabada.domain.member.repository.MemberRepository;
import kr.co.fastcampus.yanabada.domain.notification.dto.ChatNotificationDto;
import kr.co.fastcampus.yanabada.domain.notification.service.NotificationService;
import kr.co.fastcampus.yanabada.domain.product.entity.Product;
import kr.co.fastcampus.yanabada.domain.product.entity.enums.ProductStatus;
import kr.co.fastcampus.yanabada.domain.product.repository.ProductRepository;
Expand All @@ -43,6 +45,8 @@ public class ChatService {

private final ProductRepository productRepository;

private final NotificationService notificationService;

@Transactional
public ChatRoomInfoResponse getOrSaveChatRoom(ChatRoomSaveRequest request) {
Product product = productRepository.getProduct(request.productId());
Expand Down Expand Up @@ -240,6 +244,11 @@ public SendChatMessage saveChatMessage(ReceivedChatMessage message) {
LocalDateTime sendTime = LocalDateTime.now();
checkChatRoomMember(chatRoom, sender);
updateMemberPresenceStatus(chatRoom, sender);
if (chatRoom.getMessages().size() == 0) {
sendFcmAndHistoryNotification(chatRoom, sender, message.content());
} else {
sendFcmNotification(chatRoom, sender, message.content());
}
addMessageToChatRoom(chatRoom, message, sender, sendTime);
return createSendChatMessage(chatRoom, sender, message, sendTime);
}
Expand All @@ -263,4 +272,32 @@ private SendChatMessage createSendChatMessage(
) {
return SendChatMessage.from(chatRoom, sender, message.content(), sendTime);
}

private ChatNotificationDto createChatNotificationDto(
Member sender, Member receiver, ChatRoom chatRoom
) {
return ChatNotificationDto.from(sender, receiver, chatRoom);
}

private void sendFcmAndHistoryNotification(ChatRoom chatRoom, Member sender, String content) {
if (isSeller(sender, chatRoom)) {
notificationService.sendChatCreated(
createChatNotificationDto(sender, chatRoom.getBuyer(), chatRoom),
content
);
} else {
notificationService.sendChatCreated(
createChatNotificationDto(sender, chatRoom.getSeller(), chatRoom),
content
);
}
}

private void sendFcmNotification(ChatRoom chatRoom, Member sender, String content) {
if (isSeller(sender, chatRoom)) {
notificationService.sendChatMessage(sender, chatRoom.getBuyer(), content);
} else {
notificationService.sendChatMessage(sender, chatRoom.getSeller(), content);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
import java.util.HashMap;
import java.util.Map;
import kr.co.fastcampus.yanabada.common.exception.JsonProcessFailedException;
import kr.co.fastcampus.yanabada.domain.chat.entity.ChatRoom;
import kr.co.fastcampus.yanabada.domain.member.entity.Member;
import lombok.Builder;

@Builder
public record ChatNotificationDto(
Member sender,
Member receiver,
Expand All @@ -16,6 +19,21 @@ public record ChatNotificationDto(
String image
) {

public static ChatNotificationDto from(
Member sender,
Member receiver,
ChatRoom chatRoom
) {
return ChatNotificationDto.builder()
.sender(sender)
.receiver(receiver)
.accommodationName(
chatRoom.getProduct().getOrder().getRoom().getAccommodation().getName()
)
.image(sender.getImage())
.build();
}

public String convertMapToJsonStr(ObjectMapper objectMapper) {
Map<String, String> contentMap = new HashMap<>();
contentMap.put("senderNickname", senderNickname);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,26 +52,21 @@ public class NotificationService {
private final MemberRepository memberRepository;

@Transactional
public void sendChatMessage(Member sender, String content) {
public void sendChatMessage(Member sender, Member receiver, String content) {
Notification notification = Notification.builder()
.title(CHAT_MESSAGE_TITLE)
.body(sender.getNickName() + ": " + content)
.build();
Data data = Data.builder().notificationType(CHAT.name()).build();
fcmService.sendToMessage(sender.getFcmToken(), notification, data);
fcmService.sendToMessage(receiver.getFcmToken(), notification, data);
}

@Transactional
public void sendChatCreated(ChatNotificationDto chatDto) {
public void sendChatCreated(ChatNotificationDto chatDto, String content) {

Notification notification = Notification.builder()
.title(CHAT_CREATED_TITLE)
.body(
chatDto.sender().getNickName()
+ CHAT_CREATED_CONTENT_INFIX
+ getShortPhrase(chatDto.accommodationName())
+ CHAT_CREATED_CONTENT_POSTFIX
)
.title(CHAT_MESSAGE_TITLE)
.body(chatDto.sender().getNickName() + ": " + content)
.build();
Data data = Data.builder().notificationType(CHAT.name()).build();
fcmService.sendToMessage(chatDto.receiver().getFcmToken(), notification, data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import jakarta.validation.Valid;
import kr.co.fastcampus.yanabada.common.response.ResponseBody;
import kr.co.fastcampus.yanabada.common.security.PrincipalDetails;
import kr.co.fastcampus.yanabada.domain.product.dto.request.ProductPatchRequest;
import kr.co.fastcampus.yanabada.domain.product.dto.request.ProductSaveRequest;
import kr.co.fastcampus.yanabada.domain.product.dto.request.ProductSearchRequest;
Expand All @@ -16,6 +17,7 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
Expand All @@ -37,10 +39,11 @@ public class ProductController {

@PostMapping
public ResponseBody<ProductIdResponse> addProduct(
@AuthenticationPrincipal PrincipalDetails principalDetails,
@RequestBody @Valid ProductSaveRequest request
) {
return ResponseBody.ok(
productService.saveProduct(1L, request)
productService.saveProduct(principalDetails.id(), request)
);
}

Expand All @@ -64,31 +67,33 @@ public ResponseBody<ProductSummaryPageResponse> getProductsBySearchRequest(

@PatchMapping("/{productId}")
public ResponseBody<ProductIdResponse> modifyProduct(
@AuthenticationPrincipal PrincipalDetails principalDetails,
@PathVariable("productId") Long productId,
@RequestBody ProductPatchRequest request
) {
return ResponseBody.ok(
productService.updateProduct(1L, productId, request)
productService.updateProduct(principalDetails.id(), productId, request)
);
}

@DeleteMapping("/{productId}")
public ResponseBody<Void> deleteProduct(
@AuthenticationPrincipal PrincipalDetails principalDetails,
@PathVariable("productId") Long productId
) {
productService.cancelProduct(1L, productId);
productService.cancelProduct(principalDetails.id(), productId);
return ResponseBody.ok();
}

@GetMapping("/own")
public ResponseBody<ProductHistoryPageResponse> getOwnProduct(
@AuthenticationPrincipal PrincipalDetails principalDetails,
@RequestParam(name = "status", required = false) ProductStatus status,
@PageableDefault(sort = "registeredDate", direction = Sort.Direction.DESC)
Pageable pageable
) {
Long memberId = 1L;
return ResponseBody.ok(
productService.getOwnProduct(memberId, status, pageable)
productService.getOwnProduct(principalDetails.id(), status, pageable)
);
}
}
Loading