Skip to content

Commit

Permalink
Feat/issue-90 (#92)
Browse files Browse the repository at this point in the history
* Feat: chatRoom 방 생성

* chore: 패키지 변경

* Feat: chatMember 중간 테이블 생성

* Feat: 방 입장

* Feat: 방 전체 리스트 조회

* Feat: 방 삭제

* Feat: 채팅방 강퇴

* Feat: 채팅 방 강퇴시 responseBody에 강퇴당한 사람 출력

* Feat: 강퇴 당한 사용자 못들어오도록, 인원수 증가 감소

* Feat: 채팅 방 중복 입장 불가, participation 증가, 감소

* Feat: 채팅 방 삭제시 owner 검증

* Feat: 방장 위임

* Feat: exception 처리, valid 처리

* Feat: 방장 위임 할 수 없을 경우 exception 처리
  • Loading branch information
leebuwon authored Feb 14, 2024
1 parent 2035475 commit c42fe87
Show file tree
Hide file tree
Showing 26 changed files with 992 additions and 3 deletions.
7 changes: 4 additions & 3 deletions backend/chatroom-service/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.2'
id 'org.springframework.boot' version '3.2.1'
id 'io.spring.dependency-management' version '1.1.4'
}

Expand Down Expand Up @@ -32,8 +32,9 @@ dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
// runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
// runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.tadak.chatroomservice.domain.chatmember.dto.response;

