Skip to content

Commit

Permalink
Merge pull request #206 from swm-nodriversomabus/BUS-208-matching-cha…
Browse files Browse the repository at this point in the history
…troom-connect

Bus 208 matching chatroom connect
  • Loading branch information
Lemonade255 authored Nov 14, 2023
2 parents e7566bf + 948665b commit 6ae6ef2
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import com.example.api.common.exception.CustomException;
import com.example.api.common.type.ErrorCodeEnum;
import com.example.api.common.utils.AuthenticationUtils;
import com.example.api.multipart.application.port.in.UploadFileUsecase;
import com.example.api.s3.application.port.in.FileUploadUsecase;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
Expand All @@ -18,51 +18,51 @@
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.UUID;

@RestController
@Slf4j
@RequiredArgsConstructor
@Slf4j
@Tag(name = "Chat", description = "Chat API")
public class ChatController {
private final SendChatUsecase sendChatUsecase;
private final SubscribeRoomUsecase subscribeRoomUsecase;
private final GetChatListUsecase getChatListUsecase;
private final UploadFileUsecase uploadFileUsecase;
private final FileUploadUsecase fileUploadUsecase;

/**
* 추후에 jwt 인증을 통해 유저 데이터를 불러와 message에 추가할 예정
* @param roomId (ID)
* @param message (데이터)
* @param message (메시지)
*/
@Operation(summary = "Send message", description = "채팅방에 메시지를 보낸다.")
@MessageMapping("/chat/{roomId}")
public void sendMessage(@DestinationVariable String roomId, AddChatDto message, String contentType, @RequestParam("file") MultipartFile file) {
SecurityUser securityUser = AuthenticationUtils.getCurrentUserAuthentication();
if (securityUser == null) {
log.error("ChatController::sendMessage: Login is needed");
throw new CustomException(ErrorCodeEnum.LOGIN_IS_NOT_DONE);
}
message.setSenderId(securityUser.getUserId());
log.info("roomId : {}", roomId);

if (contentType.equals("image")) {
if (file.isEmpty()) {
log.error("ChatController:sendMessage: cannot find a image");
throw new CustomException(ErrorCodeEnum.IMAGE_NOT_FOUND);
}
message.setContent(uploadFileUsecase.uploadFile(file));
}
@MessageMapping(value = "/chat/{roomId}")
public void sendMessage(@DestinationVariable String roomId, @Header("userId") UUID userId, AddChatDto message) {
message.setSenderId(userId);
sendChatUsecase.send(roomId, message);
}

/**
* 채팅 이미지 업로드
* @param file (이미지)
* @return filename
*/
@Operation(summary = "Upload chat image", description = "채팅 이미지를 업로드한다.")
@PostMapping("/chat/image")
public String upload(@RequestBody MultipartFile file) {
if (file == null) {
log.error("ChatController::sendMessage: image is not found");
throw new CustomException(ErrorCodeEnum.IMAGE_NOT_FOUND);
}
return fileUploadUsecase.upload(file);
}

/**
* 구독을 시작할 때 클라이언트가 사용
* 컨슈머가 없을 시 등록 + 추후에 유저 추가 알림 같은 것을 전달 가능해 보임
Expand All @@ -71,11 +71,6 @@ public void sendMessage(@DestinationVariable String roomId, AddChatDto message,
@Operation(summary = "Enter chatroom", description = "채팅방에 입장한다.")
@MessageMapping("/subscribe/{roomId}")
public void subscribe(@DestinationVariable String roomId) {
SecurityUser securityUser = AuthenticationUtils.getCurrentUserAuthentication();
if (securityUser == null) {
log.error("ChatController::subscribe: Login is needed");
throw new CustomException(ErrorCodeEnum.LOGIN_IS_NOT_DONE);
}
subscribeRoomUsecase.subscribe(roomId);
}

Expand Down
45 changes: 43 additions & 2 deletions src/main/java/com/example/api/chat/config/StompConfiguration.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
package com.example.api.chat.config;

import com.example.api.chat.handler.StompHandler;
import com.example.api.common.exception.CustomException;
import com.example.api.common.type.ErrorCodeEnum;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.*;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.util.WebUtils;

import java.util.Map;

@Configuration
@EnableWebSocketMessageBroker // STOMP 사용 용도
Expand All @@ -19,11 +33,13 @@ public class StompConfiguration implements WebSocketMessageBrokerConfigurer {
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws/chat")
.setAllowedOriginPatterns("*")
.withSockJS();
.withSockJS()
.setInterceptors(httpSessHandshakeInterceptor())
;
}

// TODO
// 추후 jwt 인증시 필요 - 인증 절차
// 추후 jwt 인증시 필요 - 인증 절차m
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(stompHandler);
Expand All @@ -41,6 +57,31 @@ public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/pub");
}

@Bean
public HandshakeInterceptor httpSessHandshakeInterceptor() {
return new HandshakeInterceptor() {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
if (request instanceof ServletServerHttpRequest){
ServletServerHttpRequest servletServerRequest = (ServletServerHttpRequest) request;
HttpServletRequest servletRequest = servletServerRequest.getServletRequest();
Cookie token = WebUtils.getCookie(servletRequest, "access_token");
if (token != null){
attributes.put("token", token.getValue());
} else{
throw new CustomException(ErrorCodeEnum.LOGIN_IS_NOT_DONE);
}
}
return true;
}

@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {

}
};
}

// 64 KB 이상의 데이터 전송을 위해 사용
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
Expand Down
41 changes: 40 additions & 1 deletion src/main/java/com/example/api/chat/handler/StompHandler.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
package com.example.api.chat.handler;

import com.example.api.auth.domain.SecurityUser;
import com.example.api.auth.service.JwtUtilService;
import com.example.api.chat.exception.JwtException;
import com.example.api.common.exception.CustomException;
import com.example.api.common.type.ErrorCodeEnum;
import com.example.api.common.utils.AuthenticationUtils;
import com.example.api.user.service.UserService;
import jakarta.servlet.http.Cookie;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
Expand All @@ -9,13 +18,43 @@
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Objects;
import java.util.*;

@Slf4j
@RequiredArgsConstructor
@Component
public class StompHandler implements ChannelInterceptor{
private final JwtUtilService jwtUtilService;
private final UserService userService;
/**
* 메시지를 보내기전에 jwt 인증 검사
* @param message
* @param channel
* @return
*/
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = StompHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

Map<String, Object> sessionAttributes = accessor.getSessionAttributes();
String token = (String) sessionAttributes.get("token");

if (!jwtUtilService.verifyToken(token)) {
log.info("JWT 이슈 발생");
throw new JwtException("Access Token 만료");
} else {
// Security Context에 등록할 user 객체 생성
SecurityUser userinfo = userService.findSocialUser(jwtUtilService.getId(token), jwtUtilService.getProvider(token));
accessor.setHeader("userId", userinfo.getUserId());
}
return message;
}

@Override
public void postSend(@NonNull Message<?> message,@NonNull MessageChannel channel, boolean sent) {
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/example/api/chatroom/type/ChatRoomEnum.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import lombok.Getter;
import lombok.ToString;

@ToString
@AllArgsConstructor
@Getter
@AllArgsConstructor
@ToString
public enum ChatRoomEnum {
Normal("일반", 1),
Matching("매칭", 2),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import lombok.Getter;
import lombok.ToString;

@ToString
@AllArgsConstructor
@Getter
@AllArgsConstructor
@ToString
public enum ApplicationStateEnum {
Pending("대기", 0),
Canceled("취소", 1),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public enum ErrorCodeEnum {
MATCHING_NOT_FOUND(HttpStatus.BAD_REQUEST, "매칭 정보가 없습니다"),
PREFERENCE_NOT_FOUND(HttpStatus.BAD_REQUEST, "선호도 정보가 없습니다"),
APPLICATION_NOT_FOUND(HttpStatus.BAD_REQUEST, "신청 정보가 없습니다"),
IMAGE_NOT_FOUND(HttpStatus.BAD_REQUEST, "사진이 없습니다"),
FILE_NOT_FOUND(HttpStatus.BAD_REQUEST, "파일이 없습니다"),
IMAGE_NOT_FOUND(HttpStatus.BAD_REQUEST, "사진이 없습니다"),
INVALID_DATATYPE(HttpStatus.BAD_REQUEST, "유효하지 않은 데이터입니다"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import lombok.Getter;
import lombok.ToString;

@ToString
@AllArgsConstructor
@Getter
@AllArgsConstructor
@ToString
public enum MatchingTypeEnum {
TravelMate("여행객 매칭"),
Dining("식사 매칭"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import lombok.ToString;

@Getter
@ToString
@AllArgsConstructor
@ToString
public enum NotificationTypeEnum {
NewApplication("새로운 매칭 신청", 0),
ApplicationApproved("매칭 신청 수락", 1),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import lombok.Getter;
import lombok.ToString;

@ToString
@AllArgsConstructor
@Getter
@AllArgsConstructor
@ToString
public enum PreferSmokeEnum {
None("선호 없음", 0),
Nonsmoke("비흡연", 1),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import lombok.ToString;

@Getter
@ToString
@AllArgsConstructor
@ToString
public enum TasteEnum {
Cold("찬 음식", 1),
Hot("뜨거운 음식", 2),
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/example/api/user/type/UserGenderEnum.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import lombok.Getter;
import lombok.ToString;

@ToString
@AllArgsConstructor
@Getter
@AllArgsConstructor
@ToString
public enum UserGenderEnum {
None("없음", 0),
Female("여자", 1),
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/example/api/user/type/UserRoleEnum.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import lombok.Getter;
import lombok.ToString;

@ToString
@AllArgsConstructor
@Getter
@AllArgsConstructor
@ToString
public enum UserRoleEnum {
Admin("관리자", 1),
User("일반 사용자", 2);
Expand Down

0 comments on commit 6ae6ef2

Please sign in to comment.