Skip to content

Commit

Permalink
Merge pull request #103 from gague-jinsim-in-jadeul/refact/102_change…
Browse files Browse the repository at this point in the history
…_chatting_flow

Refact/102 change chatting flow
  • Loading branch information
MinkeySon authored Dec 25, 2024
2 parents a66468c + 752ee64 commit 1ff398f
Show file tree
Hide file tree
Showing 29 changed files with 390 additions and 87 deletions.
13 changes: 13 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,19 @@
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<!-- queryDSL dependency -->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>5.0.0</version>
<classifier>jakarta</classifier>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>5.0.0</version>
<classifier>jakarta</classifier>
</dependency>
</dependencies>

<build>
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/org/gagu/gagubackend/auth/dao/AuthDAO.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package org.gagu.gagubackend.auth.dao;

import org.gagu.gagubackend.auth.domain.User;
import org.gagu.gagubackend.auth.dto.request.RequestAddressDto;
import org.gagu.gagubackend.auth.dto.request.RequestChangeUserInfoDto;
import org.gagu.gagubackend.auth.dto.request.RequestGeneralSignDto;
import org.gagu.gagubackend.auth.dto.request.RequestSaveUserDto;
import org.springframework.http.ResponseEntity;

import java.util.Optional;

public interface AuthDAO {
/**
* 유저 DB 조회 후 token 생성 / 닉네임 중복 여부 확인 후 저장
Expand Down Expand Up @@ -68,4 +71,11 @@ public interface AuthDAO {
* @return
*/
ResponseEntity<?> getWorkShopDetails(Long id);

/**
* 범용적으로 사용하는 닉네임으로 유저 조회
* @param nickname
* @return
*/
Optional<User> getUserByNickname(String nickname);
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -439,6 +440,11 @@ public ResponseEntity<?> getWorkShopDetails(Long id) {
}
}

@Override
public Optional<User> getUserByNickname(String nickname) {
return userRepository.findUserByNickname(nickname);
}