import com.tadak.chatroomservice.domain.chatmember.entity.ChatMember;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EnterChatMemberResponse {

private Long chatMemberId;
private Long chatRoomId;
private String username;
private Integer participation;

public static EnterChatMemberResponse of(ChatMember chatMember, Integer participation){
return EnterChatMemberResponse.builder()
.chatMemberId(chatMember.getId())
.chatRoomId(chatMember.getChatRoom().getId())
.username(chatMember.getUsername())
.participation(participation)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.tadak.chatroomservice.domain.chatmember.entity;

import com.tadak.chatroomservice.domain.chatroom.entity.ChatRoom;
import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import static com.tadak.chatroomservice.domain.chatmember.entity.ChatMemberType.*;
import static jakarta.persistence.EnumType.STRING;
import static jakarta.persistence.FetchType.LAZY;
import static lombok.AccessLevel.PROTECTED;

@Getter
@NoArgsConstructor(access = PROTECTED)
@Entity
@SuperBuilder
@EntityListeners(AuditingEntityListener.class)
public class ChatMember {

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

@ManyToOne(fetch = LAZY)
private ChatRoom chatRoom;

private String username;

@Builder.Default
@Enumerated(STRING)
private ChatMemberType type = IN_ROOM;

public void updateState() {
this.type = KICKED;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.tadak.chatroomservice.domain.chatmember.entity;

public enum ChatMemberType {
IN_ROOM, KICKED, EXIT
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.tadak.chatroomservice.domain.chatmember.repository;

import com.tadak.chatroomservice.domain.chatmember.entity.ChatMember;
import com.tadak.chatroomservice.domain.chatroom.entity.ChatRoom;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface ChatMemberRepository extends JpaRepository<ChatMember, Long> {
Optional<ChatMember> findByChatRoomAndUsername(ChatRoom chatRoom, String username);

boolean existsByChatRoomAndUsername(ChatRoom chatRoom, String username);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.tadak.chatroomservice.domain.chatmember.service;

import com.tadak.chatroomservice.domain.chatmember.dto.response.EnterChatMemberResponse;
import com.tadak.chatroomservice.domain.chatmember.entity.ChatMember;
import com.tadak.chatroomservice.domain.chatmember.entity.ChatMemberType;
import com.tadak.chatroomservice.domain.chatmember.repository.ChatMemberRepository;
import com.tadak.chatroomservice.domain.chatroom.entity.ChatRoom;
import com.tadak.chatroomservice.domain.chatroom.exception.AlreadyKickedException;
import com.tadak.chatroomservice.domain.chatroom.exception.CannotTransferOwnershipException;
import com.tadak.chatroomservice.domain.chatroom.exception.NotFoundChatMemberException;
import com.tadak.chatroomservice.global.error.ErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Slf4j
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ChatMemberService {

private final ChatMemberRepository chatMemberRepository;

@Transactional
public EnterChatMemberResponse enterMember(ChatRoom chatRoom, String username) {
ChatMember chatMember = ChatMember.builder()
.chatRoom(chatRoom)
.username(username)
.build();

chatMemberRepository.save(chatMember);
// 채팅방 인원 증가
chatRoom.increaseParticipation();

return EnterChatMemberResponse.of(chatMember, chatRoom.getParticipation());
}

public ChatMember findByChatMember(Long chatMemberId) {
return chatMemberRepository.findById(chatMemberId)
.orElseThrow(() -> new NotFoundChatMemberException(ErrorCode.NOT_FOUND_CHAT_MEMBER_ERROR));
}

public boolean validEnterChatMember(ChatRoom chatRoom, String username) {

ChatMember chatMember = chatMemberRepository.findByChatRoomAndUsername(chatRoom, username)
.orElse(null);

if (chatMember == null){
return false;
}

log.info("chatMember type = {}", chatMember.getType());

return chatMember.getType() == ChatMemberType.KICKED;
}

// 존재하면 true, 존재하지 않으면 false
public boolean existsChatRoomAndUsername(ChatRoom chatRoom, String username) {
return chatMemberRepository.existsByChatRoomAndUsername(chatRoom, username);
}

// ChatMember 가지고 오기
public ChatMember getChatMemberByChatRoomAndUsername(ChatRoom chatRoom, String username) {
ChatMember chatMember = chatMemberRepository.findByChatRoomAndUsername(chatRoom, username)
.orElseThrow(() -> new NotFoundChatMemberException(ErrorCode.NOT_FOUND_CHAT_MEMBER_ERROR));

// 방장 위임 할 경우 exception
if (chatMember.getType() == ChatMemberType.KICKED){
throw new CannotTransferOwnershipException(ErrorCode.CANNOT_TRANSFER_OWNER_ERROR);
}

return chatMember;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.tadak.chatroomservice.domain.chatroom.controller;

import com.tadak.chatroomservice.domain.chatmember.dto.response.EnterChatMemberResponse;
import com.tadak.chatroomservice.domain.chatroom.dto.request.ChatRoomRequest;
import com.tadak.chatroomservice.domain.chatroom.dto.response.ChangeOwnerResponse;
import com.tadak.chatroomservice.domain.chatroom.dto.response.ChatRoomResponse;
import com.tadak.chatroomservice.domain.chatroom.dto.response.KickMemberResponse;
import com.tadak.chatroomservice.domain.chatroom.service.ChatRoomService;
import com.tadak.chatroomservice.domain.chatroom.dto.request.CreateChatroomRequest;
import com.tadak.chatroomservice.domain.chatroom.dto.response.CreateChatroomResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/chatroom-service")
@Slf4j
public class ChatRoomController {

private final ChatRoomService chatRoomService;

/**
* 방 생성
*/
@PostMapping("/create")
public ResponseEntity<CreateChatroomResponse> create(@RequestBody CreateChatroomRequest chatroomRequest){
CreateChatroomResponse createChatroomResponse = chatRoomService.create(chatroomRequest);
return ResponseEntity.status(HttpStatus.CREATED).body(createChatroomResponse);
}

/**
* 방 입장
*/
@PostMapping("/room-in/{roomId}")
public ResponseEntity<EnterChatMemberResponse> enter(@PathVariable Long roomId, @RequestBody ChatRoomRequest chatRoomRequest){
EnterChatMemberResponse enter = chatRoomService.enter(roomId, chatRoomRequest);
return ResponseEntity.status(HttpStatus.OK).body(enter);
}

/**
* 방 삭제
*/
@DeleteMapping("/delete/{roomId}")
public ResponseEntity<Void> deleteChatRoom(@PathVariable Long roomId, @RequestBody ChatRoomRequest chatRoomRequest) {
chatRoomService.deleteChatRoom(roomId, chatRoomRequest.getUsername());
return ResponseEntity.status(HttpStatus.OK).build();
}


/**
* 방 전체 리스트 조회
*/
@GetMapping("/rooms")
public ResponseEntity<List<ChatRoomResponse>> getAllChatRoom() {
List<ChatRoomResponse> chatRooms = chatRoomService.findAll();
return ResponseEntity.status(HttpStatus.OK).body(chatRooms);
}

/**
* 강퇴
*/
@PostMapping("/rooms/{roomId}/kicked/{chatMemberId}")
public ResponseEntity<KickMemberResponse> kickedMember(@PathVariable Long roomId, @PathVariable Long chatMemberId,
@RequestBody ChatRoomRequest chatRoomRequest){
KickMemberResponse kickMemberResponse = chatRoomService.kickMember(roomId, chatMemberId, chatRoomRequest.getUsername());
return ResponseEntity.status(HttpStatus.OK).body(kickMemberResponse);
}

/**
* 방장 위임
*/
@PatchMapping("/rooms/{roomId}/change-owner/{username}")
public ResponseEntity<ChangeOwnerResponse> changeOwner(@PathVariable Long roomId, @PathVariable String username,
@RequestBody ChatRoomRequest chatRoomRequest){
ChangeOwnerResponse changeOwnerResponse = chatRoomService.changeOwner(roomId, username, chatRoomRequest.getUsername());
return ResponseEntity.status(HttpStatus.OK).body(changeOwnerResponse);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.tadak.chatroomservice.domain.chatroom.dto.request;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ChatRoomRequest {

private String username;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.tadak.chatroomservice.domain.chatroom.dto.request;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CreateChatroomRequest {

private String roomName;
private String description;
private String owner;
private String category;
private Integer capacity;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.tadak.chatroomservice.domain.chatroom.dto.response;

import com.tadak.chatroomservice.domain.chatroom.entity.ChatRoom;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ChangeOwnerResponse {

private Long chatRoomId;
private String newOwner;

public static ChangeOwnerResponse from(ChatRoom chatRoom){
return ChangeOwnerResponse.builder()
.chatRoomId(chatRoom.getId())
.newOwner(chatRoom.getOwner())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.tadak.chatroomservice.domain.chatroom.dto.response;

import com.tadak.chatroomservice.domain.chatroom.entity.ChatRoom;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ChatRoomResponse {

private Long roomId;
private String roomName;
private String description;
private Integer participation;
private Integer capacity;
private String owner;

public static ChatRoomResponse from(ChatRoom chatRoom) {
return ChatRoomResponse.builder()
.roomId(chatRoom.getId())
.roomName(chatRoom.getRoomName())
.description(chatRoom.getDescription())
.participation(chatRoom.getParticipation())
.capacity(chatRoom.getCapacity())
.owner(chatRoom.getOwner())
.build();
}
}
Loading

0 comments on commit c42fe87

Please sign in to comment.