Skip to content
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
2 changes: 0 additions & 2 deletions src/main/java/com/sayup/SayUp/controller/AuthController.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RestController
@RequestMapping("/api/auth")
@AllArgsConstructor
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/com/sayup/SayUp/controller/ChatRoomController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.sayup.SayUp.controller;

import com.sayup.SayUp.entity.ChatRoom;
import com.sayup.SayUp.service.ChatRoomService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/chat-rooms")
@RequiredArgsConstructor
public class ChatRoomController {

private final ChatRoomService chatRoomService;

@PostMapping("/enter")
public ChatRoom enterRoom(
@RequestParam("currentUserId") Long currentUserId,
@RequestParam("friendUserId") Long friendUserId
) throws Exception {
return chatRoomService.createOrEnterRoom(currentUserId, friendUserId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class FriendshipController {
private final FriendshipService friendshipService;

@PostMapping("/request/{addresseeId}")
public ResponseEntity<?> sendFriendRequest(@AuthenticationPrincipal UserDetails userDetails, @PathVariable Integer addresseeId) {
public ResponseEntity<?> sendFriendRequest(@AuthenticationPrincipal UserDetails userDetails, @PathVariable Long addresseeId) {
if (userDetails == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("User not authenticated");
}
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/sayup/SayUp/dto/AuthRequestDTO.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.sayup.SayUp.dto;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class AuthRequestDTO {
@NotBlank(message = "Email cannot be blank")
@Pattern(regexp="^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])+[.][a-zA-Z]{2,3}$", message="이메일 주소 양식을 확인해주세요")
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/sayup/SayUp/dto/AuthResponseDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
public class AuthResponseDTO {
private final String token;
private final String email;
private final String id;
}
35 changes: 35 additions & 0 deletions src/main/java/com/sayup/SayUp/entity/ChatRoom.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.sayup.SayUp.entity;

import jakarta.persistence.*;
import lombok.*;

import java.time.LocalDateTime;
import java.util.*;

@Entity
@Table(name = "ChatRoom")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ChatRoom {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

// 채팅방에 참여하는 유저들
@ManyToMany
@JoinTable(
name = "ChatRoom_Users",
joinColumns = @JoinColumn(name = "chatroom_id"),
inverseJoinColumns = @JoinColumn(name = "user_id")
)
private List<User> participants = new ArrayList<>();

@Lob
private String metadata; // TTS 벡터 등 JSON 문자열로 저장

private LocalDateTime createdAt = LocalDateTime.now();
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.sayup.SayUp.kakao.controller;

import com.sayup.SayUp.dto.AuthResponseDTO;
import com.sayup.SayUp.entity.User;
import com.sayup.SayUp.kakao.dto.KakaoUserInfoResponseDto;
import com.sayup.SayUp.kakao.service.KakaoService;
import com.sayup.SayUp.security.JwtTokenProvider;
Expand All @@ -26,16 +27,18 @@ public class KakaoCallbackController {
@GetMapping("/callback")
public ResponseEntity<AuthResponseDTO> callback(@RequestParam("code") String code) {
String accessToken = kakaoService.getAccessTokenFromKakao(code);

KakaoUserInfoResponseDto userInfo = kakaoService.getUserInfo(accessToken);

if (userInfo.getKakaoAccount() == null || userInfo.getKakaoAccount().getEmail() == null) {
return ResponseEntity.badRequest().body(new AuthResponseDTO(null, null));
return ResponseEntity.badRequest().body(new AuthResponseDTO(null, null, null));
}

String email = userInfo.getKakaoAccount().getEmail();
authService.loadOrCreateUser(email);
User user = authService.loadOrCreateUser(email);
String jwt = jwtTokenProvider.createTokenFromEmail(email);

return ResponseEntity.ok(new AuthResponseDTO(jwt, email));
AuthResponseDTO response = new AuthResponseDTO(jwt, email, String.valueOf(user.getUserId()));
return ResponseEntity.ok(response);
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/sayup/SayUp/repository/ChatRoomRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.sayup.SayUp.repository;

import com.sayup.SayUp.entity.ChatRoom;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.Optional;

public interface ChatRoomRepository extends JpaRepository<ChatRoom, Long> {

// 두 명의 유저가 모두 참여하고 있는 방을 찾기
@Query("SELECT r FROM ChatRoom r JOIN r.participants p1 JOIN r.participants p2 WHERE p1.userId = :userId1 AND p2.userId = :userId2")
Optional<ChatRoom> findByUserIds(@Param("userId1") Long userId1,
@Param("userId2") Long userId2
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import java.util.Optional;

@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);

// email 또는 username 중 하나라도 일치하는 유저 조회
Expand Down
21 changes: 15 additions & 6 deletions src/main/java/com/sayup/SayUp/service/AuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,17 @@ public void register(AuthRequestDTO authRequestDTO) {
}

// 카카오 로그인 시 사용자 자동 등록
public void loadOrCreateUser(String email) {
User user = new User();
user.setEmail(email);
user.setPassword(passwordEncoder.encode("kakao_user")); // // OAuth 사용자는 비밀번호를 따로 설정하지 않음
public User loadOrCreateUser(String email) {
return userRepository.findByEmail(email)
.orElseGet(() -> {
User user = new User();
user.setEmail(email);
user.setPassword(passwordEncoder.encode("kakao_user")); // OAuth 사용자는 임시 비밀번호

userRepository.save(user);
user.setRole("USER"); // 기본 역할 설정

return userRepository.save(user);
});
}

/**
Expand Down Expand Up @@ -112,8 +117,12 @@ public AuthResponseDTO login(AuthRequestDTO authRequestDTO) {

String jwt = jwtTokenProvider.createToken(authentication);

User user = userRepository.findByEmail(authRequestDTO.getEmail())
.orElseThrow(() -> new RuntimeException("User not found"));

logger.info("Login successful for email: {}", authRequestDTO.getEmail());
return new AuthResponseDTO(jwt, authRequestDTO.getEmail());

return new AuthResponseDTO(jwt, authRequestDTO.getEmail(), String.valueOf(user.getUserId()));
}


Expand Down
56 changes: 56 additions & 0 deletions src/main/java/com/sayup/SayUp/service/ChatRoomService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.sayup.SayUp.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sayup.SayUp.entity.ChatRoom;
import com.sayup.SayUp.entity.User;
import com.sayup.SayUp.repository.ChatRoomRepository;
import com.sayup.SayUp.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class ChatRoomService {

private final ChatRoomRepository chatRoomRepository;
private final UserRepository userRepository;
private final ObjectMapper objectMapper;

/**
* 두 사용자가 참여하는 채팅방이 이미 존재하면 해당 방을 반환
* 없으면 새 채팅방을 생성하여 반환
*
* @param currentUserId 현재 로그인한 유저의 ID
* @param friendUserId 친구로 선택한 유저의 ID
* @return 기존 또는 새로 생성된 채팅방
* @throws Exception JSON 변환 실패 등 예외 발생 시
*/
public ChatRoom createOrEnterRoom(Long currentUserId, Long friendUserId) throws Exception {
// 두 사용자 간의 기존 채팅방이 존재하는지 확인
Optional<ChatRoom> existingRoom = chatRoomRepository.findByUserIds(currentUserId, friendUserId);
if (existingRoom.isPresent()) return existingRoom.get();

// 사용자 정보 조회 (존재하지 않으면 예외 발생)
User currentUser = userRepository.findById(currentUserId).orElseThrow();
User friendUser = userRepository.findById(friendUserId).orElseThrow();

// 친구의 TTS 벡터를 메타데이터에 저장 (key: tts_vector_{friendUserId})
Map<String, Object> metadataMap = new HashMap<>();
metadataMap.put("tts_vector_" + friendUserId, friendUser.getTtsVector());

String metadataJson = objectMapper.writeValueAsString(metadataMap);

// 새로운 채팅방 객체 생성 및 저장
ChatRoom room = ChatRoom.builder()
.participants(Arrays.asList(currentUser, friendUser))
.metadata(metadataJson)
.build();

return chatRoomRepository.save(room);
}
}
16 changes: 15 additions & 1 deletion src/main/java/com/sayup/SayUp/service/FriendshipService.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ public class FriendshipService {
@Autowired
private UserRepository userRepository;

/**
* @param addresseeId: 친구 요청을 받을 사용자의 userId
*/
@Transactional
public void sendFriendRequest(CustomUserDetails requesterDetails, Integer addresseeId) {
public void sendFriendRequest(CustomUserDetails requesterDetails, Long addresseeId) {
User requester = requesterDetails.getUser(); // User 객체 직접 접근
User addressee = userRepository.findById(addresseeId)
.orElseThrow(() -> new RuntimeException("User not found"));
Expand Down Expand Up @@ -65,6 +68,17 @@ public void sendFriendRequest(CustomUserDetails requesterDetails, Integer addres
friendshipRepository.save(relationship);
}

/**
* 전체 흐름 정리
* 1. A 유저가 B에게 친구 요청
* 서버에서 FriendRelationship 생성 -> relationshipId 생성
* 2. B 유저가 getPendingRequests() API 호출
* B를 향한 PENDING 상태의 요청들을 조회
* 각 요청마다 relationshipId + 요청자 정보 반환
* 3. B 유저가 특정 요청을 수락
* /friend/accept API 호출 시 relationshipId 전달
* 서버에서 해당 요청의 상태를 ACCEPTED로 변경
*/
@Transactional
public void acceptFriendRequest(CustomUserDetails addresseeDetails, Long relationshipId) {
User addressee = addresseeDetails.getUser();
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ springdoc.swagger-ui.operations-sorter=alpha
springdoc.packages-to-scan=com.sayup.SayUp.controller

kakao.client_id=${KAKAO}
kakao.redirect_uri=http://localhost:8080/callback
kakao.redirect_uri=http://localhost:8080/api/auth/kakao/callback
15 changes: 0 additions & 15 deletions src/main/resources/templates/login.html

This file was deleted.