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

main merge #210

Merged
merged 27 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f47ea94
hotfix(BE): 추천 매칭에서 상태가 None인 것만 표시 BUS-209-MVP1-bugfix #194
Lemonade255 Nov 10, 2023
80e285c
hotfix(BE): 선호도 조회 시 Value 대신 Key가 조회됨 BUS-209-MVP1-bugfix #195
Lemonade255 Nov 10, 2023
61c278b
hotfix(BE): 매칭 신청 오류 BUS-209-MVP1-bugfix
Lemonade255 Nov 10, 2023
b98b8e3
Merge branch 'dev' into BUS-209-MVP1-bugfix
Lemonade255 Nov 10, 2023
6732189
Merge pull request #196 from swm-nodriversomabus/BUS-209-MVP1-bugfix
Lemonade255 Nov 10, 2023
7e924a2
hotfix(BE): 매칭 신청 오류 BUS-209-MVP1-bugfix
Lemonade255 Nov 10, 2023
5227708
Merge pull request #197 from swm-nodriversomabus/BUS-209-MVP1-bugfix
Lemonade255 Nov 10, 2023
16232c5
feat(BE): 매칭 참가자 목록에 작성자 포함 BUS-218-Approved-include-Owner #198
Lemonade255 Nov 10, 2023
29a6306
Merge pull request #199 from swm-nodriversomabus/BUS-218-Approved-inc…
Lemonade255 Nov 10, 2023
a13be9d
fix(BE): SMS 컨트롤러 권한 체크 해제 BUS-203-Authority-check
Lemonade255 Nov 13, 2023
5c3fbdc
Merge pull request #200 from swm-nodriversomabus/BUS-203-Authority-check
Lemonade255 Nov 13, 2023
0981d13
fix(BE): 사용자 추가 접근 제한 해제 BUS-203-Authority-check
Lemonade255 Nov 13, 2023
42baa33
Merge pull request #201 from swm-nodriversomabus/BUS-203-Authority-check
Lemonade255 Nov 13, 2023
be653dc
feat(BE): 매칭 생성 시 채팅방 연결 BUS-208-matching-chatroom-connect #202
Lemonade255 Nov 13, 2023
c6985d9
fix(BE): 채팅 메시지 전송 실패 BUS-209-MVP1-bugfix
Lemonade255 Nov 13, 2023
f9ab195
Merge pull request #203 from swm-nodriversomabus/BUS-209-MVP1-bugfix
Lemonade255 Nov 13, 2023
e7566bf
Merge pull request #204 from swm-nodriversomabus/BUS-208-matching-cha…
Lemonade255 Nov 13, 2023
087bc05
FIX(BE): stomp에도 쿠키 담긴 jwt 인증 처리 완료 #205
namhyo01 Nov 13, 2023
b94b440
fix(BE): 채팅 전송 실패 BUS-208-matching-chatroom-connect #205
Lemonade255 Nov 14, 2023
948665b
Merge branch 'dev' into BUS-208-matching-chatroom-connect
Lemonade255 Nov 14, 2023
6ae6ef2
Merge pull request #206 from swm-nodriversomabus/BUS-208-matching-cha…
Lemonade255 Nov 14, 2023
9f7cac1
fix(BE): Enum 중복 제거 BUS-209-MVP1-bugfix
Lemonade255 Nov 14, 2023
772d300
Merge pull request #207 from swm-nodriversomabus/BUS-209-MVP1-bugfix
Lemonade255 Nov 14, 2023
72b95c9
feat(BE): 개별 사용자 ID 조회/ID로 사용자 조회 BUS-209-MVP1-bugfix
Lemonade255 Nov 14, 2023
c8f1e8b
Merge pull request #208 from swm-nodriversomabus/BUS-209-MVP1-bugfix
Lemonade255 Nov 14, 2023
b1345cb
fix(BE): 프로필 인증 절차 생략 BUS-209-MVP1-bugfix
Lemonade255 Nov 14, 2023
c7e03d6
Merge pull request #209 from swm-nodriversomabus/BUS-209-MVP1-bugfix
Lemonade255 Nov 14, 2023
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 @@ -8,15 +8,14 @@
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Optional;

@RestController
@Slf4j
@RequiredArgsConstructor
@Slf4j
public class AuthController {
private final JwtUtilService jwtUtilService;
private final FindRefreshUsecase findRefreshUsecase;
Expand Down
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,45 +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);
}
log.info("roomId : {}", roomId);
if (contentType.equals("image")) {
message.setContent(uploadFileUsecase.uploadFile(file));
}
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::upload: image is not found");
throw new CustomException(ErrorCodeEnum.IMAGE_NOT_FOUND);
}
return fileUploadUsecase.upload(file);
}

/**
* 구독을 시작할 때 클라이언트가 사용
* 컨슈머가 없을 시 등록 + 추후에 유저 추가 알림 같은 것을 전달 가능해 보임
Expand All @@ -65,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
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ public interface ChatMapper {
// @Mapping(source = "senderId.userId.userId", target = "senderId.userId")
Chat toDomain(ChatEntity chatEntity);

@Mapping(source = "senderId",target = "senderId.userId")
@Mapping(source = "senderId", target = "senderId.userId")
Chat toDomain(AddChatDto addChatDto);
}
}
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
1 change: 0 additions & 1 deletion src/main/java/com/example/api/chat/dto/AddChatDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ public class AddChatDto {
@NotNull
private UUID roomId;

@NotNull
private UUID senderId;

@NotBlank
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
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
import java.util.UUID;

@RestController
@Slf4j
@RequiredArgsConstructor
@Slf4j
@Tag(name = "ChatRoom", description = "ChatRoom API")
public class ChatRoomController {
private final CreateChatRoomUsecase createChatRoomUsecase;
Expand Down
12 changes: 7 additions & 5 deletions src/main/java/com/example/api/chatroom/type/ChatRoomEnum.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
import lombok.Getter;
import lombok.ToString;

@ToString
@AllArgsConstructor
@Getter
@AllArgsConstructor
@ToString
public enum ChatRoomEnum {
Normal("일반"),
Inquery("상담");
Normal("일반", 1),
Matching("매칭", 2),
Inquiry("상담", 3);

private final String type;
}
private final Integer typeCode;
}
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, "파일이 없습니다"),
INVALID_DATATYPE(HttpStatus.BAD_REQUEST, "유효하지 않은 데이터입니다"),
// 401 Unauthorized
Expand Down
Loading
Loading