private void updateUserNickName(String nickname, String changeNickname){
log.info("[auth] update user nickname....");
List<ChatRoom> chatLst = chatRoomRepository.findAllByRoomNameContains(nickname);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package org.gagu.gagubackend.auth.repository;

import org.gagu.gagubackend.auth.domain.User;
import org.gagu.gagubackend.auth.repository.custom.UserRepositoryCustom;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface UserRepository extends JpaRepository<User,Long> {
public interface UserRepository extends JpaRepository<User,Long>, UserRepositoryCustom {
User findByEmailAndLoginType(String name, String loginType);
User findByResourceIdAndLoginType(String resourceId, String loginType);
List<User> findAllByEmailAndLoginType(String email, String loginType);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.gagu.gagubackend.auth.repository.custom;

import org.gagu.gagubackend.auth.domain.User;

import java.util.Optional;

public interface UserRepositoryCustom {
Optional<User> findUserByNickname(String nickname);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.gagu.gagubackend.auth.repository.custom.impl;

import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import org.gagu.gagubackend.auth.domain.QUser;
import org.gagu.gagubackend.auth.domain.User;
import org.gagu.gagubackend.auth.repository.custom.UserRepositoryCustom;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
public class UserRepositoryCustomImpl implements UserRepositoryCustom {

private final JPAQueryFactory jpaQueryFactory;

@Autowired
public UserRepositoryCustomImpl(EntityManager em) {
this.jpaQueryFactory = new JPAQueryFactory(em);
}

@Override
public Optional<User> findUserByNickname(String nickname) {
QUser qUser = QUser.user;

return Optional.ofNullable(jpaQueryFactory.select(qUser)
.from(qUser)
.where(qUser.nickName.eq(nickname))
.fetchOne());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,6 @@ public interface AuthService {
* @return
*/
ResponseEntity<?> getWorkShopDetails(Long id);

boolean checkUserExistByNickname(String nickname);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.gagu.gagubackend.auth.dao.AuthDAO;
import org.gagu.gagubackend.auth.domain.User;
import org.gagu.gagubackend.auth.dto.request.*;
import org.gagu.gagubackend.auth.service.AuthService;
import org.gagu.gagubackend.global.domain.CommonResponse;
Expand All @@ -24,6 +25,7 @@
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Map;
import java.util.Optional;

@Service
@Slf4j
Expand Down Expand Up @@ -257,6 +259,12 @@ public ResponseEntity<?> getWorkShopDetails(Long id) {
return authDAO.getWorkShopDetails(id);
}

@Override
public boolean checkUserExistByNickname(String nickname) {
Optional<User> userOptional = authDAO.getUserByNickname(nickname);
return userOptional.isPresent();
}

private RequestSaveUserDto getKakaoUserInfo(String accessToken){
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;

@Configuration
@EnableWebSocketMessageBroker // 메세지 브로커가 지원하는 WebSocket 메세지 처리 활성화
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.gagu.gagubackend.auth.service.AuthService;
import org.gagu.gagubackend.chat.domain.ChatRoom;
import org.gagu.gagubackend.chat.domain.ChatRoomMember;
import org.gagu.gagubackend.chat.dto.request.RequestChatContentsDto;
Expand All @@ -18,6 +19,7 @@
import org.gagu.gagubackend.global.domain.enums.ResultCode;
import org.gagu.gagubackend.global.exception.ChatRoomNotFoundException;
import org.gagu.gagubackend.global.exception.NotFoundUserException;
import org.gagu.gagubackend.global.exception.NotMemberException;
import org.gagu.gagubackend.global.security.JwtTokenProvider;
import org.gagu.gagubackend.auth.domain.User;
import org.gagu.gagubackend.auth.dto.request.RequestUserInfoDto;
Expand All @@ -43,10 +45,9 @@ public class ChatController {
private final JwtTokenProvider jwtTokenProvider;
private final ChatService chatService;
private final SimpMessagingTemplate template;
private final UserRepository userRepository;
private final AuthService authService;
private final ChatRoomRepository chatRoomRepository;
private final ChatRoomMemberRepository chatRoomMemberRepository;
private final EstimateRepository estimateRepository;

@Operation(summary = "결제 전 채팅방을 새로 생성합니다.", security = @SecurityRequirement(name="JWT"))
@PostMapping("/new")
Expand Down Expand Up @@ -116,72 +117,39 @@ public void sendMessage(RequestChatContentsDto message,

log.info("[chat] room id : {}",roomNumber);



String nickname = (String) accessor.getSessionAttributes().get("senderNickname");
log.info("[chat] check memeber....");
log.info("[chat] checking memeber....");

if (nickname == null) {
log.error("[chat] session storage is empty!");
throw new IllegalArgumentException("세션에 닉네임이 없습니다.");
}

Long sessionRoomId = (Long) accessor.getSessionAttributes().get("chatRoomId");

if(sessionRoomId==null){ // 처음 메세지 보내는 경우
log.info("[chat] chatting session is empty room id : {}, nickname : {}", roomNumber,nickname);
User user = userRepository.findByNickName(nickname);
if(user == null){
if(sessionRoomId == null){ // 처음 메세지 보내는 경우
log.info("[chat] chatting session is empty. room id : {}, nickname : {}", roomNumber,nickname);

/**
* 사용자 유무, 채팅방 유무, 채팅방 권한 유무 확인
*/
if(!authService.checkUserExistByNickname(nickname)){
throw new NotFoundUserException();
}
Optional<ChatRoom> foundChatRoomList = chatRoomRepository.findById(roomNumber);
String workshop = (String) accessor.getSessionAttributes().get("workshop");

if(workshop == null){
log.info("[socket] first chatting with workshop: {}", workshop);
ChatRoom chatRoom = foundChatRoomList.get();
List<ChatRoomMember> list = chatRoomMemberRepository.findAllByRoomId(chatRoom);
for(ChatRoomMember e : list){
if(e.getMember().getRoles().get(0).equals("ROLE_WORKSHOP")) {
log.info("[socket] workshop is : {}", e.getMember().getNickName());
List<Estimate> estimates = estimateRepository.findAllByNickName(user);
log.info("[socket] esitmate : {}", estimates.toString());
log.info("[socket] collect estimates success!");

for (Estimate tmp : estimates) {
if ((tmp.getPrice() == null) && (tmp.getDescription() == null)) {
tmp.setMakerName(e.getMember().getNickName());
estimateRepository.save(tmp);
log.info("[socket] update estimates success!");
accessor.getSessionAttributes().putIfAbsent("workshop", e.getMember().getNickName());
}
}
}
}
}

if(!foundChatRoomList.isEmpty()){
ChatRoom chatRoom = foundChatRoomList.get();
if(checkMember(chatRoom, user)){ // 채팅방 권한이 있다면
accessor.getSessionAttributes().putIfAbsent("chatRoomId", roomNumber);// 세션에 저장되어 있지 않을때, 세션에 저장
log.info("[chat] successfully put room id to session");
}
log.info("[chat] complete check member");
Thread.sleep(1000); // 비동기적으로 메시지를 처리하기 위해서 1초 지연(옵션)
log.info("[chat] message : {}", message.getContents());
ResponseChatDto responseChatDto = chatService.sendContents(message,roomNumber,nickname);
template.convertAndSend("/sub/chatroom/"+roomNumber,responseChatDto); // 구독하고 있는 채팅방에 전송
}else{
if(!chatService.checkChatRoomExistByRoomId(roomNumber)){
throw new ChatRoomNotFoundException();
}
}else{
if(!chatService.checkChatRoomMemberAuthorization(nickname,roomNumber)){
throw new NotMemberException();
}

// 세션에 저장되어 있지 않을때, 세션에 저장
accessor.getSessionAttributes().putIfAbsent("chatRoomId", roomNumber);
log.info("[chat] successfully put room id to session");
log.info("[chat] complete check member");
}
Thread.sleep(1000); // 비동기적으로 메시지를 처리하기 위해서 1초 지연(옵션)
log.info("[chat] question : {}", message.getContents());
ResponseChatDto responseChatDto = chatService.sendContents(message,roomNumber,nickname);
template.convertAndSend("/sub/chatroom/"+roomNumber,responseChatDto); // 구독하고 있는 채팅방에 전송
}
}

private boolean checkMember(ChatRoom roomId, User member){
return chatRoomMemberRepository.existsChatRoomMemberByRoomIdAndMember(roomId,member);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.gagu.gagubackend.chat.dto.request.RequestChatContentsDto;
import org.gagu.gagubackend.chat.dto.response.Response3DDto;
import org.gagu.gagubackend.chat.dto.response.ResponseImageDto;
import org.gagu.gagubackend.chat.service.ChatService;
import org.gagu.gagubackend.global.config.RedisConfig;
import org.gagu.gagubackend.global.domain.enums.ResultCode;
import org.gagu.gagubackend.global.security.JwtTokenProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.*;
Expand Down Expand Up @@ -135,7 +132,7 @@ public String getFilename() {
@MessageMapping("/gagu-chat/2d") // mapping ex)/pub/gagu-chat/2d
public void chattingWith2D(RequestChatContentsDto message,
SimpMessageHeaderAccessor accessor) throws Exception {
log.info("[2D-chat] send prompt : {}", message.getContents());
// log.info("[2D-chat] send prompt : {}", message.getContents());
Thread.sleep(1000); // 비동기적으로 메시지를 처리하기 위해서 1초 지연(옵션)
String nickname = (String) accessor.getSessionAttributes().get("senderNickname");
ResponseImageDto responseChatDto = chatService.generate2D(message);
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/org/gagu/gagubackend/chat/dao/ChatDAO.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.gagu.gagubackend.chat.dao;

import org.gagu.gagubackend.chat.domain.ChatContents;
import org.gagu.gagubackend.chat.domain.ChatRoom;
import org.gagu.gagubackend.chat.domain.ChatRoomMember;
import org.gagu.gagubackend.chat.dto.request.RequestChatContentsDto;
import org.gagu.gagubackend.chat.dto.request.RequestCreateChatRoomDto;
import org.gagu.gagubackend.chat.dto.request.RequestFCMSendDto;
Expand All @@ -12,6 +14,8 @@
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;

import java.util.Optional;

public interface ChatDAO {
/**
* 사용자 + 공방관계자 채팅방 생성
Expand Down Expand Up @@ -60,4 +64,34 @@ public interface ChatDAO {
*/
void sendMessageTo(RequestFCMSendDto requestFCMSendDto);

/**
* 채팅방 조회
* @param id
* @return
*/
Optional<ChatRoom> getChatRoomByRoomId(Long id);

/**
* 채팅방 권한 확인
* @param nickname
* @param id
* @return
*/
Optional<ChatRoomMember> getChatRoomMember(String nickname, Long id);

/**
* 사용자가 견적 요청
* @param message
* @param nickname
* @return
*/
ResponseChatDto askEstimate(RequestChatContentsDto message, String nickname);

/**
* 견적서 완료
* @param message
* @param nickname
* @return
*/
ResponseChatDto completeEstimate(RequestChatContentsDto message, String nickname);
}
Loading

0 comments on commit 1ff398f

Please sign in to comment.