Fix ChatService customer ID domain logic

- FIXED: ChatService now uses customer.customerId instead of users.id for CUSTOMER role
- getConversations(): Resolve Customer entity to get customerId for filtering
- getConversation(): Verify ownership using customer.customerId
- sendMessage(): Updated signature to accept role parameter for staff assignment logic
- getMessages(): Verify conversation ownership using customer.customerId
- ChatController: Updated sendMessage call to pass user.getRole()

This fixes the domain bug where conversation.customerId (references customer table)
was being incorrectly populated with users.id instead of customer.customerId.

Phase 3B
This commit is contained in:
2026-03-09 01:24:10 -06:00
parent a0c782f4cc
commit dec0986830
2 changed files with 32 additions and 11 deletions

View File

@@ -5,6 +5,7 @@ import com.petshop.backend.dto.chat.ConversationResponse;
import com.petshop.backend.dto.chat.MessageRequest; import com.petshop.backend.dto.chat.MessageRequest;
import com.petshop.backend.dto.chat.MessageResponse; import com.petshop.backend.dto.chat.MessageResponse;
import com.petshop.backend.entity.User; import com.petshop.backend.entity.User;
import com.petshop.backend.repository.CustomerRepository;
import com.petshop.backend.repository.UserRepository; import com.petshop.backend.repository.UserRepository;
import com.petshop.backend.service.ChatService; import com.petshop.backend.service.ChatService;
import jakarta.validation.Valid; import jakarta.validation.Valid;
@@ -24,10 +25,12 @@ public class ChatController {
private final ChatService chatService; private final ChatService chatService;
private final UserRepository userRepository; private final UserRepository userRepository;
private final CustomerRepository customerRepository;
public ChatController(ChatService chatService, UserRepository userRepository) { public ChatController(ChatService chatService, UserRepository userRepository, CustomerRepository customerRepository) {
this.chatService = chatService; this.chatService = chatService;
this.userRepository = userRepository; this.userRepository = userRepository;
this.customerRepository = customerRepository;
} }
private User getCurrentUser() { private User getCurrentUser() {
@@ -66,7 +69,7 @@ public class ChatController {
@PathVariable Long id, @PathVariable Long id,
@Valid @RequestBody MessageRequest request) { @Valid @RequestBody MessageRequest request) {
User user = getCurrentUser(); User user = getCurrentUser();
MessageResponse message = chatService.sendMessage(id, user.getId(), request); MessageResponse message = chatService.sendMessage(id, user.getId(), user.getRole(), request);
return ResponseEntity.status(HttpStatus.CREATED).body(message); return ResponseEntity.status(HttpStatus.CREATED).body(message);
} }

View File

@@ -5,10 +5,12 @@ import com.petshop.backend.dto.chat.ConversationResponse;
import com.petshop.backend.dto.chat.MessageRequest; import com.petshop.backend.dto.chat.MessageRequest;
import com.petshop.backend.dto.chat.MessageResponse; import com.petshop.backend.dto.chat.MessageResponse;
import com.petshop.backend.entity.Conversation; import com.petshop.backend.entity.Conversation;
import com.petshop.backend.entity.Customer;
import com.petshop.backend.entity.Message; import com.petshop.backend.entity.Message;
import com.petshop.backend.entity.User; import com.petshop.backend.entity.User;
import com.petshop.backend.exception.ResourceNotFoundException; import com.petshop.backend.exception.ResourceNotFoundException;
import com.petshop.backend.repository.ConversationRepository; import com.petshop.backend.repository.ConversationRepository;
import com.petshop.backend.repository.CustomerRepository;
import com.petshop.backend.repository.MessageRepository; import com.petshop.backend.repository.MessageRepository;
import com.petshop.backend.repository.UserRepository; import com.petshop.backend.repository.UserRepository;
import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.AccessDeniedException;
@@ -24,13 +26,16 @@ public class ChatService {
private final ConversationRepository conversationRepository; private final ConversationRepository conversationRepository;
private final MessageRepository messageRepository; private final MessageRepository messageRepository;
private final UserRepository userRepository; private final UserRepository userRepository;
private final CustomerRepository customerRepository;
public ChatService(ConversationRepository conversationRepository, public ChatService(ConversationRepository conversationRepository,
MessageRepository messageRepository, MessageRepository messageRepository,
UserRepository userRepository) { UserRepository userRepository,
CustomerRepository customerRepository) {
this.conversationRepository = conversationRepository; this.conversationRepository = conversationRepository;
this.messageRepository = messageRepository; this.messageRepository = messageRepository;
this.userRepository = userRepository; this.userRepository = userRepository;
this.customerRepository = customerRepository;
} }
@Transactional @Transactional
@@ -38,8 +43,11 @@ public class ChatService {
User user = userRepository.findById(userId) User user = userRepository.findById(userId)
.orElseThrow(() -> new ResourceNotFoundException("User not found")); .orElseThrow(() -> new ResourceNotFoundException("User not found"));
Customer customer = customerRepository.findByUserId(userId)
.orElseThrow(() -> new ResourceNotFoundException("Customer record not found for user"));
Conversation conversation = new Conversation(); Conversation conversation = new Conversation();
conversation.setCustomerId(userId); conversation.setCustomerId(customer.getCustomerId());
conversation.setStatus(Conversation.ConversationStatus.OPEN); conversation.setStatus(Conversation.ConversationStatus.OPEN);
conversation = conversationRepository.save(conversation); conversation = conversationRepository.save(conversation);
@@ -57,7 +65,9 @@ public class ChatService {
List<Conversation> conversations; List<Conversation> conversations;
if (role == User.Role.CUSTOMER) { if (role == User.Role.CUSTOMER) {
conversations = conversationRepository.findByCustomerId(userId); Customer customer = customerRepository.findByUserId(userId)
.orElseThrow(() -> new ResourceNotFoundException("Customer record not found for user"));
conversations = conversationRepository.findByCustomerId(customer.getCustomerId());
} else if (role == User.Role.STAFF) { } else if (role == User.Role.STAFF) {
conversations = conversationRepository.findByStaffId(userId); conversations = conversationRepository.findByStaffId(userId);
if (conversations.isEmpty()) { if (conversations.isEmpty()) {
@@ -80,8 +90,12 @@ public class ChatService {
Conversation conversation = conversationRepository.findById(conversationId) Conversation conversation = conversationRepository.findById(conversationId)
.orElseThrow(() -> new ResourceNotFoundException("Conversation not found")); .orElseThrow(() -> new ResourceNotFoundException("Conversation not found"));
if (role == User.Role.CUSTOMER && !conversation.getCustomerId().equals(userId)) { if (role == User.Role.CUSTOMER) {
throw new AccessDeniedException("You can only view your own conversations"); Customer customer = customerRepository.findByUserId(userId)
.orElseThrow(() -> new ResourceNotFoundException("Customer record not found for user"));
if (!conversation.getCustomerId().equals(customer.getCustomerId())) {
throw new AccessDeniedException("You can only view your own conversations");
}
} }
List<Message> messages = messageRepository.findByConversationIdOrderByTimestampAsc(conversationId); List<Message> messages = messageRepository.findByConversationIdOrderByTimestampAsc(conversationId);
@@ -91,7 +105,7 @@ public class ChatService {
} }
@Transactional @Transactional
public MessageResponse sendMessage(Long conversationId, Long userId, MessageRequest request) { public MessageResponse sendMessage(Long conversationId, Long userId, User.Role role, MessageRequest request) {
Conversation conversation = conversationRepository.findById(conversationId) Conversation conversation = conversationRepository.findById(conversationId)
.orElseThrow(() -> new ResourceNotFoundException("Conversation not found")); .orElseThrow(() -> new ResourceNotFoundException("Conversation not found"));
@@ -102,7 +116,7 @@ public class ChatService {
message.setIsRead(false); message.setIsRead(false);
message = messageRepository.save(message); message = messageRepository.save(message);
if (conversation.getStaffId() == null && !userId.equals(conversation.getCustomerId())) { if (role == User.Role.STAFF && conversation.getStaffId() == null) {
conversation.setStaffId(userId); conversation.setStaffId(userId);
conversationRepository.save(conversation); conversationRepository.save(conversation);
} }
@@ -114,8 +128,12 @@ public class ChatService {
Conversation conversation = conversationRepository.findById(conversationId) Conversation conversation = conversationRepository.findById(conversationId)
.orElseThrow(() -> new ResourceNotFoundException("Conversation not found")); .orElseThrow(() -> new ResourceNotFoundException("Conversation not found"));
if (role == User.Role.CUSTOMER && !conversation.getCustomerId().equals(userId)) { if (role == User.Role.CUSTOMER) {
throw new AccessDeniedException("You can only view messages from your own conversations"); Customer customer = customerRepository.findByUserId(userId)
.orElseThrow(() -> new ResourceNotFoundException("Customer record not found for user"));
if (!conversation.getCustomerId().equals(customer.getCustomerId())) {
throw new AccessDeniedException("You can only view messages from your own conversations");
}
} }
List<Message> messages = messageRepository.findByConversationIdOrderByTimestampAsc(conversationId); List<Message> messages = messageRepository.findByConversationIdOrderByTimestampAsc(conversationId);