diff --git a/pom.xml b/pom.xml index d4b7dbc..8afede8 100644 --- a/pom.xml +++ b/pom.xml @@ -134,6 +134,19 @@ spring-security-test test + + + com.querydsl + querydsl-jpa + 5.0.0 + jakarta + + + com.querydsl + querydsl-apt + 5.0.0 + jakarta + diff --git a/src/main/java/org/gagu/gagubackend/auth/dao/AuthDAO.java b/src/main/java/org/gagu/gagubackend/auth/dao/AuthDAO.java index c874a00..5f378c8 100644 --- a/src/main/java/org/gagu/gagubackend/auth/dao/AuthDAO.java +++ b/src/main/java/org/gagu/gagubackend/auth/dao/AuthDAO.java @@ -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 생성 / 닉네임 중복 여부 확인 후 저장 @@ -68,4 +71,11 @@ public interface AuthDAO { * @return */ ResponseEntity getWorkShopDetails(Long id); + + /** + * 범용적으로 사용하는 닉네임으로 유저 조회 + * @param nickname + * @return + */ + Optional getUserByNickname(String nickname); } diff --git a/src/main/java/org/gagu/gagubackend/auth/dao/impl/AuthDAOImpl.java b/src/main/java/org/gagu/gagubackend/auth/dao/impl/AuthDAOImpl.java index da976dc..7dc10e4 100644 --- a/src/main/java/org/gagu/gagubackend/auth/dao/impl/AuthDAOImpl.java +++ b/src/main/java/org/gagu/gagubackend/auth/dao/impl/AuthDAOImpl.java @@ -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; @@ -439,6 +440,11 @@ public ResponseEntity getWorkShopDetails(Long id) { } } + @Override + public Optional getUserByNickname(String nickname) { + return userRepository.findUserByNickname(nickname); + } + private void updateUserNickName(String nickname, String changeNickname){ log.info("[auth] update user nickname...."); List chatLst = chatRoomRepository.findAllByRoomNameContains(nickname); diff --git a/src/main/java/org/gagu/gagubackend/auth/repository/UserRepository.java b/src/main/java/org/gagu/gagubackend/auth/repository/UserRepository.java index 2690518..aab969e 100644 --- a/src/main/java/org/gagu/gagubackend/auth/repository/UserRepository.java +++ b/src/main/java/org/gagu/gagubackend/auth/repository/UserRepository.java @@ -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 { +public interface UserRepository extends JpaRepository, UserRepositoryCustom { User findByEmailAndLoginType(String name, String loginType); User findByResourceIdAndLoginType(String resourceId, String loginType); List findAllByEmailAndLoginType(String email, String loginType); diff --git a/src/main/java/org/gagu/gagubackend/auth/repository/custom/UserRepositoryCustom.java b/src/main/java/org/gagu/gagubackend/auth/repository/custom/UserRepositoryCustom.java new file mode 100644 index 0000000..562b221 --- /dev/null +++ b/src/main/java/org/gagu/gagubackend/auth/repository/custom/UserRepositoryCustom.java @@ -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 findUserByNickname(String nickname); +} diff --git a/src/main/java/org/gagu/gagubackend/auth/repository/custom/impl/UserRepositoryCustomImpl.java b/src/main/java/org/gagu/gagubackend/auth/repository/custom/impl/UserRepositoryCustomImpl.java new file mode 100644 index 0000000..a56ed87 --- /dev/null +++ b/src/main/java/org/gagu/gagubackend/auth/repository/custom/impl/UserRepositoryCustomImpl.java @@ -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 findUserByNickname(String nickname) { + QUser qUser = QUser.user; + + return Optional.ofNullable(jpaQueryFactory.select(qUser) + .from(qUser) + .where(qUser.nickName.eq(nickname)) + .fetchOne()); + } +} diff --git a/src/main/java/org/gagu/gagubackend/auth/service/AuthService.java b/src/main/java/org/gagu/gagubackend/auth/service/AuthService.java index 75243f2..143c162 100644 --- a/src/main/java/org/gagu/gagubackend/auth/service/AuthService.java +++ b/src/main/java/org/gagu/gagubackend/auth/service/AuthService.java @@ -79,4 +79,6 @@ public interface AuthService { * @return */ ResponseEntity getWorkShopDetails(Long id); + + boolean checkUserExistByNickname(String nickname); } diff --git a/src/main/java/org/gagu/gagubackend/auth/service/impl/AuthServiceImpl.java b/src/main/java/org/gagu/gagubackend/auth/service/impl/AuthServiceImpl.java index d3d0ba6..757548d 100644 --- a/src/main/java/org/gagu/gagubackend/auth/service/impl/AuthServiceImpl.java +++ b/src/main/java/org/gagu/gagubackend/auth/service/impl/AuthServiceImpl.java @@ -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; @@ -24,6 +25,7 @@ import java.io.IOException; import java.security.SecureRandom; import java.util.Map; +import java.util.Optional; @Service @Slf4j @@ -257,6 +259,12 @@ public ResponseEntity getWorkShopDetails(Long id) { return authDAO.getWorkShopDetails(id); } + @Override + public boolean checkUserExistByNickname(String nickname) { + Optional userOptional = authDAO.getUserByNickname(nickname); + return userOptional.isPresent(); + } + private RequestSaveUserDto getKakaoUserInfo(String accessToken){ RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); diff --git a/src/main/java/org/gagu/gagubackend/chat/config/WebSocketConfig.java b/src/main/java/org/gagu/gagubackend/chat/config/WebSocketConfig.java index e94ea76..6cced73 100644 --- a/src/main/java/org/gagu/gagubackend/chat/config/WebSocketConfig.java +++ b/src/main/java/org/gagu/gagubackend/chat/config/WebSocketConfig.java @@ -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 메세지 처리 활성화 diff --git a/src/main/java/org/gagu/gagubackend/chat/controller/ChatController.java b/src/main/java/org/gagu/gagubackend/chat/controller/ChatController.java index 6b3af27..ae27913 100644 --- a/src/main/java/org/gagu/gagubackend/chat/controller/ChatController.java +++ b/src/main/java/org/gagu/gagubackend/chat/controller/ChatController.java @@ -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; @@ -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; @@ -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") @@ -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 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 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 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); } } diff --git a/src/main/java/org/gagu/gagubackend/chat/controller/ImageController.java b/src/main/java/org/gagu/gagubackend/chat/controller/ImageController.java index 698995f..2d1763f 100644 --- a/src/main/java/org/gagu/gagubackend/chat/controller/ImageController.java +++ b/src/main/java/org/gagu/gagubackend/chat/controller/ImageController.java @@ -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.*; @@ -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); diff --git a/src/main/java/org/gagu/gagubackend/chat/dao/ChatDAO.java b/src/main/java/org/gagu/gagubackend/chat/dao/ChatDAO.java index f476d95..c249e5f 100644 --- a/src/main/java/org/gagu/gagubackend/chat/dao/ChatDAO.java +++ b/src/main/java/org/gagu/gagubackend/chat/dao/ChatDAO.java @@ -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; @@ -12,6 +14,8 @@ import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; +import java.util.Optional; + public interface ChatDAO { /** * 사용자 + 공방관계자 채팅방 생성 @@ -60,4 +64,34 @@ public interface ChatDAO { */ void sendMessageTo(RequestFCMSendDto requestFCMSendDto); + /** + * 채팅방 조회 + * @param id + * @return + */ + Optional getChatRoomByRoomId(Long id); + + /** + * 채팅방 권한 확인 + * @param nickname + * @param id + * @return + */ + Optional 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); } diff --git a/src/main/java/org/gagu/gagubackend/chat/dao/impl/ChatDAOImpl.java b/src/main/java/org/gagu/gagubackend/chat/dao/impl/ChatDAOImpl.java index 59b9476..2a11512 100644 --- a/src/main/java/org/gagu/gagubackend/chat/dao/impl/ChatDAOImpl.java +++ b/src/main/java/org/gagu/gagubackend/chat/dao/impl/ChatDAOImpl.java @@ -19,12 +19,15 @@ import org.gagu.gagubackend.chat.repository.ChatContentsRepository; import org.gagu.gagubackend.chat.repository.ChatRoomMemberRepository; import org.gagu.gagubackend.chat.repository.ChatRoomRepository; +import org.gagu.gagubackend.estimate.domain.Estimate; +import org.gagu.gagubackend.estimate.repository.EstimateRepository; import org.gagu.gagubackend.global.domain.enums.ResultCode; import org.gagu.gagubackend.global.exception.ChatRoomNotFoundException; import org.gagu.gagubackend.global.exception.NotMemberException; import org.gagu.gagubackend.auth.domain.User; import org.gagu.gagubackend.auth.dto.request.RequestUserInfoDto; import org.gagu.gagubackend.auth.repository.UserRepository; +import org.gagu.gagubackend.global.service.TimeService; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -46,7 +49,9 @@ public class ChatDAOImpl implements ChatDAO { private final ChatRoomMemberRepository chatRoomMemberRepository; private final ChatRoomRepository chatRoomRepository; private final ChatContentsRepository chatContentsRepository; + private final EstimateRepository estimateRepository; private final FirebaseMessaging firebaseMessaging; + private final TimeService timeService; @Override public ResponseEntity createChatRoom(RequestUserInfoDto userInfoDto, RequestCreateChatRoomDto requestCreateChatRoomDto) { @@ -155,9 +160,9 @@ public ResponseChatDto saveMessage(RequestChatContentsDto requestChatContentsDto // 저장되는 채팅 내역 ChatContents chatContents = ChatContents.builder() - .sendTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd a HH시 mm분 ss초"))) + .sendTime(timeService.makeTimeTemplate()) .sender(user) - .message(requestChatContentsDto.getContents()) + .message(requestChatContentsDto.getChatContentsInfo().getContents()) .chatRoomId(roomId) .build(); @@ -264,6 +269,48 @@ public void sendMessageTo(RequestFCMSendDto requestFCMSendDto) { } } + @Override + public Optional getChatRoomByRoomId(Long id) { + return chatRoomRepository.findChatRoomByRoomId(id); + } + + @Override + public Optional getChatRoomMember(String nickname, Long id) { + return chatRoomMemberRepository.getChatRoomMemberByRoomIdAndUser(id, nickname); + } + + @Override + public ResponseChatDto askEstimate(RequestChatContentsDto message, String nickname) { + RequestChatContentsDto.EstimateInfo estimateInfo = message.getEstimateInfo(); + + return ResponseChatDto.builder() + .contents(estimateInfo.getTemplate()) + .nickName(nickname) + .time(timeService.makeTimeTemplate()) + .build(); + } + + @Override + public ResponseChatDto completeEstimate(RequestChatContentsDto message, String nickname) { + RequestChatContentsDto.EstimateInfo estimateInfo = message.getEstimateInfo(); + Optional estimateOptional = estimateRepository.findEstimateById(estimateInfo.getEstimateId()); + + if(estimateOptional.isPresent()){ + Estimate estimate = estimateOptional.get(); + estimate.setMakerName(nickname); + + estimateRepository.save(estimate); + return ResponseChatDto.builder() + .contents(estimateInfo.getTemplate()) + .nickName(nickname) + .time(timeService.makeTimeTemplate()) + .build(); + }else{ + log.error("[CHAT-DAO-IMPL] fail to get estimate info!"); + throw new NullPointerException(); + } + } + private boolean checkUserExist(String userEmail, String userNickname){ log.info("[chat] check user exist"); diff --git a/src/main/java/org/gagu/gagubackend/chat/dto/request/RequestChatContentsDto.java b/src/main/java/org/gagu/gagubackend/chat/dto/request/RequestChatContentsDto.java index fc336eb..2c9a365 100644 --- a/src/main/java/org/gagu/gagubackend/chat/dto/request/RequestChatContentsDto.java +++ b/src/main/java/org/gagu/gagubackend/chat/dto/request/RequestChatContentsDto.java @@ -4,12 +4,28 @@ import org.gagu.gagubackend.global.domain.enums.MessageType; @Getter -@Setter -@NoArgsConstructor -@AllArgsConstructor @ToString +@AllArgsConstructor @Builder public class RequestChatContentsDto { private MessageType type; - private String contents; + private String prompt; + private EstimateInfo estimateInfo; + private ChatContentsInfo chatContentsInfo; + + @Getter + @AllArgsConstructor + @Builder + public static class EstimateInfo{ + private String template; + private Long estimateId; + public EstimateInfo(){} + } + @Getter + @AllArgsConstructor + @Builder + public static class ChatContentsInfo{ + private String contents; + public ChatContentsInfo(){} + } } diff --git a/src/main/java/org/gagu/gagubackend/chat/dto/response/ResponseChatDto.java b/src/main/java/org/gagu/gagubackend/chat/dto/response/ResponseChatDto.java index e4f45c1..8a5d683 100644 --- a/src/main/java/org/gagu/gagubackend/chat/dto/response/ResponseChatDto.java +++ b/src/main/java/org/gagu/gagubackend/chat/dto/response/ResponseChatDto.java @@ -2,10 +2,7 @@ import lombok.*; -import java.time.LocalDateTime; @Getter -@Setter -@NoArgsConstructor @AllArgsConstructor @ToString @Builder diff --git a/src/main/java/org/gagu/gagubackend/chat/repository/ChatRoomMemberRepository.java b/src/main/java/org/gagu/gagubackend/chat/repository/ChatRoomMemberRepository.java index 32208ea..e8ca9e7 100644 --- a/src/main/java/org/gagu/gagubackend/chat/repository/ChatRoomMemberRepository.java +++ b/src/main/java/org/gagu/gagubackend/chat/repository/ChatRoomMemberRepository.java @@ -3,6 +3,7 @@ import org.gagu.gagubackend.chat.domain.ChatRoom; import org.gagu.gagubackend.chat.domain.ChatRoomMember; import org.gagu.gagubackend.auth.domain.User; +import org.gagu.gagubackend.chat.repository.custom.ChatRoomMemberRepositoryCustom; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -10,7 +11,7 @@ import java.util.List; import java.util.Optional; -public interface ChatRoomMemberRepository extends JpaRepository { +public interface ChatRoomMemberRepository extends JpaRepository, ChatRoomMemberRepositoryCustom { boolean existsChatRoomMemberByRoomId(ChatRoom chatRoom); List findAllByRoomId(ChatRoom chatRoom); List findAllByMember(User user); diff --git a/src/main/java/org/gagu/gagubackend/chat/repository/ChatRoomRepository.java b/src/main/java/org/gagu/gagubackend/chat/repository/ChatRoomRepository.java index 24c0978..1bc2dbd 100644 --- a/src/main/java/org/gagu/gagubackend/chat/repository/ChatRoomRepository.java +++ b/src/main/java/org/gagu/gagubackend/chat/repository/ChatRoomRepository.java @@ -1,13 +1,14 @@ package org.gagu.gagubackend.chat.repository; import org.gagu.gagubackend.chat.domain.ChatRoom; +import org.gagu.gagubackend.chat.repository.custom.ChatRoomRepositoryCustom; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; -public interface ChatRoomRepository extends JpaRepository { +public interface ChatRoomRepository extends JpaRepository, ChatRoomRepositoryCustom { Page findByIdIn(List roomIds, Pageable pageable); List findAllByRoomNameContains(String nickname); } diff --git a/src/main/java/org/gagu/gagubackend/chat/repository/custom/ChatRoomMemberRepositoryCustom.java b/src/main/java/org/gagu/gagubackend/chat/repository/custom/ChatRoomMemberRepositoryCustom.java new file mode 100644 index 0000000..27e7028 --- /dev/null +++ b/src/main/java/org/gagu/gagubackend/chat/repository/custom/ChatRoomMemberRepositoryCustom.java @@ -0,0 +1,9 @@ +package org.gagu.gagubackend.chat.repository.custom; + +import org.gagu.gagubackend.chat.domain.ChatRoomMember; + +import java.util.Optional; + +public interface ChatRoomMemberRepositoryCustom { + Optional getChatRoomMemberByRoomIdAndUser(Long roomId, String nickname); +} diff --git a/src/main/java/org/gagu/gagubackend/chat/repository/custom/ChatRoomRepositoryCustom.java b/src/main/java/org/gagu/gagubackend/chat/repository/custom/ChatRoomRepositoryCustom.java new file mode 100644 index 0000000..ca9209f --- /dev/null +++ b/src/main/java/org/gagu/gagubackend/chat/repository/custom/ChatRoomRepositoryCustom.java @@ -0,0 +1,9 @@ +package org.gagu.gagubackend.chat.repository.custom; + +import org.gagu.gagubackend.chat.domain.ChatRoom; + +import java.util.Optional; + +public interface ChatRoomRepositoryCustom { + Optional findChatRoomByRoomId(Long id); +} diff --git a/src/main/java/org/gagu/gagubackend/chat/repository/custom/impl/ChatRoomMemberRepositoryCustomImpl.java b/src/main/java/org/gagu/gagubackend/chat/repository/custom/impl/ChatRoomMemberRepositoryCustomImpl.java new file mode 100644 index 0000000..a354028 --- /dev/null +++ b/src/main/java/org/gagu/gagubackend/chat/repository/custom/impl/ChatRoomMemberRepositoryCustomImpl.java @@ -0,0 +1,30 @@ +package org.gagu.gagubackend.chat.repository.custom.impl; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import org.gagu.gagubackend.chat.domain.ChatRoomMember; +import org.gagu.gagubackend.chat.domain.QChatRoomMember; +import org.gagu.gagubackend.chat.repository.custom.ChatRoomMemberRepositoryCustom; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +public class ChatRoomMemberRepositoryCustomImpl implements ChatRoomMemberRepositoryCustom { + private final JPAQueryFactory jpaQueryFactory; + @Autowired + public ChatRoomMemberRepositoryCustomImpl(EntityManager em) { + this.jpaQueryFactory = new JPAQueryFactory(em); + } + @Override + public Optional getChatRoomMemberByRoomIdAndUser(Long roomId, String nickname) { + QChatRoomMember qChatRoomMember = QChatRoomMember.chatRoomMember; + + return Optional.ofNullable( + jpaQueryFactory.select(qChatRoomMember) + .from(qChatRoomMember) + .where(qChatRoomMember.member.nickName.eq(nickname).and(qChatRoomMember.roomId.id.eq(roomId))) + .fetchOne()); + } +} diff --git a/src/main/java/org/gagu/gagubackend/chat/repository/custom/impl/ChatRoomRepositoryCustomImpl.java b/src/main/java/org/gagu/gagubackend/chat/repository/custom/impl/ChatRoomRepositoryCustomImpl.java new file mode 100644 index 0000000..1d56b3c --- /dev/null +++ b/src/main/java/org/gagu/gagubackend/chat/repository/custom/impl/ChatRoomRepositoryCustomImpl.java @@ -0,0 +1,31 @@ +package org.gagu.gagubackend.chat.repository.custom.impl; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import org.gagu.gagubackend.chat.domain.ChatRoom; +import org.gagu.gagubackend.chat.domain.QChatRoom; +import org.gagu.gagubackend.chat.repository.custom.ChatRoomRepositoryCustom; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +public class ChatRoomRepositoryCustomImpl implements ChatRoomRepositoryCustom { + + private final JPAQueryFactory jpaQueryFactory; + @Autowired + public ChatRoomRepositoryCustomImpl(EntityManager em) { + this.jpaQueryFactory = new JPAQueryFactory(em); + } + + @Override + public Optional findChatRoomByRoomId(Long id) { + QChatRoom qChatRoom = QChatRoom.chatRoom1; + return Optional.ofNullable(jpaQueryFactory + .select(qChatRoom) + .from(qChatRoom) + .where(qChatRoom.id.eq(id)) + .fetchOne()); + } +} diff --git a/src/main/java/org/gagu/gagubackend/chat/service/ChatService.java b/src/main/java/org/gagu/gagubackend/chat/service/ChatService.java index 67b737d..62415a6 100644 --- a/src/main/java/org/gagu/gagubackend/chat/service/ChatService.java +++ b/src/main/java/org/gagu/gagubackend/chat/service/ChatService.java @@ -65,4 +65,19 @@ public interface ChatService { ResponseImageDto generate2D(RequestChatContentsDto message) throws JsonProcessingException; ResponseEntity sendMessageTo(ReqeustDto dto); + + /** + * 범용적으로 사용하는 채팅방 조회 + * @param id + * @return + */ + boolean checkChatRoomExistByRoomId(Long id); + + /** + * 채팅방 권한 확인 + * @param nickname + * @param id + * @return + */ + boolean checkChatRoomMemberAuthorization(String nickname, Long id); } diff --git a/src/main/java/org/gagu/gagubackend/chat/service/impl/ChatServiceImpl.java b/src/main/java/org/gagu/gagubackend/chat/service/impl/ChatServiceImpl.java index d55214f..063ca0c 100644 --- a/src/main/java/org/gagu/gagubackend/chat/service/impl/ChatServiceImpl.java +++ b/src/main/java/org/gagu/gagubackend/chat/service/impl/ChatServiceImpl.java @@ -4,17 +4,15 @@ import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.ObjectMetadata; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.auth.oauth2.GoogleCredentials; import com.google.firebase.messaging.FirebaseMessaging; import com.google.firebase.messaging.Message; import com.google.firebase.messaging.Notification; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.gagu.gagubackend.chat.config.FCMConfig; import org.gagu.gagubackend.chat.dao.ChatDAO; -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.*; import org.gagu.gagubackend.chat.dto.response.*; import org.gagu.gagubackend.chat.service.ChatService; @@ -27,25 +25,19 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.http.*; -import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; - import java.io.ByteArrayInputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Optional; @Service @Slf4j @RequiredArgsConstructor public class ChatServiceImpl implements ChatService { private final ChatDAO chatDAO; - private final EstimateDAO estimateDAO; private final AmazonS3Client amazonS3Client; private final UserRepository userRepository; private final FirebaseMessaging firebaseMessaging; @@ -71,8 +63,12 @@ public ResponseChatDto sendContents(RequestChatContentsDto message, Long roomNum switch (messageType){ case "SEND": return chatDAO.saveMessage(message,roomNumber,nickname); + case "REQUEST_ESTIMATE": + return chatDAO.askEstimate(message,nickname); + case "RESPONSE_ESTIMATE": + return chatDAO.completeEstimate(message,nickname); } - return null; + throw new RuntimeException(); } @Override @@ -93,8 +89,8 @@ public ResponseImageDto generate2D(RequestChatContentsDto message) throws JsonPr case "LLM": Map requestBody = new HashMap<>(); ObjectMapper objectMapper = new ObjectMapper(); - requestBody.put("prompt", message.getContents()); - log.info("[2D-LLM] prompt : {}", message.getContents()); + requestBody.put("prompt", message.getPrompt()); + log.info("[2D-LLM] prompt : {}", message.getPrompt()); RestTemplate restTemplate = new RestTemplate(); HttpHeaders header = new HttpHeaders(); @@ -171,4 +167,16 @@ public ResponseEntity sendMessageTo(ReqeustDto dto) { return ResultCode.FAIL.toResponseEntity(); } } + + @Override + public boolean checkChatRoomExistByRoomId(Long id) { + Optional chatRoomOptional = chatDAO.getChatRoomByRoomId(id); + return chatRoomOptional.isPresent(); + } + + @Override + public boolean checkChatRoomMemberAuthorization(String nickname, Long id) { + Optional chatRoomMemberOptional = chatDAO.getChatRoomMember(nickname, id); + return chatRoomMemberOptional.isPresent(); + } } diff --git a/src/main/java/org/gagu/gagubackend/estimate/repository/EstimateRepository.java b/src/main/java/org/gagu/gagubackend/estimate/repository/EstimateRepository.java index 36fea85..8768fa4 100644 --- a/src/main/java/org/gagu/gagubackend/estimate/repository/EstimateRepository.java +++ b/src/main/java/org/gagu/gagubackend/estimate/repository/EstimateRepository.java @@ -2,13 +2,14 @@ import org.gagu.gagubackend.auth.domain.User; import org.gagu.gagubackend.estimate.domain.Estimate; +import org.gagu.gagubackend.estimate.repository.custom.EstimateRepositoryCustom; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; -public interface EstimateRepository extends JpaRepository { +public interface EstimateRepository extends JpaRepository, EstimateRepositoryCustom{ Page findByNickName(User user, Pageable pageable); Page findByNickNameAndMakerName(User user, String workshop, Pageable pageable); List findAllByNickName(User user); diff --git a/src/main/java/org/gagu/gagubackend/estimate/repository/custom/EstimateRepositoryCustom.java b/src/main/java/org/gagu/gagubackend/estimate/repository/custom/EstimateRepositoryCustom.java new file mode 100644 index 0000000..8f78707 --- /dev/null +++ b/src/main/java/org/gagu/gagubackend/estimate/repository/custom/EstimateRepositoryCustom.java @@ -0,0 +1,9 @@ +package org.gagu.gagubackend.estimate.repository.custom; + +import org.gagu.gagubackend.estimate.domain.Estimate; + +import java.util.Optional; + +public interface EstimateRepositoryCustom { + Optional findEstimateById(Long id); +} diff --git a/src/main/java/org/gagu/gagubackend/estimate/repository/custom/impl/EstimateRepositoryCustomImpl.java b/src/main/java/org/gagu/gagubackend/estimate/repository/custom/impl/EstimateRepositoryCustomImpl.java new file mode 100644 index 0000000..2d7b464 --- /dev/null +++ b/src/main/java/org/gagu/gagubackend/estimate/repository/custom/impl/EstimateRepositoryCustomImpl.java @@ -0,0 +1,29 @@ +package org.gagu.gagubackend.estimate.repository.custom.impl; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import org.gagu.gagubackend.estimate.domain.Estimate; +import org.gagu.gagubackend.estimate.domain.QEstimate; +import org.gagu.gagubackend.estimate.repository.custom.EstimateRepositoryCustom; +import org.springframework.stereotype.Service; + +import java.util.Optional; +@Service +public class EstimateRepositoryCustomImpl implements EstimateRepositoryCustom { + + private final JPAQueryFactory jpaQueryFactory; + + public EstimateRepositoryCustomImpl(EntityManager em) { + this.jpaQueryFactory = new JPAQueryFactory(em); + } + + @Override + public Optional findEstimateById(Long id) { + QEstimate qEstimate = QEstimate.estimate; + return Optional.ofNullable(jpaQueryFactory + .select(qEstimate) + .from(qEstimate) + .where(qEstimate.id.eq(id)) + .fetchOne()); + } +} diff --git a/src/main/java/org/gagu/gagubackend/global/domain/enums/MessageType.java b/src/main/java/org/gagu/gagubackend/global/domain/enums/MessageType.java index 77a7ec8..def3602 100644 --- a/src/main/java/org/gagu/gagubackend/global/domain/enums/MessageType.java +++ b/src/main/java/org/gagu/gagubackend/global/domain/enums/MessageType.java @@ -3,5 +3,6 @@ public enum MessageType { SEND, LLM, - ESTIMATE + RESPONSE_ESTIMATE, + REQUEST_ESTIMATE } diff --git a/src/main/java/org/gagu/gagubackend/global/service/TimeService.java b/src/main/java/org/gagu/gagubackend/global/service/TimeService.java new file mode 100644 index 0000000..b77ca88 --- /dev/null +++ b/src/main/java/org/gagu/gagubackend/global/service/TimeService.java @@ -0,0 +1,5 @@ +package org.gagu.gagubackend.global.service; + +public interface TimeService { + String makeTimeTemplate(); +} diff --git a/src/main/java/org/gagu/gagubackend/global/service/impl/TimeServiceImpl.java b/src/main/java/org/gagu/gagubackend/global/service/impl/TimeServiceImpl.java new file mode 100644 index 0000000..f2fc9e8 --- /dev/null +++ b/src/main/java/org/gagu/gagubackend/global/service/impl/TimeServiceImpl.java @@ -0,0 +1,15 @@ +package org.gagu.gagubackend.global.service.impl; + +import org.gagu.gagubackend.global.service.TimeService; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +@Service +public class TimeServiceImpl implements TimeService { + @Override + public String makeTimeTemplate() { + return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd a HH시 mm분 ss초")); + } +}