From 73f7270bdd040965c3ece3dd43ff361a377dfd03 Mon Sep 17 00:00:00 2001 From: F-hiller Date: Tue, 9 Apr 2024 14:13:50 +0900 Subject: [PATCH 01/19] =?UTF-8?q?feat(Channel)=20:=20=EC=B1=84=EB=84=90=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=97=90=20=EA=B4=80=ED=95=9C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=9E=91=EC=84=B1.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ChannelController.java | 35 +++++++++++ .../gdsc/comunity/entity/channel/Channel.java | 6 +- .../repository/channel/ChannelRepository.java | 2 + .../service/channel/ChannelService.java | 14 +++++ .../service/channel/ChannelServiceImpl.java | 41 +++++++++++++ .../channel/ChannelServiceImplTest.java | 58 +++++++++++++++++++ 6 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 src/main/java/gdsc/comunity/controller/ChannelController.java create mode 100644 src/main/java/gdsc/comunity/service/channel/ChannelService.java create mode 100644 src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java create mode 100644 src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java diff --git a/src/main/java/gdsc/comunity/controller/ChannelController.java b/src/main/java/gdsc/comunity/controller/ChannelController.java new file mode 100644 index 0000000..a53aef1 --- /dev/null +++ b/src/main/java/gdsc/comunity/controller/ChannelController.java @@ -0,0 +1,35 @@ +package gdsc.comunity.controller; + +import gdsc.comunity.entity.user.Provider; +import gdsc.comunity.entity.user.User; +import gdsc.comunity.service.channel.ChannelServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api/channel") +@RequiredArgsConstructor +public class ChannelController { + private final ChannelServiceImpl channelServiceImpl; + + @GetMapping("/hello") + public String test() { + return "test"; + } + + @PostMapping + ResponseEntity createChannel(@RequestBody String channelName){ + // TODO : 사용자 로그인 정보를 바탕으로 User Entity를 보유하고 있음을 가정함. + User user = User.builder() + .email("test") + .profileImageUrl("test") + .provider(Provider.GOOGLE) + .providerId("1") + .build(); + + channelServiceImpl.createChannel(user, channelName); + return new ResponseEntity<>("Channel created.", HttpStatus.CREATED); + } +} diff --git a/src/main/java/gdsc/comunity/entity/channel/Channel.java b/src/main/java/gdsc/comunity/entity/channel/Channel.java index 814d2eb..5d23436 100644 --- a/src/main/java/gdsc/comunity/entity/channel/Channel.java +++ b/src/main/java/gdsc/comunity/entity/channel/Channel.java @@ -40,9 +40,11 @@ public class Channel extends BaseTimeEntity { @JoinColumn(name = "manager_id") private User manager; + private String channelName; + @Builder - private Channel(User manager) { + private Channel(User manager, String channelName) { this.manager = manager; + this.channelName = channelName; } - } diff --git a/src/main/java/gdsc/comunity/repository/channel/ChannelRepository.java b/src/main/java/gdsc/comunity/repository/channel/ChannelRepository.java index e28433b..ac450e5 100644 --- a/src/main/java/gdsc/comunity/repository/channel/ChannelRepository.java +++ b/src/main/java/gdsc/comunity/repository/channel/ChannelRepository.java @@ -2,6 +2,8 @@ import gdsc.comunity.entity.channel.Channel; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface ChannelRepository extends JpaRepository { } diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelService.java b/src/main/java/gdsc/comunity/service/channel/ChannelService.java new file mode 100644 index 0000000..20b8de5 --- /dev/null +++ b/src/main/java/gdsc/comunity/service/channel/ChannelService.java @@ -0,0 +1,14 @@ +package gdsc.comunity.service.channel; + +import gdsc.comunity.entity.channel.Channel; +import gdsc.comunity.entity.user.User; + +public interface ChannelService { + Channel createChannel(User user, String channelName); + + void leaveChannel(User user); + + void deleteChannel(User user); + + Channel searchChannel(Long channelId); +} diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java new file mode 100644 index 0000000..04d0e8f --- /dev/null +++ b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java @@ -0,0 +1,41 @@ +package gdsc.comunity.service.channel; + +import gdsc.comunity.entity.channel.Channel; +import gdsc.comunity.entity.user.User; +import gdsc.comunity.repository.channel.ChannelRepository; +import gdsc.comunity.repository.user.UserChannelRepository; +import gdsc.comunity.repository.user.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ChannelServiceImpl implements ChannelService { + private final ChannelRepository channelRepository; + private final UserChannelRepository userChannelRepository; + + @Override + public Channel createChannel(User user, String channelName) { + Channel newChannel = Channel.builder() + .channelName(channelName) + .manager(user) + .build(); + channelRepository.save(newChannel); + return newChannel; + } + + @Override + public void leaveChannel(User user) { + + } + + @Override + public void deleteChannel(User user) { + + } + + @Override + public Channel searchChannel(Long channelId) { + return null; + } +} diff --git a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java new file mode 100644 index 0000000..af00805 --- /dev/null +++ b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java @@ -0,0 +1,58 @@ +package gdsc.comunity.service.channel; + +import gdsc.comunity.entity.channel.Channel; +import gdsc.comunity.entity.user.Provider; +import gdsc.comunity.entity.user.User; +import gdsc.comunity.repository.channel.ChannelRepository; +import gdsc.comunity.repository.user.UserChannelRepository; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.Assertions.*; + +@SpringBootTest +class ChannelServiceImplTest { + @Mock + private ChannelRepository channelRepository; + @Mock + private UserChannelRepository userChannelRepository; + + @InjectMocks + private ChannelServiceImpl channelServiceImpl; + + public User user; + public Long randomNum; + public String randomStr; + + @BeforeEach + void setVar() { + user = User.builder() + .providerId("1") + .email("email") + .profileImageUrl("image url") + .provider(Provider.GOOGLE) + .build(); + + randomNum = (long) (Math.random() * 100); + randomStr = randomNum.toString(); + } + + @Test + void createChannel() { + //Arrange + //already set in @BefroeEach + + //Act + Channel newChannel = channelServiceImpl.createChannel(user, "Channel" + randomStr); + + //Assert + assertThat(newChannel).isNotNull(); + assertThat(newChannel.getChannelName()).isEqualTo("Channel" + randomStr); + } +} \ No newline at end of file From 2b8f9dd6c085e6ce7327a9f8f01f874ee4c811eb Mon Sep 17 00:00:00 2001 From: Choi Jun Ho Date: Mon, 15 Apr 2024 01:08:39 +0900 Subject: [PATCH 02/19] =?UTF-8?q?feat(Channel)=20:=20=EC=B1=84=EB=84=90=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=A1=B0=ED=9A=8C,=20=EC=B1=84=EB=84=90?= =?UTF-8?q?=20=EB=82=98=EA=B0=80=EA=B8=B0,=20=EC=B1=84=EB=84=90=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=ED=95=98=EA=B8=B0=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ChannelController.java | 25 ++- .../comunity/dto/channel/ChannelInfoDto.java | 37 +++++ .../gdsc/comunity/entity/channel/Channel.java | 4 + .../user/UserChannelRepository.java | 12 ++ .../service/channel/ChannelService.java | 9 +- .../service/channel/ChannelServiceImpl.java | 58 ++++++- .../java/gdsc/comunity/util/TestUtil.java | 27 ++++ .../channel/ChannelServiceImplTest.java | 148 ++++++++++++++---- 8 files changed, 267 insertions(+), 53 deletions(-) create mode 100644 src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java create mode 100644 src/main/java/gdsc/comunity/util/TestUtil.java diff --git a/src/main/java/gdsc/comunity/controller/ChannelController.java b/src/main/java/gdsc/comunity/controller/ChannelController.java index a53aef1..911cb16 100644 --- a/src/main/java/gdsc/comunity/controller/ChannelController.java +++ b/src/main/java/gdsc/comunity/controller/ChannelController.java @@ -1,5 +1,6 @@ package gdsc.comunity.controller; +import gdsc.comunity.dto.channel.ChannelInfoDto; import gdsc.comunity.entity.user.Provider; import gdsc.comunity.entity.user.User; import gdsc.comunity.service.channel.ChannelServiceImpl; @@ -14,22 +15,16 @@ public class ChannelController { private final ChannelServiceImpl channelServiceImpl; - @GetMapping("/hello") - public String test() { - return "test"; - } - + // TODO : 사용자 id는 @UserId 어노테이션으로 받아올 예정이다. @PostMapping - ResponseEntity createChannel(@RequestBody String channelName){ - // TODO : 사용자 로그인 정보를 바탕으로 User Entity를 보유하고 있음을 가정함. - User user = User.builder() - .email("test") - .profileImageUrl("test") - .provider(Provider.GOOGLE) - .providerId("1") - .build(); - - channelServiceImpl.createChannel(user, channelName); + ResponseEntity createChannel(@RequestBody String channelName, Long id){ + channelServiceImpl.createChannel(id, channelName); return new ResponseEntity<>("Channel created.", HttpStatus.CREATED); } + + @GetMapping + ResponseEntity searchChannel(@RequestParam Long channelId, Long id){ + ChannelInfoDto channelInfoDto = channelServiceImpl.searchChannel(channelId); + return new ResponseEntity<>(channelInfoDto, HttpStatus.OK); + } } diff --git a/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java b/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java new file mode 100644 index 0000000..11c4bec --- /dev/null +++ b/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java @@ -0,0 +1,37 @@ +package gdsc.comunity.dto.channel; + +import gdsc.comunity.entity.user.User; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@AllArgsConstructor +@Getter +public class ChannelInfoDto { + /** + * { + * "channelName": "채널명", + * "openDate": "2024-04-06", + * "managerNickname": "관리자 닉네임", + * "channelUsers": [ + * { + * "id": 1, + * "nickname": "nick1" + * }, + * { + * "id": 2, + * "nickname": "nick2" + * }, + * { + * "id": 3, + * "nickname": "nick3" + * } + * ] + * } + */ + private String channelName; + private String openDate; + private String managerNickname; + private List channelUsers; +} diff --git a/src/main/java/gdsc/comunity/entity/channel/Channel.java b/src/main/java/gdsc/comunity/entity/channel/Channel.java index 5d23436..241b4b2 100644 --- a/src/main/java/gdsc/comunity/entity/channel/Channel.java +++ b/src/main/java/gdsc/comunity/entity/channel/Channel.java @@ -47,4 +47,8 @@ private Channel(User manager, String channelName) { this.manager = manager; this.channelName = channelName; } + + public void updateManager(User newManager) { + this.manager = newManager; + } } diff --git a/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java b/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java index 1c2eb25..bd25560 100644 --- a/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java +++ b/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java @@ -1,8 +1,20 @@ package gdsc.comunity.repository.user; +import gdsc.comunity.entity.user.User; import gdsc.comunity.entity.user.UserChannel; +import org.springframework.boot.autoconfigure.flyway.FlywayProperties; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; +import java.util.Optional; + public interface UserChannelRepository extends JpaRepository { + Optional findSecondByChannelIdOrderByCreatedDateDesc(Long channelId); + + Optional findByUserIdAndChannelId(Long id, Long channelId); + + void deleteAllByChannelId(Long channelId); + + List findAllByChannelId(Long channelId); } diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelService.java b/src/main/java/gdsc/comunity/service/channel/ChannelService.java index 20b8de5..d69a5d8 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelService.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelService.java @@ -1,14 +1,15 @@ package gdsc.comunity.service.channel; +import gdsc.comunity.dto.channel.ChannelInfoDto; import gdsc.comunity.entity.channel.Channel; import gdsc.comunity.entity.user.User; public interface ChannelService { - Channel createChannel(User user, String channelName); + Channel createChannel(Long userId, String channelName); - void leaveChannel(User user); + void leaveChannel(Long userId, Long channelId); - void deleteChannel(User user); + void deleteChannel(Long userId, Long channelId); - Channel searchChannel(Long channelId); + ChannelInfoDto searchChannel(Long channelId); } diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java index 04d0e8f..419d051 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java @@ -1,21 +1,31 @@ package gdsc.comunity.service.channel; +import gdsc.comunity.dto.channel.ChannelInfoDto; import gdsc.comunity.entity.channel.Channel; import gdsc.comunity.entity.user.User; +import gdsc.comunity.entity.user.UserChannel; import gdsc.comunity.repository.channel.ChannelRepository; import gdsc.comunity.repository.user.UserChannelRepository; import gdsc.comunity.repository.user.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; @Service @RequiredArgsConstructor +// TODO : Exception handling public class ChannelServiceImpl implements ChannelService { private final ChannelRepository channelRepository; private final UserChannelRepository userChannelRepository; + private final UserRepository userRepository; @Override - public Channel createChannel(User user, String channelName) { + public Channel createChannel(Long userId, String channelName) { + User user = userRepository.findById(userId).orElseThrow(); Channel newChannel = Channel.builder() .channelName(channelName) .manager(user) @@ -25,17 +35,55 @@ public Channel createChannel(User user, String channelName) { } @Override - public void leaveChannel(User user) { + @Transactional + public void leaveChannel(Long userId, Long channelId) { + User user = userRepository.findById(userId).orElseThrow(); + + Channel channel = channelRepository.findById(channelId).orElseThrow(); + if (!(Objects.equals(channel.getManager().getId(), user.getId()))) { + UserChannel userChannel = userChannelRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow(); + userChannelRepository.delete(userChannel); + return; + } + // TODO : 채널 매니저가 나갈 경우 새로운 매니저 지정 - 만약, 더 이상 새로운 매니저를 지정할 수 없다면 deleteChannel을 물어보도록?? + Optional newOptionalManager = userChannelRepository.findSecondByChannelIdOrderByCreatedDateDesc(channelId); + if (newOptionalManager.isEmpty()) { + throw new IllegalArgumentException("There is no manager in this channel."); + } + User newManager = newOptionalManager.get().getUser(); + channel.updateManager(newManager); + channelRepository.save(channel); + UserChannel userChannel = userChannelRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow(); + userChannelRepository.delete(userChannel); } @Override - public void deleteChannel(User user) { + @Transactional + public void deleteChannel(Long userId, Long channelId) { + User user = userRepository.findById(userId).orElseThrow(); + // 채널 매니저만 채널 삭제 가능 + Channel channel = channelRepository.findById(channelId).orElseThrow(); + if (!(Objects.equals(channel.getManager().getId(), user.getId()))) { + throw new IllegalArgumentException("Only manager can delete channel."); + } + // 연관된 UserChannel 및 Channel 삭제 + userChannelRepository.deleteAllByChannelId(channelId); + channelRepository.delete(channel); } @Override - public Channel searchChannel(Long channelId) { - return null; + public ChannelInfoDto searchChannel(Long channelId) { + Channel channel = channelRepository.findById(channelId).orElseThrow(); + List channelUsers = userChannelRepository.findAllByChannelId(channelId).stream().map(UserChannel::getUser).toList(); + UserChannel manager = userChannelRepository.findByUserIdAndChannelId(channel.getManager().getId(), channelId).orElseThrow(); + + return new ChannelInfoDto( + channel.getChannelName(), + channel.getCreatedDate().toString(), + manager.getNickname(), + channelUsers + ); } } diff --git a/src/main/java/gdsc/comunity/util/TestUtil.java b/src/main/java/gdsc/comunity/util/TestUtil.java new file mode 100644 index 0000000..5701b47 --- /dev/null +++ b/src/main/java/gdsc/comunity/util/TestUtil.java @@ -0,0 +1,27 @@ +package gdsc.comunity.util; + +import java.lang.reflect.Field; +import java.time.LocalDateTime; + +public class TestUtil { + public static void setField(Object object, String fieldName, Object value) { + Field field; + try { + field = object.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + field.set(object, value); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + public static Object getTestDate() { + return LocalDateTime.now(); + } + + public static void setDate(Object object) { + // set createdDate, modifiedDate + setField(object, "createdDate", getTestDate()); + setField(object, "modifiedDate", getTestDate()); + } +} diff --git a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java index af00805..3bf0203 100644 --- a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java +++ b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java @@ -1,58 +1,148 @@ package gdsc.comunity.service.channel; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; + +import gdsc.comunity.dto.channel.ChannelInfoDto; import gdsc.comunity.entity.channel.Channel; import gdsc.comunity.entity.user.Provider; import gdsc.comunity.entity.user.User; +import gdsc.comunity.entity.user.UserChannel; import gdsc.comunity.repository.channel.ChannelRepository; import gdsc.comunity.repository.user.UserChannelRepository; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; +import gdsc.comunity.repository.user.UserRepository; +import gdsc.comunity.util.TestUtil; import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +//import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.annotation.Transactional; -import static org.junit.jupiter.api.Assertions.*; -import static org.assertj.core.api.Assertions.*; +import java.util.Optional; +//TODO : Test code 작성 +@ExtendWith(SpringExtension.class) @SpringBootTest -class ChannelServiceImplTest { - @Mock +//@ActiveProfiles("test") // Ensure you use the 'test' profile to avoid using the production database +@Transactional // Ensure that each test is independently rolled back after execution +public class ChannelServiceImplTest { + @Autowired + private ChannelServiceImpl channelService; + @Autowired + private UserRepository userRepository; + @Autowired private ChannelRepository channelRepository; - @Mock + @Autowired private UserChannelRepository userChannelRepository; - @InjectMocks - private ChannelServiceImpl channelServiceImpl; + @Test + void createChannel_Success() { + // Arrange + User user = User.builder() + .email("email") + .profileImageUrl("image") + .provider(Provider.GOOGLE) + .providerId("1") + .build(); + user = userRepository.save(user); + + // Act + Channel channel = channelService.createChannel(user.getId(), "New Channel"); - public User user; - public Long randomNum; - public String randomStr; + // Assert + assertNotNull(channel.getId()); + assertEquals("New Channel", channel.getChannelName()); + assertEquals(user.getId(), channel.getManager().getId()); - @BeforeEach - void setVar() { - user = User.builder() + Optional userChannel = userChannelRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); + assertTrue(userChannel.isPresent()); + } + + @Test + void leaveChannel_Success() { + // Arrange + User user = User.builder() + .email("email") + .profileImageUrl("image") + .provider(Provider.GOOGLE) .providerId("1") + .build(); + user = userRepository.save(user); + + User manager = User.builder() + .email("manager") + .profileImageUrl("manager") + .provider(Provider.GOOGLE) + .providerId("2") + .build(); + manager = userRepository.save(manager); + + Channel channel = channelService.createChannel(manager.getId(), "New Channel"); + // TODO : user join to channel + + // Act + channelService.leaveChannel(manager.getId(), channel.getId()); + + // Assert + Optional userChannel = userChannelRepository.findByUserIdAndChannelId(manager.getId(), channel.getId()); + assertTrue(userChannel.isEmpty()); + + Optional channelOptional = channelRepository.findById(channel.getId()); + assertTrue(channelOptional.isPresent()); + assertEquals(user.getId(), channelOptional.get().getManager().getId()); + } + + @Test + void deleteChannel_Failure_NotManager() { + // Arrange + User user = User.builder() .email("email") - .profileImageUrl("image url") + .profileImageUrl("image") .provider(Provider.GOOGLE) + .providerId("1") + .build(); + user = userRepository.save(user); + + User manager = User.builder() + .email("manager") + .profileImageUrl("manager") + .provider(Provider.GOOGLE) + .providerId("2") .build(); + manager = userRepository.save(manager); - randomNum = (long) (Math.random() * 100); - randomStr = randomNum.toString(); + Channel channel = channelService.createChannel(manager.getId(), "New Channel"); + + Long userId = user.getId(); + Long channelId = channel.getId(); + + // Act && Assert + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + channelService.deleteChannel(userId, channelId); + }); + assertEquals("Only manager can delete channel.", exception.getMessage()); } @Test - void createChannel() { - //Arrange - //already set in @BefroeEach + void searchChannel_Success() { + // Arrange + User manager = User.builder() + .email("manager") + .profileImageUrl("manager") + .provider(Provider.GOOGLE) + .providerId("2") + .build(); + manager = userRepository.save(manager); + Channel channel = channelService.createChannel(manager.getId(), "New Channel"); - //Act - Channel newChannel = channelServiceImpl.createChannel(user, "Channel" + randomStr); + // Act + ChannelInfoDto result = channelService.searchChannel(channel.getId()); - //Assert - assertThat(newChannel).isNotNull(); - assertThat(newChannel.getChannelName()).isEqualTo("Channel" + randomStr); + // Assert + assertThat(result.getChannelName()).isEqualTo("New Channel"); } } \ No newline at end of file From 14d5a9682af802374be4276b5ab366c86054f6f3 Mon Sep 17 00:00:00 2001 From: Choi Jun Ho Date: Thu, 25 Apr 2024 21:46:06 +0900 Subject: [PATCH 03/19] =?UTF-8?q?feat(Entity)=20:=20ChannelJoinRequest=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=B6=94=EA=B0=80.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/channel/ChannelJoinRequest.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/main/java/gdsc/comunity/entity/channel/ChannelJoinRequest.java diff --git a/src/main/java/gdsc/comunity/entity/channel/ChannelJoinRequest.java b/src/main/java/gdsc/comunity/entity/channel/ChannelJoinRequest.java new file mode 100644 index 0000000..a0dff24 --- /dev/null +++ b/src/main/java/gdsc/comunity/entity/channel/ChannelJoinRequest.java @@ -0,0 +1,37 @@ +package gdsc.comunity.entity.channel; + +import gdsc.comunity.entity.common.BaseTimeEntity; +import gdsc.comunity.entity.user.User; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class ChannelJoinRequest extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "channel_id") + private Channel channel; + + @Column(nullable = false) + String nickname; + + @Builder + private ChannelJoinRequest(User user, Channel channel, String nickname){ + this.user = user; + this.channel = channel; + this.nickname = nickname; + } + +} From 48283174452ae7b0232e467b5bb6a5355c997f15 Mon Sep 17 00:00:00 2001 From: Choi Jun Ho Date: Thu, 25 Apr 2024 23:53:24 +0900 Subject: [PATCH 04/19] =?UTF-8?q?feat(Channel)=20:=20ChannelJoinRequest?= =?UTF-8?q?=EB=A5=BC=20=ED=99=9C=EC=9A=A9=ED=95=98=EC=97=AC=20=EC=B1=84?= =?UTF-8?q?=EB=84=90=20=EC=B0=B8=EC=97=AC=20=EC=9A=94=EC=B2=AD=20=EC=A0=84?= =?UTF-8?q?=EC=86=A1=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ChannelController.java | 46 +++++++++++++- .../dto/channel/ApproveJoinChannelDto.java | 14 +++++ .../comunity/dto/channel/ChannelInfoDto.java | 21 ------- .../channel/ChannelJoinRequestRepository.java | 12 ++++ .../service/channel/ChannelService.java | 10 +++ .../service/channel/ChannelServiceImpl.java | 61 +++++++++++++++---- 6 files changed, 129 insertions(+), 35 deletions(-) create mode 100644 src/main/java/gdsc/comunity/dto/channel/ApproveJoinChannelDto.java create mode 100644 src/main/java/gdsc/comunity/repository/channel/ChannelJoinRequestRepository.java diff --git a/src/main/java/gdsc/comunity/controller/ChannelController.java b/src/main/java/gdsc/comunity/controller/ChannelController.java index 911cb16..f6707c8 100644 --- a/src/main/java/gdsc/comunity/controller/ChannelController.java +++ b/src/main/java/gdsc/comunity/controller/ChannelController.java @@ -1,5 +1,6 @@ package gdsc.comunity.controller; +import gdsc.comunity.dto.channel.ApproveJoinChannelDto; import gdsc.comunity.dto.channel.ChannelInfoDto; import gdsc.comunity.entity.user.Provider; import gdsc.comunity.entity.user.User; @@ -9,6 +10,8 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; + @RestController @RequestMapping("/api/channel") @RequiredArgsConstructor @@ -22,9 +25,48 @@ ResponseEntity createChannel(@RequestBody String channelName, Long id){ return new ResponseEntity<>("Channel created.", HttpStatus.CREATED); } - @GetMapping - ResponseEntity searchChannel(@RequestParam Long channelId, Long id){ + @GetMapping("/{channelId}") + ResponseEntity searchChannel(@PathVariable Long channelId, Long id){ ChannelInfoDto channelInfoDto = channelServiceImpl.searchChannel(channelId); return new ResponseEntity<>(channelInfoDto, HttpStatus.OK); } + + @GetMapping("/join/{channelId}") + ResponseEntity searchJoinRequest(@PathVariable Long channelId, Long id){ + // TODO : 반환 형식이 아직 정해지지 않았다. 회의를 통해 문서화하고 코드에 반영 필요. + List userList = channelServiceImpl.searchJoinRequest(id, channelId); + return new ResponseEntity<>(userList, HttpStatus.OK); + } + + @PostMapping("/join/{channelId}") + ResponseEntity sendJoinRequest(@RequestBody String nickname, @PathVariable Long channelId, Long id){ + channelServiceImpl.sendJoinRequest(nickname, id, channelId); + return new ResponseEntity<>("Channel joined.", HttpStatus.OK); + } + + @PutMapping("/join/{channelId}") + ResponseEntity leaveChannel(@PathVariable Long channelId, Long id){ + channelServiceImpl.leaveChannel(id, channelId); + return new ResponseEntity<>("Channel left.", HttpStatus.OK); + } + + @DeleteMapping("/join/{channelId}") + ResponseEntity deleteChannel(@PathVariable Long channelId, Long id){ + channelServiceImpl.deleteChannel(id, channelId); + return new ResponseEntity<>("Channel deleted.", HttpStatus.OK); + } + + @PutMapping("/approve") + ResponseEntity approveJoinChannel(@RequestBody ApproveJoinChannelDto approveJoinChannelDto, Long userId){ + Long targetUserId = approveJoinChannelDto.getUserId(); + Long channelId = approveJoinChannelDto.getChannelId(); + channelServiceImpl.approveJoinChannel(userId, targetUserId, channelId); + return new ResponseEntity<>("Channel joined.", HttpStatus.OK); + } + + @PutMapping("/nickname") + ResponseEntity changeNickname(@RequestBody String nickname, Long id){ + channelServiceImpl.changeNickname(id, nickname); + return new ResponseEntity<>("Nickname changed.", HttpStatus.OK); + } } diff --git a/src/main/java/gdsc/comunity/dto/channel/ApproveJoinChannelDto.java b/src/main/java/gdsc/comunity/dto/channel/ApproveJoinChannelDto.java new file mode 100644 index 0000000..e3cdeff --- /dev/null +++ b/src/main/java/gdsc/comunity/dto/channel/ApproveJoinChannelDto.java @@ -0,0 +1,14 @@ +package gdsc.comunity.dto.channel; + +import gdsc.comunity.entity.user.User; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@AllArgsConstructor +@Getter +public class ApproveJoinChannelDto { + private Long userId; + private Long channelId; +} diff --git a/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java b/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java index 11c4bec..c5f84d9 100644 --- a/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java +++ b/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java @@ -9,27 +9,6 @@ @AllArgsConstructor @Getter public class ChannelInfoDto { - /** - * { - * "channelName": "채널명", - * "openDate": "2024-04-06", - * "managerNickname": "관리자 닉네임", - * "channelUsers": [ - * { - * "id": 1, - * "nickname": "nick1" - * }, - * { - * "id": 2, - * "nickname": "nick2" - * }, - * { - * "id": 3, - * "nickname": "nick3" - * } - * ] - * } - */ private String channelName; private String openDate; private String managerNickname; diff --git a/src/main/java/gdsc/comunity/repository/channel/ChannelJoinRequestRepository.java b/src/main/java/gdsc/comunity/repository/channel/ChannelJoinRequestRepository.java new file mode 100644 index 0000000..24ba4e3 --- /dev/null +++ b/src/main/java/gdsc/comunity/repository/channel/ChannelJoinRequestRepository.java @@ -0,0 +1,12 @@ +package gdsc.comunity.repository.channel; + +import gdsc.comunity.entity.channel.ChannelJoinRequest; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface ChannelJoinRequestRepository extends JpaRepository { + Optional findByUserIdAndChannelId(Long targetUserId, Long userId); +} diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelService.java b/src/main/java/gdsc/comunity/service/channel/ChannelService.java index d69a5d8..016a3ba 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelService.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelService.java @@ -4,6 +4,8 @@ import gdsc.comunity.entity.channel.Channel; import gdsc.comunity.entity.user.User; +import java.util.List; + public interface ChannelService { Channel createChannel(Long userId, String channelName); @@ -12,4 +14,12 @@ public interface ChannelService { void deleteChannel(Long userId, Long channelId); ChannelInfoDto searchChannel(Long channelId); + + void approveJoinChannel(Long id, Long userId, Long channelId); + + void sendJoinRequest(String nickname, Long id, Long channelId); + + List searchJoinRequest(Long id, Long channelId); + + void changeNickname(Long id, String nickname); } diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java index 419d051..1e58cc3 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java @@ -2,8 +2,10 @@ import gdsc.comunity.dto.channel.ChannelInfoDto; import gdsc.comunity.entity.channel.Channel; +import gdsc.comunity.entity.channel.ChannelJoinRequest; import gdsc.comunity.entity.user.User; import gdsc.comunity.entity.user.UserChannel; +import gdsc.comunity.repository.channel.ChannelJoinRequestRepository; import gdsc.comunity.repository.channel.ChannelRepository; import gdsc.comunity.repository.user.UserChannelRepository; import gdsc.comunity.repository.user.UserRepository; @@ -22,6 +24,7 @@ public class ChannelServiceImpl implements ChannelService { private final ChannelRepository channelRepository; private final UserChannelRepository userChannelRepository; private final UserRepository userRepository; + private final ChannelJoinRequestRepository channelJoinRequestRepository; @Override public Channel createChannel(Long userId, String channelName) { @@ -38,24 +41,24 @@ public Channel createChannel(Long userId, String channelName) { @Transactional public void leaveChannel(Long userId, Long channelId) { User user = userRepository.findById(userId).orElseThrow(); - Channel channel = channelRepository.findById(channelId).orElseThrow(); if (!(Objects.equals(channel.getManager().getId(), user.getId()))) { - UserChannel userChannel = userChannelRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow(); - userChannelRepository.delete(userChannel); + userChannelRepository.findByUserIdAndChannelId(user.getId(), channelId).ifPresentOrElse( + userChannelRepository::delete, + () -> { + throw new IllegalArgumentException("You are not in this channel."); + } + ); return; } - // TODO : 채널 매니저가 나갈 경우 새로운 매니저 지정 - 만약, 더 이상 새로운 매니저를 지정할 수 없다면 deleteChannel을 물어보도록?? - Optional newOptionalManager = userChannelRepository.findSecondByChannelIdOrderByCreatedDateDesc(channelId); - if (newOptionalManager.isEmpty()) { - throw new IllegalArgumentException("There is no manager in this channel."); - } - User newManager = newOptionalManager.get().getUser(); - channel.updateManager(newManager); + + UserChannel newManagerUserChannel = userChannelRepository.findSecondByChannelIdOrderByCreatedDateDesc(channelId) + .orElseThrow(() -> new IllegalArgumentException("There is no manager in this channel.")); + channel.updateManager(newManagerUserChannel.getUser()); channelRepository.save(channel); - UserChannel userChannel = userChannelRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow(); - userChannelRepository.delete(userChannel); + UserChannel deleteUserChannel = userChannelRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow(); + userChannelRepository.delete(deleteUserChannel); } @Override @@ -86,4 +89,38 @@ public ChannelInfoDto searchChannel(Long channelId) { channelUsers ); } + + @Override + public void sendJoinRequest(String nickname, Long userId, Long channelId) { + userChannelRepository.findAllByChannelId(channelId).stream() + .filter(userChannel -> userChannel.getNickname().equals(nickname)) + .findAny() + .ifPresent(userChannel -> { + throw new IllegalArgumentException("Nickname is already exist in this channel."); + }); + + User user = userRepository.findById(userId).orElseThrow(); + Channel channel = channelRepository.findById(channelId).orElseThrow(); + + channelJoinRequestRepository.save(ChannelJoinRequest + .builder() + .channel(channel) + .user(user) + .nickname(nickname) + .build()); + } + + @Override + public void approveJoinChannel(Long userId, Long targetUserId, Long channelId){ + } + + @Override + public List searchJoinRequest(Long userId, Long channelId) { + return null; + } + + @Override + public void changeNickname(Long userId, String nickname){ + + } } From bfeb3ab0459bba92a95e02eb07e0095508fc82cc Mon Sep 17 00:00:00 2001 From: fhiller Date: Fri, 26 Apr 2024 11:30:08 +0900 Subject: [PATCH 05/19] =?UTF-8?q?feat(Channel)=20:=20=EA=B0=80=EC=9E=85=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EC=8A=B9=EC=9D=B8,=20=EA=B0=80=EC=9E=85?= =?UTF-8?q?=20=EC=9A=94=EC=B2=AD=20=EC=A1=B0=ED=9A=8C,=20=EB=8B=89?= =?UTF-8?q?=EB=84=A4=EC=9E=84=20=EB=B3=80=EA=B2=BD=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ChannelController.java | 12 +++-- .../dto/channel/ChannelNicknameDto.java | 11 ++++ .../comunity/entity/user/UserChannel.java | 4 ++ .../channel/ChannelJoinRequestRepository.java | 3 ++ .../user/UserChannelRepository.java | 4 ++ .../service/channel/ChannelService.java | 11 ++-- .../service/channel/ChannelServiceImpl.java | 54 +++++++++++++++---- 7 files changed, 81 insertions(+), 18 deletions(-) create mode 100644 src/main/java/gdsc/comunity/dto/channel/ChannelNicknameDto.java diff --git a/src/main/java/gdsc/comunity/controller/ChannelController.java b/src/main/java/gdsc/comunity/controller/ChannelController.java index f6707c8..4c8e94b 100644 --- a/src/main/java/gdsc/comunity/controller/ChannelController.java +++ b/src/main/java/gdsc/comunity/controller/ChannelController.java @@ -2,6 +2,8 @@ import gdsc.comunity.dto.channel.ApproveJoinChannelDto; import gdsc.comunity.dto.channel.ChannelInfoDto; +import gdsc.comunity.dto.channel.ChannelNicknameDto; +import gdsc.comunity.entity.channel.ChannelJoinRequest; import gdsc.comunity.entity.user.Provider; import gdsc.comunity.entity.user.User; import gdsc.comunity.service.channel.ChannelServiceImpl; @@ -32,9 +34,9 @@ ResponseEntity searchChannel(@PathVariable Long channelId, Long } @GetMapping("/join/{channelId}") - ResponseEntity searchJoinRequest(@PathVariable Long channelId, Long id){ + ResponseEntity> searchJoinRequest(@PathVariable Long channelId, Long id){ // TODO : 반환 형식이 아직 정해지지 않았다. 회의를 통해 문서화하고 코드에 반영 필요. - List userList = channelServiceImpl.searchJoinRequest(id, channelId); + List userList = channelServiceImpl.searchJoinRequest(id, channelId); return new ResponseEntity<>(userList, HttpStatus.OK); } @@ -65,8 +67,10 @@ ResponseEntity approveJoinChannel(@RequestBody ApproveJoinChannelDto app } @PutMapping("/nickname") - ResponseEntity changeNickname(@RequestBody String nickname, Long id){ - channelServiceImpl.changeNickname(id, nickname); + ResponseEntity changeNickname(@RequestBody ChannelNicknameDto channelNicknameDto, Long id){ + String nickname = channelNicknameDto.getNickname(); + Long channelId = channelNicknameDto.getChannelId(); + channelServiceImpl.changeNickname(id, channelId, nickname); return new ResponseEntity<>("Nickname changed.", HttpStatus.OK); } } diff --git a/src/main/java/gdsc/comunity/dto/channel/ChannelNicknameDto.java b/src/main/java/gdsc/comunity/dto/channel/ChannelNicknameDto.java new file mode 100644 index 0000000..c2758e7 --- /dev/null +++ b/src/main/java/gdsc/comunity/dto/channel/ChannelNicknameDto.java @@ -0,0 +1,11 @@ +package gdsc.comunity.dto.channel; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class ChannelNicknameDto { + private String nickname; + private Long channelId; +} diff --git a/src/main/java/gdsc/comunity/entity/user/UserChannel.java b/src/main/java/gdsc/comunity/entity/user/UserChannel.java index d00b556..8539d66 100644 --- a/src/main/java/gdsc/comunity/entity/user/UserChannel.java +++ b/src/main/java/gdsc/comunity/entity/user/UserChannel.java @@ -40,6 +40,10 @@ private UserChannel(String nickname, User user, Channel channel) { this.user = user; this.channel = channel; } + + public void updateNickname(String nickname) { + this.nickname = nickname; + } } diff --git a/src/main/java/gdsc/comunity/repository/channel/ChannelJoinRequestRepository.java b/src/main/java/gdsc/comunity/repository/channel/ChannelJoinRequestRepository.java index 24ba4e3..dfa2f06 100644 --- a/src/main/java/gdsc/comunity/repository/channel/ChannelJoinRequestRepository.java +++ b/src/main/java/gdsc/comunity/repository/channel/ChannelJoinRequestRepository.java @@ -4,9 +4,12 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; import java.util.Optional; @Repository public interface ChannelJoinRequestRepository extends JpaRepository { Optional findByUserIdAndChannelId(Long targetUserId, Long userId); + + List findAllByChannelId(Long channelId); } diff --git a/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java b/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java index bd25560..cc961b3 100644 --- a/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java +++ b/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java @@ -17,4 +17,8 @@ public interface UserChannelRepository extends JpaRepository void deleteAllByChannelId(Long channelId); List findAllByChannelId(Long channelId); + + Optional findByUserIdAndNickname(Long userId, String nickname); + + Optional findByUserId(Long userId); } diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelService.java b/src/main/java/gdsc/comunity/service/channel/ChannelService.java index 016a3ba..39d4c1d 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelService.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelService.java @@ -2,6 +2,7 @@ import gdsc.comunity.dto.channel.ChannelInfoDto; import gdsc.comunity.entity.channel.Channel; +import gdsc.comunity.entity.channel.ChannelJoinRequest; import gdsc.comunity.entity.user.User; import java.util.List; @@ -15,11 +16,13 @@ public interface ChannelService { ChannelInfoDto searchChannel(Long channelId); - void approveJoinChannel(Long id, Long userId, Long channelId); + void approveJoinChannel(Long userId, Long targetUserId, Long channelId); - void sendJoinRequest(String nickname, Long id, Long channelId); + void sendJoinRequest(String nickname, Long userId, Long channelId); - List searchJoinRequest(Long id, Long channelId); + List searchJoinRequest(Long userId, Long channelId); - void changeNickname(Long id, String nickname); + void changeNickname(Long userId, Long channelId, String nickname); + + void doubleCheckNicknameThrowException(Long channelId, String nickname); } diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java index 1e58cc3..00cc942 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java @@ -15,7 +15,6 @@ import java.util.List; import java.util.Objects; -import java.util.Optional; @Service @RequiredArgsConstructor @@ -42,6 +41,7 @@ public Channel createChannel(Long userId, String channelName) { public void leaveChannel(Long userId, Long channelId) { User user = userRepository.findById(userId).orElseThrow(); Channel channel = channelRepository.findById(channelId).orElseThrow(); + // 대상이 매니저가 아닌 경우, UserChannel 삭제 if (!(Objects.equals(channel.getManager().getId(), user.getId()))) { userChannelRepository.findByUserIdAndChannelId(user.getId(), channelId).ifPresentOrElse( userChannelRepository::delete, @@ -52,11 +52,13 @@ public void leaveChannel(Long userId, Long channelId) { return; } + // 대상이 매니저인 경우, 채널 매니저 변경 UserChannel newManagerUserChannel = userChannelRepository.findSecondByChannelIdOrderByCreatedDateDesc(channelId) .orElseThrow(() -> new IllegalArgumentException("There is no manager in this channel.")); channel.updateManager(newManagerUserChannel.getUser()); channelRepository.save(channel); + // 이후 대상의 UserChannel 삭제 UserChannel deleteUserChannel = userChannelRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow(); userChannelRepository.delete(deleteUserChannel); } @@ -71,6 +73,7 @@ public void deleteChannel(Long userId, Long channelId) { if (!(Objects.equals(channel.getManager().getId(), user.getId()))) { throw new IllegalArgumentException("Only manager can delete channel."); } + // 연관된 UserChannel 및 Channel 삭제 userChannelRepository.deleteAllByChannelId(channelId); channelRepository.delete(channel); @@ -82,6 +85,7 @@ public ChannelInfoDto searchChannel(Long channelId) { List channelUsers = userChannelRepository.findAllByChannelId(channelId).stream().map(UserChannel::getUser).toList(); UserChannel manager = userChannelRepository.findByUserIdAndChannelId(channel.getManager().getId(), channelId).orElseThrow(); + // 요청한 채널의 정보(채널 이름, 생성일, 매니저 닉네임, 채널 유저 리스트) 반환 return new ChannelInfoDto( channel.getChannelName(), channel.getCreatedDate().toString(), @@ -92,16 +96,12 @@ public ChannelInfoDto searchChannel(Long channelId) { @Override public void sendJoinRequest(String nickname, Long userId, Long channelId) { - userChannelRepository.findAllByChannelId(channelId).stream() - .filter(userChannel -> userChannel.getNickname().equals(nickname)) - .findAny() - .ifPresent(userChannel -> { - throw new IllegalArgumentException("Nickname is already exist in this channel."); - }); + doubleCheckNicknameThrowException(channelId, nickname); User user = userRepository.findById(userId).orElseThrow(); Channel channel = channelRepository.findById(channelId).orElseThrow(); + // 사용자에 대한 채널 가입 요청 저장 channelJoinRequestRepository.save(ChannelJoinRequest .builder() .channel(channel) @@ -111,16 +111,50 @@ public void sendJoinRequest(String nickname, Long userId, Long channelId) { } @Override + @Transactional public void approveJoinChannel(Long userId, Long targetUserId, Long channelId){ + // 채널 가입 요청을 승인하고 UserChannel에 저장. 이후 ChannelJoinRequest 삭제 + ChannelJoinRequest channelJoinRequest = channelJoinRequestRepository.findByUserIdAndChannelId(targetUserId, channelId).orElseThrow(); + User user = userRepository.findById(userId).orElseThrow(); + Channel channel = channelRepository.findById(channelId).orElseThrow(); + + userChannelRepository.save(UserChannel.builder() + .channel(channel) + .user(channelJoinRequest.getUser()) + .nickname(channelJoinRequest.getNickname()) + .build()); + channelJoinRequestRepository.delete(channelJoinRequest); } @Override - public List searchJoinRequest(Long userId, Long channelId) { - return null; + public List searchJoinRequest(Long userId, Long channelId) { + // 채널의 매니저가 이나라면 예외 발생 + Channel channel = channelRepository.findById(channelId). + orElseThrow(() -> new IllegalArgumentException("Channel does not exist.")); + if (!Objects.equals(channel.getManager().getId(), userId)) { + throw new IllegalArgumentException("Only manager can search join request."); + } + return channelJoinRequestRepository.findAllByChannelId(channelId); } @Override - public void changeNickname(Long userId, String nickname){ + public void changeNickname(Long userId, Long channelId, String nickname){ + // 닉네임 중복 확인 후 변경. + doubleCheckNicknameThrowException(channelId, nickname); + + UserChannel userChannel = userChannelRepository.findByUserId(userId).orElseThrow(); + userChannel.updateNickname(nickname); + userChannelRepository.save(userChannel); + } + @Override + public void doubleCheckNicknameThrowException(Long channelId, String nickname){ + // 닉네임 중복 시 throw Exception + userChannelRepository.findAllByChannelId(channelId).stream() + .filter(userChannel -> userChannel.getNickname().equals(nickname)) + .findAny() + .ifPresent(userChannel -> { + throw new IllegalArgumentException("Nickname is already exist in this channel."); + }); } } From 4c429eca129bdd6eab5aa54b298fe740f3927ac2 Mon Sep 17 00:00:00 2001 From: fhiller Date: Fri, 26 Apr 2024 15:26:08 +0900 Subject: [PATCH 06/19] =?UTF-8?q?test(Channel)=20:=20Channel=20=ED=86=B5?= =?UTF-8?q?=ED=95=A9=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 + .../controller/ChannelController.java | 7 +- .../dto/channel/ChannelCreateDto.java | 11 + .../comunity/entity/user/UserChannel.java | 5 +- .../user/UserChannelRepository.java | 10 +- .../service/channel/ChannelService.java | 2 +- .../service/channel/ChannelServiceImpl.java | 24 +- .../java/gdsc/comunity/util/TestUtil.java | 27 --- .../channel/ChannelServiceImplTest.java | 227 +++++++++++++++++- 9 files changed, 258 insertions(+), 59 deletions(-) create mode 100644 src/main/java/gdsc/comunity/dto/channel/ChannelCreateDto.java delete mode 100644 src/main/java/gdsc/comunity/util/TestUtil.java diff --git a/build.gradle b/build.gradle index fc29fee..682fbcb 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,11 @@ dependencies { compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' + + // test testImplementation 'org.springframework.boot:spring-boot-starter-test' + testAnnotationProcessor('org.projectlombok:lombok') + testImplementation('org.projectlombok:lombok') // Swagger implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' diff --git a/src/main/java/gdsc/comunity/controller/ChannelController.java b/src/main/java/gdsc/comunity/controller/ChannelController.java index 4c8e94b..1aa0b61 100644 --- a/src/main/java/gdsc/comunity/controller/ChannelController.java +++ b/src/main/java/gdsc/comunity/controller/ChannelController.java @@ -1,6 +1,7 @@ package gdsc.comunity.controller; import gdsc.comunity.dto.channel.ApproveJoinChannelDto; +import gdsc.comunity.dto.channel.ChannelCreateDto; import gdsc.comunity.dto.channel.ChannelInfoDto; import gdsc.comunity.dto.channel.ChannelNicknameDto; import gdsc.comunity.entity.channel.ChannelJoinRequest; @@ -22,8 +23,10 @@ public class ChannelController { // TODO : 사용자 id는 @UserId 어노테이션으로 받아올 예정이다. @PostMapping - ResponseEntity createChannel(@RequestBody String channelName, Long id){ - channelServiceImpl.createChannel(id, channelName); + ResponseEntity createChannel(@RequestBody ChannelCreateDto channelCreateDto, Long id){ + String channelName = channelCreateDto.getChannelName(); + String nickname = channelCreateDto.getNickname(); + channelServiceImpl.createChannel(id, channelName, nickname); return new ResponseEntity<>("Channel created.", HttpStatus.CREATED); } diff --git a/src/main/java/gdsc/comunity/dto/channel/ChannelCreateDto.java b/src/main/java/gdsc/comunity/dto/channel/ChannelCreateDto.java new file mode 100644 index 0000000..e23ba57 --- /dev/null +++ b/src/main/java/gdsc/comunity/dto/channel/ChannelCreateDto.java @@ -0,0 +1,11 @@ +package gdsc.comunity.dto.channel; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class ChannelCreateDto { + private String channelName; + private String nickname; +} diff --git a/src/main/java/gdsc/comunity/entity/user/UserChannel.java b/src/main/java/gdsc/comunity/entity/user/UserChannel.java index 8539d66..ebb0ab8 100644 --- a/src/main/java/gdsc/comunity/entity/user/UserChannel.java +++ b/src/main/java/gdsc/comunity/entity/user/UserChannel.java @@ -44,7 +44,4 @@ private UserChannel(String nickname, User user, Channel channel) { public void updateNickname(String nickname) { this.nickname = nickname; } -} - - - +} \ No newline at end of file diff --git a/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java b/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java index cc961b3..9fc2013 100644 --- a/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java +++ b/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java @@ -1,24 +1,22 @@ package gdsc.comunity.repository.user; -import gdsc.comunity.entity.user.User; import gdsc.comunity.entity.user.UserChannel; -import org.springframework.boot.autoconfigure.flyway.FlywayProperties; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import java.util.List; import java.util.Optional; +@Repository public interface UserChannelRepository extends JpaRepository { - Optional findSecondByChannelIdOrderByCreatedDateDesc(Long channelId); + List findTop2ByChannelIdOrderByCreatedDateAsc(Long channelId); - Optional findByUserIdAndChannelId(Long id, Long channelId); + Optional findByUserIdAndChannelId(Long userId, Long channelId); void deleteAllByChannelId(Long channelId); List findAllByChannelId(Long channelId); - Optional findByUserIdAndNickname(Long userId, String nickname); - Optional findByUserId(Long userId); } diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelService.java b/src/main/java/gdsc/comunity/service/channel/ChannelService.java index 39d4c1d..1f18bf9 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelService.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelService.java @@ -8,7 +8,7 @@ import java.util.List; public interface ChannelService { - Channel createChannel(Long userId, String channelName); + Channel createChannel(Long userId, String channelName, String nickname); void leaveChannel(Long userId, Long channelId); diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java index 00cc942..4a01a5d 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java @@ -26,13 +26,21 @@ public class ChannelServiceImpl implements ChannelService { private final ChannelJoinRequestRepository channelJoinRequestRepository; @Override - public Channel createChannel(Long userId, String channelName) { + public Channel createChannel(Long userId, String channelName, String nickname) { User user = userRepository.findById(userId).orElseThrow(); Channel newChannel = Channel.builder() .channelName(channelName) .manager(user) .build(); channelRepository.save(newChannel); + + UserChannel userChannel = UserChannel.builder() + .channel(newChannel) + .user(user) + .nickname(nickname) + .build(); + userChannelRepository.save(userChannel); + return newChannel; } @@ -53,8 +61,12 @@ public void leaveChannel(Long userId, Long channelId) { } // 대상이 매니저인 경우, 채널 매니저 변경 - UserChannel newManagerUserChannel = userChannelRepository.findSecondByChannelIdOrderByCreatedDateDesc(channelId) - .orElseThrow(() -> new IllegalArgumentException("There is no manager in this channel.")); + List userChannelList = userChannelRepository.findTop2ByChannelIdOrderByCreatedDateAsc(channelId); + // list의 size가 2이상인 경우 진행 아니면 exception + if (userChannelList.size() < 2) { + throw new IllegalArgumentException("There is no user to be a manager."); + } + UserChannel newManagerUserChannel = userChannelList.get(1); channel.updateManager(newManagerUserChannel.getUser()); channelRepository.save(channel); @@ -112,7 +124,7 @@ public void sendJoinRequest(String nickname, Long userId, Long channelId) { @Override @Transactional - public void approveJoinChannel(Long userId, Long targetUserId, Long channelId){ + public void approveJoinChannel(Long userId, Long targetUserId, Long channelId) { // 채널 가입 요청을 승인하고 UserChannel에 저장. 이후 ChannelJoinRequest 삭제 ChannelJoinRequest channelJoinRequest = channelJoinRequestRepository.findByUserIdAndChannelId(targetUserId, channelId).orElseThrow(); User user = userRepository.findById(userId).orElseThrow(); @@ -138,7 +150,7 @@ public List searchJoinRequest(Long userId, Long channelId) { } @Override - public void changeNickname(Long userId, Long channelId, String nickname){ + public void changeNickname(Long userId, Long channelId, String nickname) { // 닉네임 중복 확인 후 변경. doubleCheckNicknameThrowException(channelId, nickname); @@ -148,7 +160,7 @@ public void changeNickname(Long userId, Long channelId, String nickname){ } @Override - public void doubleCheckNicknameThrowException(Long channelId, String nickname){ + public void doubleCheckNicknameThrowException(Long channelId, String nickname) { // 닉네임 중복 시 throw Exception userChannelRepository.findAllByChannelId(channelId).stream() .filter(userChannel -> userChannel.getNickname().equals(nickname)) diff --git a/src/main/java/gdsc/comunity/util/TestUtil.java b/src/main/java/gdsc/comunity/util/TestUtil.java deleted file mode 100644 index 5701b47..0000000 --- a/src/main/java/gdsc/comunity/util/TestUtil.java +++ /dev/null @@ -1,27 +0,0 @@ -package gdsc.comunity.util; - -import java.lang.reflect.Field; -import java.time.LocalDateTime; - -public class TestUtil { - public static void setField(Object object, String fieldName, Object value) { - Field field; - try { - field = object.getClass().getDeclaredField(fieldName); - field.setAccessible(true); - field.set(object, value); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - public static Object getTestDate() { - return LocalDateTime.now(); - } - - public static void setDate(Object object) { - // set createdDate, modifiedDate - setField(object, "createdDate", getTestDate()); - setField(object, "modifiedDate", getTestDate()); - } -} diff --git a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java index 3bf0203..5ced9d6 100644 --- a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java +++ b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java @@ -1,20 +1,21 @@ package gdsc.comunity.service.channel; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; import static org.junit.jupiter.api.Assertions.*; import static org.assertj.core.api.Assertions.assertThat; import gdsc.comunity.dto.channel.ChannelInfoDto; import gdsc.comunity.entity.channel.Channel; +import gdsc.comunity.entity.channel.ChannelJoinRequest; import gdsc.comunity.entity.user.Provider; import gdsc.comunity.entity.user.User; import gdsc.comunity.entity.user.UserChannel; +import gdsc.comunity.repository.channel.ChannelJoinRequestRepository; import gdsc.comunity.repository.channel.ChannelRepository; import gdsc.comunity.repository.user.UserChannelRepository; import gdsc.comunity.repository.user.UserRepository; -import gdsc.comunity.util.TestUtil; -import org.junit.jupiter.api.Test; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -22,13 +23,16 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.transaction.annotation.Transactional; +import java.util.List; import java.util.Optional; //TODO : Test code 작성 @ExtendWith(SpringExtension.class) @SpringBootTest //@ActiveProfiles("test") // Ensure you use the 'test' profile to avoid using the production database -@Transactional // Ensure that each test is independently rolled back after execution +@Transactional +@Slf4j +@TestMethodOrder(MethodOrderer.MethodName.class) public class ChannelServiceImplTest { @Autowired private ChannelServiceImpl channelService; @@ -38,10 +42,13 @@ public class ChannelServiceImplTest { private ChannelRepository channelRepository; @Autowired private UserChannelRepository userChannelRepository; + @Autowired + private ChannelJoinRequestRepository channelJoinRequestRepository; @Test + @DisplayName("채널 생성 성공") void createChannel_Success() { - // Arrange + // set env User user = User.builder() .email("email") .profileImageUrl("image") @@ -50,10 +57,10 @@ void createChannel_Success() { .build(); user = userRepository.save(user); - // Act - Channel channel = channelService.createChannel(user.getId(), "New Channel"); + // do + Channel channel = channelService.createChannel(user.getId(), "New Channel", "nickname"); - // Assert + // assert result assertNotNull(channel.getId()); assertEquals("New Channel", channel.getChannelName()); assertEquals(user.getId(), channel.getManager().getId()); @@ -63,7 +70,76 @@ void createChannel_Success() { } @Test - void leaveChannel_Success() { + @DisplayName("채널 가입 요청 성공") + void sendJoinRequest_Success() { + // set env + User user = User.builder() + .email("email") + .profileImageUrl("image") + .provider(Provider.GOOGLE) + .providerId("1") + .build(); + user = userRepository.save(user); + + User manager = User.builder() + .email("manager") + .profileImageUrl("manager") + .provider(Provider.GOOGLE) + .providerId("2") + .build(); + manager = userRepository.save(manager); + + Channel channel = channelService.createChannel(manager.getId(), "New Channel", "nickname"); + + // do + channelService.sendJoinRequest("nickname2", user.getId(), channel.getId()); + + // assert result + Optional userChannel = userChannelRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); + assertTrue(userChannel.isEmpty()); + + Optional channelJoinRequest = channelJoinRequestRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); + assertTrue(channelJoinRequest.isPresent()); + } + + @Test + @DisplayName("채널 가입 요청 승인 성공") + void approveJoinChannel_Success() { + // set env + User user = User.builder() + .email("email") + .profileImageUrl("image") + .provider(Provider.GOOGLE) + .providerId("1") + .build(); + user = userRepository.save(user); + + User manager = User.builder() + .email("manager") + .profileImageUrl("manager") + .provider(Provider.GOOGLE) + .providerId("2") + .build(); + manager = userRepository.save(manager); + + Channel channel = channelService.createChannel(manager.getId(), "New Channel", "nickname"); + + channelService.sendJoinRequest("nickname2", user.getId(), channel.getId()); + + // do + channelService.approveJoinChannel(manager.getId(), user.getId(), channel.getId()); + + // assert result + Optional userChannel = userChannelRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); + assertTrue(userChannel.isPresent()); + + Optional channelJoinRequest = channelJoinRequestRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); + assertTrue(channelJoinRequest.isEmpty()); + } + + @Test + @DisplayName("채널 나가기 성공 - 매니저가 아닌 경우") + void leaveChannel_Success_WithNormalUser() { // Arrange User user = User.builder() .email("email") @@ -81,8 +157,110 @@ void leaveChannel_Success() { .build(); manager = userRepository.save(manager); - Channel channel = channelService.createChannel(manager.getId(), "New Channel"); - // TODO : user join to channel + Channel channel = channelService.createChannel(manager.getId(), "New Channel", "nickname"); + channelService.sendJoinRequest("nickname2", user.getId(), channel.getId()); + channelService.approveJoinChannel(manager.getId(), user.getId(), channel.getId()); + + // Act + channelService.leaveChannel(manager.getId(), channel.getId()); + + // Assert + Optional userChannel = userChannelRepository.findByUserIdAndChannelId(manager.getId(), channel.getId()); + assertTrue(userChannel.isEmpty()); + + Optional channelOptional = channelRepository.findById(channel.getId()); + assertTrue(channelOptional.isPresent()); + assertEquals(user.getId(), channelOptional.get().getManager().getId()); + } + + @Test + @DisplayName("채널 나가기 실패 - 매니저인 경우, 매니저를 넘겨줄 사람이 없는 경우") + void leaveChannel_Failure_WithManager_NoMoreUser() { + // Arrange + User manager = User.builder() + .email("manager") + .profileImageUrl("manager") + .provider(Provider.GOOGLE) + .providerId("2") + .build(); + manager = userRepository.save(manager); + + Channel channel = channelService.createChannel(manager.getId(), "New Channel", "nickname"); + + // Act & Assert + Long managerId = manager.getId(); + Long channelId = channel.getId(); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + channelService.leaveChannel(managerId, channelId); + }); + assertEquals("There is no user to be a manager.", exception.getMessage()); + } + + @Test + @DisplayName("UserChannel respository 메소드 테스트 - findTop2ByChannelIdOrderByCreatedDateDesc") + void userRepositoryFindTop2ByChannelIdOrderByCreatedDateDesc() { + // Arrange + User manager = User.builder() + .email("manager") + .profileImageUrl("manager") + .provider(Provider.GOOGLE) + .providerId("2") + .build(); + manager = userRepository.save(manager); + + User user1 = User.builder() + .email("email1") + .profileImageUrl("image1") + .provider(Provider.GOOGLE) + .providerId("1") + .build(); + user1 = userRepository.save(user1); + + User user2 = User.builder() + .email("email2") + .profileImageUrl("image2") + .provider(Provider.GOOGLE) + .providerId("3") + .build(); + user2 = userRepository.save(user2); + + Channel channel = channelService.createChannel(manager.getId(), "New Channel", "nickname"); + channelService.sendJoinRequest("nickname1", user1.getId(), channel.getId()); + channelService.sendJoinRequest("nickname2", user2.getId(), channel.getId()); + channelService.approveJoinChannel(manager.getId(), user1.getId(), channel.getId()); + channelService.approveJoinChannel(manager.getId(), user2.getId(), channel.getId()); + + // Act + List listUserChannel = userChannelRepository.findTop2ByChannelIdOrderByCreatedDateAsc(channel.getId()); + + // Assert + assertEquals(2, listUserChannel.size()); + } + + @Test + @DisplayName("채널 나가기 성공 - 매니저인 경우, 매니저를 넘겨줄 사람이 있는 경우") + void leaveChannel_Success_WithManager_HasMoreUser() { + // Arrange + User manager = User.builder() + .email("manager") + .profileImageUrl("manager") + .provider(Provider.GOOGLE) + .providerId("2") + .build(); + manager = userRepository.save(manager); + + User user = User.builder() + .email("email") + .profileImageUrl("image") + .provider(Provider.GOOGLE) + .providerId("1") + .build(); + user = userRepository.save(user); + + Channel channel = channelService.createChannel(manager.getId(), "New Channel", "nickname"); + channelService.sendJoinRequest("nickname2", user.getId(), channel.getId()); + channelService.approveJoinChannel(manager.getId(), user.getId(), channel.getId()); // Act channelService.leaveChannel(manager.getId(), channel.getId()); @@ -97,6 +275,7 @@ void leaveChannel_Success() { } @Test + @DisplayName("채널 삭제 실패 - 매니저가 아닌 경우") void deleteChannel_Failure_NotManager() { // Arrange User user = User.builder() @@ -115,7 +294,7 @@ void deleteChannel_Failure_NotManager() { .build(); manager = userRepository.save(manager); - Channel channel = channelService.createChannel(manager.getId(), "New Channel"); + Channel channel = channelService.createChannel(manager.getId(), "New Channel", "nickname"); Long userId = user.getId(); Long channelId = channel.getId(); @@ -128,6 +307,28 @@ void deleteChannel_Failure_NotManager() { } @Test + @DisplayName("채널 삭제 성공") + void deleteChannel_Success() { + // Arrange + User manager = User.builder() + .email("manager") + .profileImageUrl("manager") + .provider(Provider.GOOGLE) + .providerId("2") + .build(); + manager = userRepository.save(manager); + Channel channel = channelService.createChannel(manager.getId(), "New Channel", "nickname"); + + // Act + channelService.deleteChannel(manager.getId(), channel.getId()); + + // Assert + Optional channelOptional = channelRepository.findById(channel.getId()); + assertTrue(channelOptional.isEmpty()); + } + + @Test + @DisplayName("채널 검색 성공") void searchChannel_Success() { // Arrange User manager = User.builder() @@ -137,7 +338,7 @@ void searchChannel_Success() { .providerId("2") .build(); manager = userRepository.save(manager); - Channel channel = channelService.createChannel(manager.getId(), "New Channel"); + Channel channel = channelService.createChannel(manager.getId(), "New Channel", "nickname"); // Act ChannelInfoDto result = channelService.searchChannel(channel.getId()); From 64a56716c523c3ee9d1d789d6c4d65ffa346f9d9 Mon Sep 17 00:00:00 2001 From: fhiller Date: Fri, 26 Apr 2024 17:01:22 +0900 Subject: [PATCH 07/19] =?UTF-8?q?refactor(Channel)=20:=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C-=EC=BD=94=EB=93=9C=20api=20=EC=9D=BC=EC=B9=98?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95.=20List=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=20=ED=98=95=EC=8B=9D=EC=9D=84=20Wrapper?= =?UTF-8?q?=EB=A1=9C=20=EA=B0=90=EC=8B=B8=EC=84=9C=20=EB=B0=98=ED=99=98.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ChannelController.java | 14 +++----- .../comunity/dto/channel/ChannelInfoDto.java | 34 +++++++++++++++++-- .../dto/channel/ChannelJoinRequestDto.java | 13 +++++++ .../user/UserChannelRepository.java | 1 - .../service/channel/ChannelService.java | 3 +- .../service/channel/ChannelServiceImpl.java | 17 ++++++++-- .../java/gdsc/comunity/util/ListWrapper.java | 12 +++++++ 7 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 src/main/java/gdsc/comunity/dto/channel/ChannelJoinRequestDto.java create mode 100644 src/main/java/gdsc/comunity/util/ListWrapper.java diff --git a/src/main/java/gdsc/comunity/controller/ChannelController.java b/src/main/java/gdsc/comunity/controller/ChannelController.java index 1aa0b61..85ae410 100644 --- a/src/main/java/gdsc/comunity/controller/ChannelController.java +++ b/src/main/java/gdsc/comunity/controller/ChannelController.java @@ -1,13 +1,11 @@ package gdsc.comunity.controller; -import gdsc.comunity.dto.channel.ApproveJoinChannelDto; -import gdsc.comunity.dto.channel.ChannelCreateDto; -import gdsc.comunity.dto.channel.ChannelInfoDto; -import gdsc.comunity.dto.channel.ChannelNicknameDto; +import gdsc.comunity.dto.channel.*; import gdsc.comunity.entity.channel.ChannelJoinRequest; import gdsc.comunity.entity.user.Provider; import gdsc.comunity.entity.user.User; import gdsc.comunity.service.channel.ChannelServiceImpl; +import gdsc.comunity.util.ListWrapper; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -21,7 +19,6 @@ public class ChannelController { private final ChannelServiceImpl channelServiceImpl; - // TODO : 사용자 id는 @UserId 어노테이션으로 받아올 예정이다. @PostMapping ResponseEntity createChannel(@RequestBody ChannelCreateDto channelCreateDto, Long id){ String channelName = channelCreateDto.getChannelName(); @@ -37,10 +34,9 @@ ResponseEntity searchChannel(@PathVariable Long channelId, Long } @GetMapping("/join/{channelId}") - ResponseEntity> searchJoinRequest(@PathVariable Long channelId, Long id){ - // TODO : 반환 형식이 아직 정해지지 않았다. 회의를 통해 문서화하고 코드에 반영 필요. - List userList = channelServiceImpl.searchJoinRequest(id, channelId); - return new ResponseEntity<>(userList, HttpStatus.OK); + ResponseEntity>> searchJoinRequest(@PathVariable Long channelId, Long id){ + List userList = channelServiceImpl.searchJoinRequest(id, channelId); + return new ResponseEntity<>(new ListWrapper<>(userList), HttpStatus.OK); } @PostMapping("/join/{channelId}") diff --git a/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java b/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java index c5f84d9..6c705ab 100644 --- a/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java +++ b/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java @@ -1,16 +1,46 @@ package gdsc.comunity.dto.channel; import gdsc.comunity.entity.user.User; +import gdsc.comunity.entity.user.UserChannel; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.ArrayList; import java.util.List; -@AllArgsConstructor @Getter public class ChannelInfoDto { + + @Getter + public static class UserDto { + private Long id; + private String email; + private String nickname; + private String profileImageUrl; + + public UserDto(String nickname, User user) { + this.id = user.getId(); + this.email = user.getEmail(); + this.nickname = nickname; + this.profileImageUrl = user.getProfileImageUrl(); + } + } + private String channelName; private String openDate; private String managerNickname; - private List channelUsers; + private List channelUsers; + + public ChannelInfoDto(String channelName, String openDate, String managerNickname, List userChannelList, List userList) { + this.channelName = channelName; + this.openDate = openDate; + this.managerNickname = managerNickname; + this.channelUsers = new ArrayList<>(); + + for (UserChannel userChannel : userChannelList) { + for (User user : userList) { + channelUsers.add(new UserDto(userChannel.getNickname(), user)); + } + } + } } diff --git a/src/main/java/gdsc/comunity/dto/channel/ChannelJoinRequestDto.java b/src/main/java/gdsc/comunity/dto/channel/ChannelJoinRequestDto.java new file mode 100644 index 0000000..754fd11 --- /dev/null +++ b/src/main/java/gdsc/comunity/dto/channel/ChannelJoinRequestDto.java @@ -0,0 +1,13 @@ +package gdsc.comunity.dto.channel; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class ChannelJoinRequestDto { + Long id; + Long userId; + Long channelId; + String nickname; +} diff --git a/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java b/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java index 9fc2013..75a0d20 100644 --- a/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java +++ b/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java @@ -8,7 +8,6 @@ import java.util.List; import java.util.Optional; -@Repository public interface UserChannelRepository extends JpaRepository { List findTop2ByChannelIdOrderByCreatedDateAsc(Long channelId); diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelService.java b/src/main/java/gdsc/comunity/service/channel/ChannelService.java index 1f18bf9..057c5c5 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelService.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelService.java @@ -1,6 +1,7 @@ package gdsc.comunity.service.channel; import gdsc.comunity.dto.channel.ChannelInfoDto; +import gdsc.comunity.dto.channel.ChannelJoinRequestDto; import gdsc.comunity.entity.channel.Channel; import gdsc.comunity.entity.channel.ChannelJoinRequest; import gdsc.comunity.entity.user.User; @@ -20,7 +21,7 @@ public interface ChannelService { void sendJoinRequest(String nickname, Long userId, Long channelId); - List searchJoinRequest(Long userId, Long channelId); + List searchJoinRequest(Long userId, Long channelId); void changeNickname(Long userId, Long channelId, String nickname); diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java index 4a01a5d..c436b5a 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java @@ -1,6 +1,7 @@ package gdsc.comunity.service.channel; import gdsc.comunity.dto.channel.ChannelInfoDto; +import gdsc.comunity.dto.channel.ChannelJoinRequestDto; import gdsc.comunity.entity.channel.Channel; import gdsc.comunity.entity.channel.ChannelJoinRequest; import gdsc.comunity.entity.user.User; @@ -94,7 +95,9 @@ public void deleteChannel(Long userId, Long channelId) { @Override public ChannelInfoDto searchChannel(Long channelId) { Channel channel = channelRepository.findById(channelId).orElseThrow(); - List channelUsers = userChannelRepository.findAllByChannelId(channelId).stream().map(UserChannel::getUser).toList(); + List userChannels = userChannelRepository.findAllByChannelId(channelId); + List channelUsers = userChannels.stream().map(UserChannel::getUser).toList(); + UserChannel manager = userChannelRepository.findByUserIdAndChannelId(channel.getManager().getId(), channelId).orElseThrow(); // 요청한 채널의 정보(채널 이름, 생성일, 매니저 닉네임, 채널 유저 리스트) 반환 @@ -102,6 +105,7 @@ public ChannelInfoDto searchChannel(Long channelId) { channel.getChannelName(), channel.getCreatedDate().toString(), manager.getNickname(), + userChannels, channelUsers ); } @@ -139,14 +143,21 @@ public void approveJoinChannel(Long userId, Long targetUserId, Long channelId) { } @Override - public List searchJoinRequest(Long userId, Long channelId) { + public List searchJoinRequest(Long userId, Long channelId) { // 채널의 매니저가 이나라면 예외 발생 Channel channel = channelRepository.findById(channelId). orElseThrow(() -> new IllegalArgumentException("Channel does not exist.")); if (!Objects.equals(channel.getManager().getId(), userId)) { throw new IllegalArgumentException("Only manager can search join request."); } - return channelJoinRequestRepository.findAllByChannelId(channelId); + return channelJoinRequestRepository.findAllByChannelId(channelId).stream().map( + channelJoinRequest -> new ChannelJoinRequestDto( + channelJoinRequest.getId(), + channelJoinRequest.getUser().getId(), + channelJoinRequest.getChannel().getId(), + channelJoinRequest.getNickname() + ) + ).toList(); } @Override diff --git a/src/main/java/gdsc/comunity/util/ListWrapper.java b/src/main/java/gdsc/comunity/util/ListWrapper.java new file mode 100644 index 0000000..cc71e93 --- /dev/null +++ b/src/main/java/gdsc/comunity/util/ListWrapper.java @@ -0,0 +1,12 @@ +package gdsc.comunity.util; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class ListWrapper { + private T data; +} From 992992533519fe6c660bc11ba7e8952d0a2d1755 Mon Sep 17 00:00:00 2001 From: fhiller Date: Mon, 29 Apr 2024 11:41:29 +0900 Subject: [PATCH 08/19] =?UTF-8?q?fix(Backend)=20:=20=EC=8B=A4=ED=96=89=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=20=ED=95=B4=EA=B2=B0.=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=9A=A9=20=ED=99=98=EA=B2=BD=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20DB=20Compatibility=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- .../comunity/controller/OAuthController.java | 1 - .../user/UserChannelJpaRepository.java | 11 +++++++ .../comunity/service/OAuthGoogleService.java | 1 - .../service/channel/ChannelServiceImpl.java | 30 +++++++++---------- src/main/resources/application.yml | 2 +- .../channel/ChannelServiceImplTest.java | 25 +++++++++------- 7 files changed, 43 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index ca66177..f1e79dc 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,5 @@ out/ .vscode/ ### env ### -.env \ No newline at end of file +.env +application-test.yml \ No newline at end of file diff --git a/src/main/java/gdsc/comunity/controller/OAuthController.java b/src/main/java/gdsc/comunity/controller/OAuthController.java index a80d47c..e2df645 100644 --- a/src/main/java/gdsc/comunity/controller/OAuthController.java +++ b/src/main/java/gdsc/comunity/controller/OAuthController.java @@ -1,6 +1,5 @@ package gdsc.comunity.controller; -import gdsc.comunity.dto.GoogleUserInfo; import gdsc.comunity.dto.JwtTokensDto; import java.util.Map; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/gdsc/comunity/repository/user/UserChannelJpaRepository.java b/src/main/java/gdsc/comunity/repository/user/UserChannelJpaRepository.java index 300602d..458240b 100644 --- a/src/main/java/gdsc/comunity/repository/user/UserChannelJpaRepository.java +++ b/src/main/java/gdsc/comunity/repository/user/UserChannelJpaRepository.java @@ -6,10 +6,21 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.util.List; import java.util.Optional; public interface UserChannelJpaRepository extends JpaRepository { @Query(value = "SELECT user_id FROM user_channel WHERE nickname = :senderNickname AND channel_id = :channelId", nativeQuery = true) Optional findUserIdByNicknameAndChannel(@Param("senderNickname") String senderNickname, @Param("channelId") Long channelId); + + List findTop2ByChannelIdOrderByCreatedDateAsc(Long channelId); + + Optional findByUserIdAndChannelId(Long userId, Long channelId); + + void deleteAllByChannelId(Long channelId); + + List findAllByChannelId(Long channelId); + + Optional findByUserId(Long userId); } diff --git a/src/main/java/gdsc/comunity/service/OAuthGoogleService.java b/src/main/java/gdsc/comunity/service/OAuthGoogleService.java index 650878c..b1fb15b 100644 --- a/src/main/java/gdsc/comunity/service/OAuthGoogleService.java +++ b/src/main/java/gdsc/comunity/service/OAuthGoogleService.java @@ -1,6 +1,5 @@ package gdsc.comunity.service; -import gdsc.comunity.dto.GoogleUserInfo; import gdsc.comunity.dto.JwtTokensDto; import gdsc.comunity.entity.user.Provider; import gdsc.comunity.entity.user.User; diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java index c436b5a..55e07e8 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java @@ -8,7 +8,7 @@ import gdsc.comunity.entity.user.UserChannel; import gdsc.comunity.repository.channel.ChannelJoinRequestRepository; import gdsc.comunity.repository.channel.ChannelRepository; -import gdsc.comunity.repository.user.UserChannelRepository; +import gdsc.comunity.repository.user.UserChannelJpaRepository; import gdsc.comunity.repository.user.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -22,7 +22,7 @@ // TODO : Exception handling public class ChannelServiceImpl implements ChannelService { private final ChannelRepository channelRepository; - private final UserChannelRepository userChannelRepository; + private final UserChannelJpaRepository userChannelJpaRepository; private final UserRepository userRepository; private final ChannelJoinRequestRepository channelJoinRequestRepository; @@ -40,7 +40,7 @@ public Channel createChannel(Long userId, String channelName, String nickname) { .user(user) .nickname(nickname) .build(); - userChannelRepository.save(userChannel); + userChannelJpaRepository.save(userChannel); return newChannel; } @@ -52,8 +52,8 @@ public void leaveChannel(Long userId, Long channelId) { Channel channel = channelRepository.findById(channelId).orElseThrow(); // 대상이 매니저가 아닌 경우, UserChannel 삭제 if (!(Objects.equals(channel.getManager().getId(), user.getId()))) { - userChannelRepository.findByUserIdAndChannelId(user.getId(), channelId).ifPresentOrElse( - userChannelRepository::delete, + userChannelJpaRepository.findByUserIdAndChannelId(user.getId(), channelId).ifPresentOrElse( + userChannelJpaRepository::delete, () -> { throw new IllegalArgumentException("You are not in this channel."); } @@ -62,7 +62,7 @@ public void leaveChannel(Long userId, Long channelId) { } // 대상이 매니저인 경우, 채널 매니저 변경 - List userChannelList = userChannelRepository.findTop2ByChannelIdOrderByCreatedDateAsc(channelId); + List userChannelList = userChannelJpaRepository.findTop2ByChannelIdOrderByCreatedDateAsc(channelId); // list의 size가 2이상인 경우 진행 아니면 exception if (userChannelList.size() < 2) { throw new IllegalArgumentException("There is no user to be a manager."); @@ -72,8 +72,8 @@ public void leaveChannel(Long userId, Long channelId) { channelRepository.save(channel); // 이후 대상의 UserChannel 삭제 - UserChannel deleteUserChannel = userChannelRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow(); - userChannelRepository.delete(deleteUserChannel); + UserChannel deleteUserChannel = userChannelJpaRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow(); + userChannelJpaRepository.delete(deleteUserChannel); } @Override @@ -88,17 +88,17 @@ public void deleteChannel(Long userId, Long channelId) { } // 연관된 UserChannel 및 Channel 삭제 - userChannelRepository.deleteAllByChannelId(channelId); + userChannelJpaRepository.deleteAllByChannelId(channelId); channelRepository.delete(channel); } @Override public ChannelInfoDto searchChannel(Long channelId) { Channel channel = channelRepository.findById(channelId).orElseThrow(); - List userChannels = userChannelRepository.findAllByChannelId(channelId); + List userChannels = userChannelJpaRepository.findAllByChannelId(channelId); List channelUsers = userChannels.stream().map(UserChannel::getUser).toList(); - UserChannel manager = userChannelRepository.findByUserIdAndChannelId(channel.getManager().getId(), channelId).orElseThrow(); + UserChannel manager = userChannelJpaRepository.findByUserIdAndChannelId(channel.getManager().getId(), channelId).orElseThrow(); // 요청한 채널의 정보(채널 이름, 생성일, 매니저 닉네임, 채널 유저 리스트) 반환 return new ChannelInfoDto( @@ -134,7 +134,7 @@ public void approveJoinChannel(Long userId, Long targetUserId, Long channelId) { User user = userRepository.findById(userId).orElseThrow(); Channel channel = channelRepository.findById(channelId).orElseThrow(); - userChannelRepository.save(UserChannel.builder() + userChannelJpaRepository.save(UserChannel.builder() .channel(channel) .user(channelJoinRequest.getUser()) .nickname(channelJoinRequest.getNickname()) @@ -165,15 +165,15 @@ public void changeNickname(Long userId, Long channelId, String nickname) { // 닉네임 중복 확인 후 변경. doubleCheckNicknameThrowException(channelId, nickname); - UserChannel userChannel = userChannelRepository.findByUserId(userId).orElseThrow(); + UserChannel userChannel = userChannelJpaRepository.findByUserId(userId).orElseThrow(); userChannel.updateNickname(nickname); - userChannelRepository.save(userChannel); + userChannelJpaRepository.save(userChannel); } @Override public void doubleCheckNicknameThrowException(Long channelId, String nickname) { // 닉네임 중복 시 throw Exception - userChannelRepository.findAllByChannelId(channelId).stream() + userChannelJpaRepository.findAllByChannelId(channelId).stream() .filter(userChannel -> userChannel.getNickname().equals(nickname)) .findAny() .ifPresent(userChannel -> { diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 22cf694..9425723 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: datasource: - url: "jdbc:h2:mem:community;MODE=PostgreSQL" + url: "jdbc:h2:mem:community;MODE=mysql" username: "sa" password: "" driver-class-name: org.h2.Driver diff --git a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java index 5ced9d6..d868405 100644 --- a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java +++ b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java @@ -12,7 +12,7 @@ import gdsc.comunity.entity.user.UserChannel; import gdsc.comunity.repository.channel.ChannelJoinRequestRepository; import gdsc.comunity.repository.channel.ChannelRepository; -import gdsc.comunity.repository.user.UserChannelRepository; +import gdsc.comunity.repository.user.UserChannelJpaRepository; import gdsc.comunity.repository.user.UserRepository; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.*; @@ -20,19 +20,22 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; //import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.annotation.Rollback; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Optional; -//TODO : Test code 작성 @ExtendWith(SpringExtension.class) @SpringBootTest -//@ActiveProfiles("test") // Ensure you use the 'test' profile to avoid using the production database +@ActiveProfiles("test") @Transactional +@Rollback @Slf4j @TestMethodOrder(MethodOrderer.MethodName.class) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class ChannelServiceImplTest { @Autowired private ChannelServiceImpl channelService; @@ -41,7 +44,7 @@ public class ChannelServiceImplTest { @Autowired private ChannelRepository channelRepository; @Autowired - private UserChannelRepository userChannelRepository; + private UserChannelJpaRepository userChannelJpaRepository; @Autowired private ChannelJoinRequestRepository channelJoinRequestRepository; @@ -65,7 +68,7 @@ void createChannel_Success() { assertEquals("New Channel", channel.getChannelName()); assertEquals(user.getId(), channel.getManager().getId()); - Optional userChannel = userChannelRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); + Optional userChannel = userChannelJpaRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); assertTrue(userChannel.isPresent()); } @@ -95,7 +98,7 @@ void sendJoinRequest_Success() { channelService.sendJoinRequest("nickname2", user.getId(), channel.getId()); // assert result - Optional userChannel = userChannelRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); + Optional userChannel = userChannelJpaRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); assertTrue(userChannel.isEmpty()); Optional channelJoinRequest = channelJoinRequestRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); @@ -107,7 +110,7 @@ void sendJoinRequest_Success() { void approveJoinChannel_Success() { // set env User user = User.builder() - .email("email") + .email("email2") .profileImageUrl("image") .provider(Provider.GOOGLE) .providerId("1") @@ -130,7 +133,7 @@ void approveJoinChannel_Success() { channelService.approveJoinChannel(manager.getId(), user.getId(), channel.getId()); // assert result - Optional userChannel = userChannelRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); + Optional userChannel = userChannelJpaRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); assertTrue(userChannel.isPresent()); Optional channelJoinRequest = channelJoinRequestRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); @@ -165,7 +168,7 @@ void leaveChannel_Success_WithNormalUser() { channelService.leaveChannel(manager.getId(), channel.getId()); // Assert - Optional userChannel = userChannelRepository.findByUserIdAndChannelId(manager.getId(), channel.getId()); + Optional userChannel = userChannelJpaRepository.findByUserIdAndChannelId(manager.getId(), channel.getId()); assertTrue(userChannel.isEmpty()); Optional channelOptional = channelRepository.findById(channel.getId()); @@ -232,7 +235,7 @@ void userRepositoryFindTop2ByChannelIdOrderByCreatedDateDesc() { channelService.approveJoinChannel(manager.getId(), user2.getId(), channel.getId()); // Act - List listUserChannel = userChannelRepository.findTop2ByChannelIdOrderByCreatedDateAsc(channel.getId()); + List listUserChannel = userChannelJpaRepository.findTop2ByChannelIdOrderByCreatedDateAsc(channel.getId()); // Assert assertEquals(2, listUserChannel.size()); @@ -266,7 +269,7 @@ void leaveChannel_Success_WithManager_HasMoreUser() { channelService.leaveChannel(manager.getId(), channel.getId()); // Assert - Optional userChannel = userChannelRepository.findByUserIdAndChannelId(manager.getId(), channel.getId()); + Optional userChannel = userChannelJpaRepository.findByUserIdAndChannelId(manager.getId(), channel.getId()); assertTrue(userChannel.isEmpty()); Optional channelOptional = channelRepository.findById(channel.getId()); From 4821e3b3dc5824843659e4ecbc50a08753966521 Mon Sep 17 00:00:00 2001 From: fhiller Date: Mon, 29 Apr 2024 16:28:53 +0900 Subject: [PATCH 09/19] =?UTF-8?q?refactor(Channel)=20:=20Optional=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EB=B0=9C=EC=83=9D=20=EC=84=A4=EC=A0=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/channel/ChannelServiceImpl.java | 76 +++++++++++++------ 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java index 55e07e8..c79adea 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java @@ -19,7 +19,6 @@ @Service @RequiredArgsConstructor -// TODO : Exception handling public class ChannelServiceImpl implements ChannelService { private final ChannelRepository channelRepository; private final UserChannelJpaRepository userChannelJpaRepository; @@ -27,8 +26,11 @@ public class ChannelServiceImpl implements ChannelService { private final ChannelJoinRequestRepository channelJoinRequestRepository; @Override + @Transactional public Channel createChannel(Long userId, String channelName, String nickname) { - User user = userRepository.findById(userId).orElseThrow(); + User user = userRepository.findById(userId).orElseThrow( + () -> new IllegalArgumentException("해당 사용자가 존재하지 않습니다.") + ); Channel newChannel = Channel.builder() .channelName(channelName) .manager(user) @@ -48,16 +50,18 @@ public Channel createChannel(Long userId, String channelName, String nickname) { @Override @Transactional public void leaveChannel(Long userId, Long channelId) { - User user = userRepository.findById(userId).orElseThrow(); - Channel channel = channelRepository.findById(channelId).orElseThrow(); + User user = userRepository.findById(userId).orElseThrow( + () -> new IllegalArgumentException("해당 사용자가 존재하지 않습니다.") + ); + Channel channel = channelRepository.findById(channelId).orElseThrow( + () -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.") + ); // 대상이 매니저가 아닌 경우, UserChannel 삭제 if (!(Objects.equals(channel.getManager().getId(), user.getId()))) { - userChannelJpaRepository.findByUserIdAndChannelId(user.getId(), channelId).ifPresentOrElse( - userChannelJpaRepository::delete, - () -> { - throw new IllegalArgumentException("You are not in this channel."); - } + UserChannel userChannel = userChannelJpaRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow( + () -> new IllegalStateException("사용자 본인이 해당 채널에 속해있지 않습니다.") ); + userChannelJpaRepository.delete(userChannel); return; } @@ -65,26 +69,32 @@ public void leaveChannel(Long userId, Long channelId) { List userChannelList = userChannelJpaRepository.findTop2ByChannelIdOrderByCreatedDateAsc(channelId); // list의 size가 2이상인 경우 진행 아니면 exception if (userChannelList.size() < 2) { - throw new IllegalArgumentException("There is no user to be a manager."); + throw new IllegalStateException("채널에 다른 사용자가 없어 채널을 탈퇴할 수 없습니다. 채널 삭제를 진행해주세요."); } UserChannel newManagerUserChannel = userChannelList.get(1); channel.updateManager(newManagerUserChannel.getUser()); channelRepository.save(channel); // 이후 대상의 UserChannel 삭제 - UserChannel deleteUserChannel = userChannelJpaRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow(); + UserChannel deleteUserChannel = userChannelJpaRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow( + () -> new IllegalArgumentException("해당 사용자가 채널에 속해있지 않습니다.") + ); userChannelJpaRepository.delete(deleteUserChannel); } @Override @Transactional public void deleteChannel(Long userId, Long channelId) { - User user = userRepository.findById(userId).orElseThrow(); + User user = userRepository.findById(userId).orElseThrow( + () -> new IllegalArgumentException("해당 사용자가 존재하지 않습니다.") + ); // 채널 매니저만 채널 삭제 가능 - Channel channel = channelRepository.findById(channelId).orElseThrow(); + Channel channel = channelRepository.findById(channelId).orElseThrow( + () -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.") + ); if (!(Objects.equals(channel.getManager().getId(), user.getId()))) { - throw new IllegalArgumentException("Only manager can delete channel."); + throw new IllegalStateException("채널 매니저만 채널을 삭제할 수 있습니다."); } // 연관된 UserChannel 및 Channel 삭제 @@ -94,11 +104,15 @@ public void deleteChannel(Long userId, Long channelId) { @Override public ChannelInfoDto searchChannel(Long channelId) { - Channel channel = channelRepository.findById(channelId).orElseThrow(); + Channel channel = channelRepository.findById(channelId).orElseThrow( + () -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.") + ); List userChannels = userChannelJpaRepository.findAllByChannelId(channelId); List channelUsers = userChannels.stream().map(UserChannel::getUser).toList(); - UserChannel manager = userChannelJpaRepository.findByUserIdAndChannelId(channel.getManager().getId(), channelId).orElseThrow(); + UserChannel manager = userChannelJpaRepository.findByUserIdAndChannelId(channel.getManager().getId(), channelId).orElseThrow( + () -> new IllegalArgumentException("해당 채널의 매니저가 존재하지 않습니다.") + ); // 요청한 채널의 정보(채널 이름, 생성일, 매니저 닉네임, 채널 유저 리스트) 반환 return new ChannelInfoDto( @@ -114,8 +128,12 @@ public ChannelInfoDto searchChannel(Long channelId) { public void sendJoinRequest(String nickname, Long userId, Long channelId) { doubleCheckNicknameThrowException(channelId, nickname); - User user = userRepository.findById(userId).orElseThrow(); - Channel channel = channelRepository.findById(channelId).orElseThrow(); + User user = userRepository.findById(userId).orElseThrow( + () -> new IllegalArgumentException("해당 사용자가 존재하지 않습니다.") + ); + Channel channel = channelRepository.findById(channelId).orElseThrow( + () -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.") + ); // 사용자에 대한 채널 가입 요청 저장 channelJoinRequestRepository.save(ChannelJoinRequest @@ -130,9 +148,15 @@ public void sendJoinRequest(String nickname, Long userId, Long channelId) { @Transactional public void approveJoinChannel(Long userId, Long targetUserId, Long channelId) { // 채널 가입 요청을 승인하고 UserChannel에 저장. 이후 ChannelJoinRequest 삭제 - ChannelJoinRequest channelJoinRequest = channelJoinRequestRepository.findByUserIdAndChannelId(targetUserId, channelId).orElseThrow(); - User user = userRepository.findById(userId).orElseThrow(); - Channel channel = channelRepository.findById(channelId).orElseThrow(); + ChannelJoinRequest channelJoinRequest = channelJoinRequestRepository.findByUserIdAndChannelId(targetUserId, channelId).orElseThrow( + () -> new IllegalArgumentException("해당 사용자의 채널 가입 요청이 존재하지 않습니다.") + ); + User user = userRepository.findById(userId).orElseThrow( + () -> new IllegalArgumentException("해당 사용자가 존재하지 않습니다.") + ); + Channel channel = channelRepository.findById(channelId).orElseThrow( + () -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.") + ); userChannelJpaRepository.save(UserChannel.builder() .channel(channel) @@ -146,9 +170,9 @@ public void approveJoinChannel(Long userId, Long targetUserId, Long channelId) { public List searchJoinRequest(Long userId, Long channelId) { // 채널의 매니저가 이나라면 예외 발생 Channel channel = channelRepository.findById(channelId). - orElseThrow(() -> new IllegalArgumentException("Channel does not exist.")); + orElseThrow(() -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.")); if (!Objects.equals(channel.getManager().getId(), userId)) { - throw new IllegalArgumentException("Only manager can search join request."); + throw new IllegalArgumentException("매니저만 채널 가입 요청을 조회할 수 있습니다."); } return channelJoinRequestRepository.findAllByChannelId(channelId).stream().map( channelJoinRequest -> new ChannelJoinRequestDto( @@ -165,7 +189,9 @@ public void changeNickname(Long userId, Long channelId, String nickname) { // 닉네임 중복 확인 후 변경. doubleCheckNicknameThrowException(channelId, nickname); - UserChannel userChannel = userChannelJpaRepository.findByUserId(userId).orElseThrow(); + UserChannel userChannel = userChannelJpaRepository.findByUserId(userId).orElseThrow( + () -> new IllegalArgumentException("해당 사용자가 채널에 속해있지 않습니다.") + ); userChannel.updateNickname(nickname); userChannelJpaRepository.save(userChannel); } @@ -177,7 +203,7 @@ public void doubleCheckNicknameThrowException(Long channelId, String nickname) { .filter(userChannel -> userChannel.getNickname().equals(nickname)) .findAny() .ifPresent(userChannel -> { - throw new IllegalArgumentException("Nickname is already exist in this channel."); + throw new IllegalStateException("이미 사용 중인 닉네임입니다."); }); } } From 9b9905275b290f35902f9ff4b3613ab9faa7be3a Mon Sep 17 00:00:00 2001 From: fhiller Date: Mon, 29 Apr 2024 16:33:34 +0900 Subject: [PATCH 10/19] =?UTF-8?q?fix(Channel)=20:=20=EB=A7=A4=EB=8B=88?= =?UTF-8?q?=EC=A0=80=EB=A7=8C=20=EA=B0=80=EC=9E=85=20=EC=8A=B9=EC=9D=B8=20?= =?UTF-8?q?=EC=A1=B0=EA=B1=B4=20=EC=B6=94=EA=B0=80.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/channel/ChannelServiceImpl.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java index c79adea..e0e05ac 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java @@ -147,10 +147,6 @@ public void sendJoinRequest(String nickname, Long userId, Long channelId) { @Override @Transactional public void approveJoinChannel(Long userId, Long targetUserId, Long channelId) { - // 채널 가입 요청을 승인하고 UserChannel에 저장. 이후 ChannelJoinRequest 삭제 - ChannelJoinRequest channelJoinRequest = channelJoinRequestRepository.findByUserIdAndChannelId(targetUserId, channelId).orElseThrow( - () -> new IllegalArgumentException("해당 사용자의 채널 가입 요청이 존재하지 않습니다.") - ); User user = userRepository.findById(userId).orElseThrow( () -> new IllegalArgumentException("해당 사용자가 존재하지 않습니다.") ); @@ -158,6 +154,16 @@ public void approveJoinChannel(Long userId, Long targetUserId, Long channelId) { () -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.") ); + // 채널의 매니저만 채널 가입 요청 승인 가능 + if (!Objects.equals(channel.getManager().getId(), user.getId())) { + throw new IllegalArgumentException("채널 매니저만 채널 가입 요청을 승인할 수 있습니다."); + } + + // 채널 가입 요청을 승인하고 UserChannel에 저장. 이후 ChannelJoinRequest 삭제 + ChannelJoinRequest channelJoinRequest = channelJoinRequestRepository.findByUserIdAndChannelId(targetUserId, channelId).orElseThrow( + () -> new IllegalArgumentException("해당 사용자의 채널 가입 요청이 존재하지 않습니다.") + ); + userChannelJpaRepository.save(UserChannel.builder() .channel(channel) .user(channelJoinRequest.getUser()) From 330183345ab3c44febdcb7dca01f30aa22f5b48c Mon Sep 17 00:00:00 2001 From: fhiller Date: Mon, 29 Apr 2024 16:34:20 +0900 Subject: [PATCH 11/19] =?UTF-8?q?test(Channel)=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=A1=B0?= =?UTF-8?q?=EA=B1=B4=20=EC=A0=9C=EA=B1=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comunity/service/channel/ChannelServiceImplTest.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java index d868405..c36a2b6 100644 --- a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java +++ b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java @@ -194,10 +194,9 @@ void leaveChannel_Failure_WithManager_NoMoreUser() { Long managerId = manager.getId(); Long channelId = channel.getId(); - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> { channelService.leaveChannel(managerId, channelId); }); - assertEquals("There is no user to be a manager.", exception.getMessage()); } @Test @@ -303,10 +302,9 @@ void deleteChannel_Failure_NotManager() { Long channelId = channel.getId(); // Act && Assert - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> { channelService.deleteChannel(userId, channelId); }); - assertEquals("Only manager can delete channel.", exception.getMessage()); } @Test From 3d27659fe10378a7d8feaf288b3f80f9a29d2212 Mon Sep 17 00:00:00 2001 From: fhiller Date: Mon, 29 Apr 2024 16:56:34 +0900 Subject: [PATCH 12/19] =?UTF-8?q?fix(Channel)=20:=20UserId=20=EC=95=A0?= =?UTF-8?q?=EB=84=88=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=97=B0=EA=B2=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ChannelController.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/main/java/gdsc/comunity/controller/ChannelController.java b/src/main/java/gdsc/comunity/controller/ChannelController.java index 85ae410..7d6d7f3 100644 --- a/src/main/java/gdsc/comunity/controller/ChannelController.java +++ b/src/main/java/gdsc/comunity/controller/ChannelController.java @@ -1,9 +1,7 @@ package gdsc.comunity.controller; +import gdsc.comunity.annotation.UserId; import gdsc.comunity.dto.channel.*; -import gdsc.comunity.entity.channel.ChannelJoinRequest; -import gdsc.comunity.entity.user.Provider; -import gdsc.comunity.entity.user.User; import gdsc.comunity.service.channel.ChannelServiceImpl; import gdsc.comunity.util.ListWrapper; import lombok.RequiredArgsConstructor; @@ -20,7 +18,7 @@ public class ChannelController { private final ChannelServiceImpl channelServiceImpl; @PostMapping - ResponseEntity createChannel(@RequestBody ChannelCreateDto channelCreateDto, Long id){ + ResponseEntity createChannel(@RequestBody ChannelCreateDto channelCreateDto, @UserId Long id) { String channelName = channelCreateDto.getChannelName(); String nickname = channelCreateDto.getNickname(); channelServiceImpl.createChannel(id, channelName, nickname); @@ -28,37 +26,37 @@ ResponseEntity createChannel(@RequestBody ChannelCreateDto channelCreate } @GetMapping("/{channelId}") - ResponseEntity searchChannel(@PathVariable Long channelId, Long id){ + ResponseEntity searchChannel(@PathVariable Long channelId, @UserId Long id) { ChannelInfoDto channelInfoDto = channelServiceImpl.searchChannel(channelId); return new ResponseEntity<>(channelInfoDto, HttpStatus.OK); } @GetMapping("/join/{channelId}") - ResponseEntity>> searchJoinRequest(@PathVariable Long channelId, Long id){ + ResponseEntity>> searchJoinRequest(@PathVariable Long channelId, @UserId Long id) { List userList = channelServiceImpl.searchJoinRequest(id, channelId); return new ResponseEntity<>(new ListWrapper<>(userList), HttpStatus.OK); } @PostMapping("/join/{channelId}") - ResponseEntity sendJoinRequest(@RequestBody String nickname, @PathVariable Long channelId, Long id){ + ResponseEntity sendJoinRequest(@RequestBody String nickname, @PathVariable Long channelId, @UserId Long id) { channelServiceImpl.sendJoinRequest(nickname, id, channelId); return new ResponseEntity<>("Channel joined.", HttpStatus.OK); } @PutMapping("/join/{channelId}") - ResponseEntity leaveChannel(@PathVariable Long channelId, Long id){ + ResponseEntity leaveChannel(@PathVariable Long channelId, @UserId Long id) { channelServiceImpl.leaveChannel(id, channelId); return new ResponseEntity<>("Channel left.", HttpStatus.OK); } @DeleteMapping("/join/{channelId}") - ResponseEntity deleteChannel(@PathVariable Long channelId, Long id){ + ResponseEntity deleteChannel(@PathVariable Long channelId, @UserId Long id) { channelServiceImpl.deleteChannel(id, channelId); return new ResponseEntity<>("Channel deleted.", HttpStatus.OK); } @PutMapping("/approve") - ResponseEntity approveJoinChannel(@RequestBody ApproveJoinChannelDto approveJoinChannelDto, Long userId){ + ResponseEntity approveJoinChannel(@RequestBody ApproveJoinChannelDto approveJoinChannelDto, @UserId Long userId) { Long targetUserId = approveJoinChannelDto.getUserId(); Long channelId = approveJoinChannelDto.getChannelId(); channelServiceImpl.approveJoinChannel(userId, targetUserId, channelId); @@ -66,7 +64,7 @@ ResponseEntity approveJoinChannel(@RequestBody ApproveJoinChannelDto app } @PutMapping("/nickname") - ResponseEntity changeNickname(@RequestBody ChannelNicknameDto channelNicknameDto, Long id){ + ResponseEntity changeNickname(@RequestBody ChannelNicknameDto channelNicknameDto, @UserId Long id) { String nickname = channelNicknameDto.getNickname(); Long channelId = channelNicknameDto.getChannelId(); channelServiceImpl.changeNickname(id, channelId, nickname); From 34d527fa7ceb6d400e8bf1caa00725e75daeea53 Mon Sep 17 00:00:00 2001 From: fhiller Date: Tue, 30 Apr 2024 14:33:31 +0900 Subject: [PATCH 13/19] =?UTF-8?q?feat(Channel)=20:=20Manager=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=EB=B3=84=EB=8F=84?= =?UTF-8?q?=EC=9D=98=20=EB=A9=94=EC=84=9C=EB=93=9C=EB=A1=9C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/channel/ChannelService.java | 4 ++-- .../service/channel/ChannelServiceImpl.java | 22 ++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelService.java b/src/main/java/gdsc/comunity/service/channel/ChannelService.java index 057c5c5..89ec4ad 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelService.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelService.java @@ -3,8 +3,6 @@ import gdsc.comunity.dto.channel.ChannelInfoDto; import gdsc.comunity.dto.channel.ChannelJoinRequestDto; import gdsc.comunity.entity.channel.Channel; -import gdsc.comunity.entity.channel.ChannelJoinRequest; -import gdsc.comunity.entity.user.User; import java.util.List; @@ -26,4 +24,6 @@ public interface ChannelService { void changeNickname(Long userId, Long channelId, String nickname); void doubleCheckNicknameThrowException(Long channelId, String nickname); + + void checkManagerThrowException(Long userId, Long channelId); } diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java index e0e05ac..80ade51 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java @@ -5,11 +5,11 @@ import gdsc.comunity.entity.channel.Channel; import gdsc.comunity.entity.channel.ChannelJoinRequest; import gdsc.comunity.entity.user.User; -import gdsc.comunity.entity.user.UserChannel; +import gdsc.comunity.entity.userchannel.UserChannel; import gdsc.comunity.repository.channel.ChannelJoinRequestRepository; import gdsc.comunity.repository.channel.ChannelRepository; -import gdsc.comunity.repository.user.UserChannelJpaRepository; import gdsc.comunity.repository.user.UserRepository; +import gdsc.comunity.repository.userchannel.UserChannelJpaRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -154,10 +154,7 @@ public void approveJoinChannel(Long userId, Long targetUserId, Long channelId) { () -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.") ); - // 채널의 매니저만 채널 가입 요청 승인 가능 - if (!Objects.equals(channel.getManager().getId(), user.getId())) { - throw new IllegalArgumentException("채널 매니저만 채널 가입 요청을 승인할 수 있습니다."); - } + checkManagerThrowException(userId, channel.getManager().getId()); // 채널 가입 요청을 승인하고 UserChannel에 저장. 이후 ChannelJoinRequest 삭제 ChannelJoinRequest channelJoinRequest = channelJoinRequestRepository.findByUserIdAndChannelId(targetUserId, channelId).orElseThrow( @@ -174,12 +171,10 @@ public void approveJoinChannel(Long userId, Long targetUserId, Long channelId) { @Override public List searchJoinRequest(Long userId, Long channelId) { - // 채널의 매니저가 이나라면 예외 발생 Channel channel = channelRepository.findById(channelId). orElseThrow(() -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.")); - if (!Objects.equals(channel.getManager().getId(), userId)) { - throw new IllegalArgumentException("매니저만 채널 가입 요청을 조회할 수 있습니다."); - } + checkManagerThrowException(userId, channel.getManager().getId()); + return channelJoinRequestRepository.findAllByChannelId(channelId).stream().map( channelJoinRequest -> new ChannelJoinRequestDto( channelJoinRequest.getId(), @@ -212,4 +207,11 @@ public void doubleCheckNicknameThrowException(Long channelId, String nickname) { throw new IllegalStateException("이미 사용 중인 닉네임입니다."); }); } + + @Override + public void checkManagerThrowException(Long userId, Long managerId) { + if (!Objects.equals(userId, managerId)) { + throw new IllegalArgumentException("해당 채널의 매니저가 아닙니다."); + } + } } From 1b973a0253f6d592ead673bca7566cfead5c9d68 Mon Sep 17 00:00:00 2001 From: fhiller Date: Tue, 30 Apr 2024 14:35:49 +0900 Subject: [PATCH 14/19] =?UTF-8?q?refactor(UserChannel)=20:=20UserChannel?= =?UTF-8?q?=20=EC=97=94=ED=8B=B0=ED=8B=B0,=20=EB=A0=88=ED=8F=AC=EC=A7=80?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=EC=9D=98=20=ED=8F=B4=EB=8D=94=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gdsc/comunity/dto/channel/ChannelInfoDto.java | 3 +-- .../entity/{user => userchannel}/UserChannel.java | 12 +++--------- .../UserChannelJpaRepository.java | 4 ++-- .../{user => userchannel}/UserChannelRepository.java | 2 +- .../UserChannelRepositoryImpl.java | 2 +- src/main/java/gdsc/comunity/service/ChatService.java | 4 ++-- .../service/channel/ChannelServiceImplTest.java | 12 +++++------- 7 files changed, 15 insertions(+), 24 deletions(-) rename src/main/java/gdsc/comunity/entity/{user => userchannel}/UserChannel.java (73%) rename src/main/java/gdsc/comunity/repository/{user => userchannel}/UserChannelJpaRepository.java (90%) rename src/main/java/gdsc/comunity/repository/{user => userchannel}/UserChannelRepository.java (82%) rename src/main/java/gdsc/comunity/repository/{user => userchannel}/UserChannelRepositoryImpl.java (96%) diff --git a/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java b/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java index 6c705ab..0fd1c3d 100644 --- a/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java +++ b/src/main/java/gdsc/comunity/dto/channel/ChannelInfoDto.java @@ -1,8 +1,7 @@ package gdsc.comunity.dto.channel; import gdsc.comunity.entity.user.User; -import gdsc.comunity.entity.user.UserChannel; -import lombok.AllArgsConstructor; +import gdsc.comunity.entity.userchannel.UserChannel; import lombok.Getter; import java.util.ArrayList; diff --git a/src/main/java/gdsc/comunity/entity/user/UserChannel.java b/src/main/java/gdsc/comunity/entity/userchannel/UserChannel.java similarity index 73% rename from src/main/java/gdsc/comunity/entity/user/UserChannel.java rename to src/main/java/gdsc/comunity/entity/userchannel/UserChannel.java index ebb0ab8..d8f18e5 100644 --- a/src/main/java/gdsc/comunity/entity/user/UserChannel.java +++ b/src/main/java/gdsc/comunity/entity/userchannel/UserChannel.java @@ -1,15 +1,9 @@ -package gdsc.comunity.entity.user; +package gdsc.comunity.entity.userchannel; import gdsc.comunity.entity.channel.Channel; import gdsc.comunity.entity.common.BaseTimeEntity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; +import gdsc.comunity.entity.user.User; +import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; diff --git a/src/main/java/gdsc/comunity/repository/user/UserChannelJpaRepository.java b/src/main/java/gdsc/comunity/repository/userchannel/UserChannelJpaRepository.java similarity index 90% rename from src/main/java/gdsc/comunity/repository/user/UserChannelJpaRepository.java rename to src/main/java/gdsc/comunity/repository/userchannel/UserChannelJpaRepository.java index 458240b..8a099f8 100644 --- a/src/main/java/gdsc/comunity/repository/user/UserChannelJpaRepository.java +++ b/src/main/java/gdsc/comunity/repository/userchannel/UserChannelJpaRepository.java @@ -1,7 +1,7 @@ -package gdsc.comunity.repository.user; +package gdsc.comunity.repository.userchannel; -import gdsc.comunity.entity.user.UserChannel; +import gdsc.comunity.entity.userchannel.UserChannel; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java b/src/main/java/gdsc/comunity/repository/userchannel/UserChannelRepository.java similarity index 82% rename from src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java rename to src/main/java/gdsc/comunity/repository/userchannel/UserChannelRepository.java index 4681a1b..dcfd3ee 100644 --- a/src/main/java/gdsc/comunity/repository/user/UserChannelRepository.java +++ b/src/main/java/gdsc/comunity/repository/userchannel/UserChannelRepository.java @@ -1,4 +1,4 @@ -package gdsc.comunity.repository.user; +package gdsc.comunity.repository.userchannel; import java.util.Map; diff --git a/src/main/java/gdsc/comunity/repository/user/UserChannelRepositoryImpl.java b/src/main/java/gdsc/comunity/repository/userchannel/UserChannelRepositoryImpl.java similarity index 96% rename from src/main/java/gdsc/comunity/repository/user/UserChannelRepositoryImpl.java rename to src/main/java/gdsc/comunity/repository/userchannel/UserChannelRepositoryImpl.java index 13145da..005a247 100644 --- a/src/main/java/gdsc/comunity/repository/user/UserChannelRepositoryImpl.java +++ b/src/main/java/gdsc/comunity/repository/userchannel/UserChannelRepositoryImpl.java @@ -1,4 +1,4 @@ -package gdsc.comunity.repository.user; +package gdsc.comunity.repository.userchannel; import lombok.RequiredArgsConstructor; import org.springframework.jdbc.core.JdbcTemplate; diff --git a/src/main/java/gdsc/comunity/service/ChatService.java b/src/main/java/gdsc/comunity/service/ChatService.java index 8e2d701..1fc1c10 100644 --- a/src/main/java/gdsc/comunity/service/ChatService.java +++ b/src/main/java/gdsc/comunity/service/ChatService.java @@ -1,11 +1,11 @@ package gdsc.comunity.service; -import gdsc.comunity.dto.chat.PagingChatting; import gdsc.comunity.dto.chat.Chatting; +import gdsc.comunity.dto.chat.PagingChatting; import gdsc.comunity.entity.chat.ChatLog; import gdsc.comunity.repository.channel.ChannelRepository; import gdsc.comunity.repository.chat.ChatRepository; -import gdsc.comunity.repository.user.UserChannelRepository; +import gdsc.comunity.repository.userchannel.UserChannelRepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.scheduling.annotation.Async; diff --git a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java index c36a2b6..f88775f 100644 --- a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java +++ b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java @@ -1,25 +1,20 @@ package gdsc.comunity.service.channel; -import static org.mockito.ArgumentMatchers.any; -import static org.junit.jupiter.api.Assertions.*; -import static org.assertj.core.api.Assertions.assertThat; - import gdsc.comunity.dto.channel.ChannelInfoDto; import gdsc.comunity.entity.channel.Channel; import gdsc.comunity.entity.channel.ChannelJoinRequest; import gdsc.comunity.entity.user.Provider; import gdsc.comunity.entity.user.User; -import gdsc.comunity.entity.user.UserChannel; +import gdsc.comunity.entity.userchannel.UserChannel; import gdsc.comunity.repository.channel.ChannelJoinRequestRepository; import gdsc.comunity.repository.channel.ChannelRepository; -import gdsc.comunity.repository.user.UserChannelJpaRepository; import gdsc.comunity.repository.user.UserRepository; +import gdsc.comunity.repository.userchannel.UserChannelJpaRepository; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -//import org.springframework.test.context.ActiveProfiles; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -28,6 +23,9 @@ import java.util.List; import java.util.Optional; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + @ExtendWith(SpringExtension.class) @SpringBootTest @ActiveProfiles("test") From 7bbfee4be76a5bce8be484e07ffa9b38ff5fa248 Mon Sep 17 00:00:00 2001 From: fhiller Date: Wed, 1 May 2024 14:43:43 +0900 Subject: [PATCH 15/19] =?UTF-8?q?feat(UserChannel,=20Channel)=20:=20Channe?= =?UTF-8?q?l=EC=97=90=EC=84=9C=20CASCADE=EB=A5=BC=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=EB=B3=80=EA=B2=BD.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gdsc/comunity/entity/channel/Channel.java | 27 +++++++++++++------ .../service/channel/ChannelServiceImpl.java | 16 ++++++----- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/main/java/gdsc/comunity/entity/channel/Channel.java b/src/main/java/gdsc/comunity/entity/channel/Channel.java index 241b4b2..36be96b 100644 --- a/src/main/java/gdsc/comunity/entity/channel/Channel.java +++ b/src/main/java/gdsc/comunity/entity/channel/Channel.java @@ -3,19 +3,16 @@ import gdsc.comunity.entity.common.BaseTimeEntity; import gdsc.comunity.entity.user.User; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; +import gdsc.comunity.entity.userchannel.UserChannel; +import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import java.util.HashSet; +import java.util.Set; + @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity @@ -42,6 +39,9 @@ public class Channel extends BaseTimeEntity { private String channelName; + @OneToMany(mappedBy = "channel", cascade = CascadeType.ALL, orphanRemoval = true) + private Set userChannels; + @Builder private Channel(User manager, String channelName) { this.manager = manager; @@ -51,4 +51,15 @@ private Channel(User manager, String channelName) { public void updateManager(User newManager) { this.manager = newManager; } + + public void addUserChannel(UserChannel userChannel) { + if (userChannels == null) { + userChannels = new HashSet<>(); + } + userChannels.add(userChannel); + } + + public void removeUserChannel(UserChannel userChannel) { + userChannels.remove(userChannel); + } } diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java index 80ade51..d860b20 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java @@ -35,14 +35,16 @@ public Channel createChannel(Long userId, String channelName, String nickname) { .channelName(channelName) .manager(user) .build(); - channelRepository.save(newChannel); UserChannel userChannel = UserChannel.builder() .channel(newChannel) .user(user) .nickname(nickname) .build(); - userChannelJpaRepository.save(userChannel); + + newChannel.addUserChannel(userChannel); + channelRepository.save(newChannel); +// userChannelJpaRepository.save(userChannel); return newChannel; } @@ -61,6 +63,8 @@ public void leaveChannel(Long userId, Long channelId) { UserChannel userChannel = userChannelJpaRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow( () -> new IllegalStateException("사용자 본인이 해당 채널에 속해있지 않습니다.") ); + channel.removeUserChannel(userChannel); + channelRepository.save(channel); userChannelJpaRepository.delete(userChannel); return; } @@ -71,15 +75,15 @@ public void leaveChannel(Long userId, Long channelId) { if (userChannelList.size() < 2) { throw new IllegalStateException("채널에 다른 사용자가 없어 채널을 탈퇴할 수 없습니다. 채널 삭제를 진행해주세요."); } - UserChannel newManagerUserChannel = userChannelList.get(1); - channel.updateManager(newManagerUserChannel.getUser()); - channelRepository.save(channel); - // 이후 대상의 UserChannel 삭제 UserChannel deleteUserChannel = userChannelJpaRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow( () -> new IllegalArgumentException("해당 사용자가 채널에 속해있지 않습니다.") ); userChannelJpaRepository.delete(deleteUserChannel); + + channel.updateManager(userChannelList.get(1).getUser()); + channel.removeUserChannel(deleteUserChannel); + channelRepository.save(channel); } @Override From c467c234ba043f60fd5b8599c7984295bdcd8f4d Mon Sep 17 00:00:00 2001 From: fhiller Date: Wed, 1 May 2024 14:44:24 +0900 Subject: [PATCH 16/19] =?UTF-8?q?test(Channel)=20:=20Channel=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EB=B0=9C=EA=B2=AC=20=EB=B0=8F=20=EC=88=98=EC=A0=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comunity/service/channel/ChannelServiceImplTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java index f88775f..4c3b415 100644 --- a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java +++ b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java @@ -163,15 +163,15 @@ void leaveChannel_Success_WithNormalUser() { channelService.approveJoinChannel(manager.getId(), user.getId(), channel.getId()); // Act - channelService.leaveChannel(manager.getId(), channel.getId()); + channelService.leaveChannel(user.getId(), channel.getId()); // Assert - Optional userChannel = userChannelJpaRepository.findByUserIdAndChannelId(manager.getId(), channel.getId()); - assertTrue(userChannel.isEmpty()); + Optional userChannelOptional = userChannelJpaRepository.findByUserIdAndChannelId(user.getId(), channel.getId()); + assertTrue(userChannelOptional.isEmpty()); Optional channelOptional = channelRepository.findById(channel.getId()); assertTrue(channelOptional.isPresent()); - assertEquals(user.getId(), channelOptional.get().getManager().getId()); + assertEquals(manager.getId(), channelOptional.get().getManager().getId()); } @Test From db57725898bc75bafc46ca17d05792a051f7f89e Mon Sep 17 00:00:00 2001 From: fhiller Date: Wed, 1 May 2024 14:50:29 +0900 Subject: [PATCH 17/19] =?UTF-8?q?fix(Channel)=20:=20Channel=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EB=A1=9C=EC=A7=81=20CASCADE=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EB=B0=9C=EA=B2=AC=20=EB=B0=8F=20=EB=B3=80=EA=B2=BD.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/gdsc/comunity/service/channel/ChannelServiceImpl.java | 3 --- .../gdsc/comunity/service/channel/ChannelServiceImplTest.java | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java index d860b20..5e8d5f2 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java @@ -44,7 +44,6 @@ public Channel createChannel(Long userId, String channelName, String nickname) { newChannel.addUserChannel(userChannel); channelRepository.save(newChannel); -// userChannelJpaRepository.save(userChannel); return newChannel; } @@ -101,8 +100,6 @@ public void deleteChannel(Long userId, Long channelId) { throw new IllegalStateException("채널 매니저만 채널을 삭제할 수 있습니다."); } - // 연관된 UserChannel 및 Channel 삭제 - userChannelJpaRepository.deleteAllByChannelId(channelId); channelRepository.delete(channel); } diff --git a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java index 4c3b415..ab75bf7 100644 --- a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java +++ b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java @@ -324,6 +324,9 @@ void deleteChannel_Success() { // Assert Optional channelOptional = channelRepository.findById(channel.getId()); assertTrue(channelOptional.isEmpty()); + + Optional userChannelOptional = userChannelJpaRepository.findByUserIdAndChannelId(manager.getId(), channel.getId()); + assertTrue(userChannelOptional.isEmpty()); } @Test From 71c4f31fe6da227c913dd601005006f613c4de57 Mon Sep 17 00:00:00 2001 From: fhiller Date: Wed, 1 May 2024 15:56:03 +0900 Subject: [PATCH 18/19] =?UTF-8?q?refactor(Channel)=20:=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=EB=90=98=EB=8A=94=20=EC=98=88=EC=99=B8=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=EB=AC=B8=20=ED=95=A8=EC=88=98=EB=A1=9C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/channel/ChannelService.java | 5 ++ .../service/channel/ChannelServiceImpl.java | 56 ++++++++----------- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelService.java b/src/main/java/gdsc/comunity/service/channel/ChannelService.java index 89ec4ad..b0345d0 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelService.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelService.java @@ -3,6 +3,7 @@ import gdsc.comunity.dto.channel.ChannelInfoDto; import gdsc.comunity.dto.channel.ChannelJoinRequestDto; import gdsc.comunity.entity.channel.Channel; +import gdsc.comunity.entity.user.User; import java.util.List; @@ -26,4 +27,8 @@ public interface ChannelService { void doubleCheckNicknameThrowException(Long channelId, String nickname); void checkManagerThrowException(Long userId, Long channelId); + + User findUserByIdThrowException(Long userId); + + Channel findChannelByIdThrowException(Long channelId); } diff --git a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java index 5e8d5f2..25355a7 100644 --- a/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java +++ b/src/main/java/gdsc/comunity/service/channel/ChannelServiceImpl.java @@ -28,9 +28,8 @@ public class ChannelServiceImpl implements ChannelService { @Override @Transactional public Channel createChannel(Long userId, String channelName, String nickname) { - User user = userRepository.findById(userId).orElseThrow( - () -> new IllegalArgumentException("해당 사용자가 존재하지 않습니다.") - ); + User user = findUserByIdThrowException(userId); + Channel newChannel = Channel.builder() .channelName(channelName) .manager(user) @@ -51,12 +50,9 @@ public Channel createChannel(Long userId, String channelName, String nickname) { @Override @Transactional public void leaveChannel(Long userId, Long channelId) { - User user = userRepository.findById(userId).orElseThrow( - () -> new IllegalArgumentException("해당 사용자가 존재하지 않습니다.") - ); - Channel channel = channelRepository.findById(channelId).orElseThrow( - () -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.") - ); + User user = findUserByIdThrowException(userId); + Channel channel = findChannelByIdThrowException(channelId); + // 대상이 매니저가 아닌 경우, UserChannel 삭제 if (!(Objects.equals(channel.getManager().getId(), user.getId()))) { UserChannel userChannel = userChannelJpaRepository.findByUserIdAndChannelId(user.getId(), channelId).orElseThrow( @@ -88,14 +84,10 @@ public void leaveChannel(Long userId, Long channelId) { @Override @Transactional public void deleteChannel(Long userId, Long channelId) { - User user = userRepository.findById(userId).orElseThrow( - () -> new IllegalArgumentException("해당 사용자가 존재하지 않습니다.") - ); + User user = findUserByIdThrowException(userId); + Channel channel = findChannelByIdThrowException(channelId); // 채널 매니저만 채널 삭제 가능 - Channel channel = channelRepository.findById(channelId).orElseThrow( - () -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.") - ); if (!(Objects.equals(channel.getManager().getId(), user.getId()))) { throw new IllegalStateException("채널 매니저만 채널을 삭제할 수 있습니다."); } @@ -105,9 +97,7 @@ public void deleteChannel(Long userId, Long channelId) { @Override public ChannelInfoDto searchChannel(Long channelId) { - Channel channel = channelRepository.findById(channelId).orElseThrow( - () -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.") - ); + Channel channel = findChannelByIdThrowException(channelId); List userChannels = userChannelJpaRepository.findAllByChannelId(channelId); List channelUsers = userChannels.stream().map(UserChannel::getUser).toList(); @@ -129,14 +119,9 @@ public ChannelInfoDto searchChannel(Long channelId) { public void sendJoinRequest(String nickname, Long userId, Long channelId) { doubleCheckNicknameThrowException(channelId, nickname); - User user = userRepository.findById(userId).orElseThrow( - () -> new IllegalArgumentException("해당 사용자가 존재하지 않습니다.") - ); - Channel channel = channelRepository.findById(channelId).orElseThrow( - () -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.") - ); + User user = findUserByIdThrowException(userId); + Channel channel = findChannelByIdThrowException(channelId); - // 사용자에 대한 채널 가입 요청 저장 channelJoinRequestRepository.save(ChannelJoinRequest .builder() .channel(channel) @@ -148,12 +133,8 @@ public void sendJoinRequest(String nickname, Long userId, Long channelId) { @Override @Transactional public void approveJoinChannel(Long userId, Long targetUserId, Long channelId) { - User user = userRepository.findById(userId).orElseThrow( - () -> new IllegalArgumentException("해당 사용자가 존재하지 않습니다.") - ); - Channel channel = channelRepository.findById(channelId).orElseThrow( - () -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.") - ); + User user = findUserByIdThrowException(userId); + Channel channel = findChannelByIdThrowException(channelId); checkManagerThrowException(userId, channel.getManager().getId()); @@ -172,8 +153,7 @@ public void approveJoinChannel(Long userId, Long targetUserId, Long channelId) { @Override public List searchJoinRequest(Long userId, Long channelId) { - Channel channel = channelRepository.findById(channelId). - orElseThrow(() -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.")); + Channel channel = findChannelByIdThrowException(channelId); checkManagerThrowException(userId, channel.getManager().getId()); return channelJoinRequestRepository.findAllByChannelId(channelId).stream().map( @@ -215,4 +195,14 @@ public void checkManagerThrowException(Long userId, Long managerId) { throw new IllegalArgumentException("해당 채널의 매니저가 아닙니다."); } } + + @Override + public User findUserByIdThrowException(Long userId) { + return userRepository.findById(userId).orElseThrow(() -> new IllegalArgumentException("해당 사용자가 존재하지 않습니다.")); + } + + @Override + public Channel findChannelByIdThrowException(Long channelId) { + return channelRepository.findById(channelId).orElseThrow(() -> new IllegalArgumentException("해당 채널이 존재하지 않습니다.")); + } } From bbd1a767c5a37186a397fa2196348057894316a4 Mon Sep 17 00:00:00 2001 From: fhiller Date: Wed, 1 May 2024 15:57:13 +0900 Subject: [PATCH 19/19] =?UTF-8?q?refactor(Class)=20:=20DI=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20=EC=83=9D=EC=84=B1=EC=9E=90=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD.=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=9C=84=EC=A3=BC?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/channel/ApproveJoinChannelDto.java | 10 ++++----- .../dto/channel/ChannelCreateDto.java | 7 ++++-- .../dto/channel/ChannelJoinRequestDto.java | 9 ++++++-- .../dto/channel/ChannelNicknameDto.java | 7 ++++-- .../java/gdsc/comunity/dto/chat/Chatting.java | 8 +++++-- .../channel/ChannelServiceImplTest.java | 22 +++++++++++-------- 6 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/main/java/gdsc/comunity/dto/channel/ApproveJoinChannelDto.java b/src/main/java/gdsc/comunity/dto/channel/ApproveJoinChannelDto.java index e3cdeff..916916c 100644 --- a/src/main/java/gdsc/comunity/dto/channel/ApproveJoinChannelDto.java +++ b/src/main/java/gdsc/comunity/dto/channel/ApproveJoinChannelDto.java @@ -1,14 +1,14 @@ package gdsc.comunity.dto.channel; -import gdsc.comunity.entity.user.User; -import lombok.AllArgsConstructor; import lombok.Getter; -import java.util.List; - -@AllArgsConstructor @Getter public class ApproveJoinChannelDto { private Long userId; private Long channelId; + + public ApproveJoinChannelDto(Long userId, Long channelId) { + this.userId = userId; + this.channelId = channelId; + } } diff --git a/src/main/java/gdsc/comunity/dto/channel/ChannelCreateDto.java b/src/main/java/gdsc/comunity/dto/channel/ChannelCreateDto.java index e23ba57..ba912ca 100644 --- a/src/main/java/gdsc/comunity/dto/channel/ChannelCreateDto.java +++ b/src/main/java/gdsc/comunity/dto/channel/ChannelCreateDto.java @@ -1,11 +1,14 @@ package gdsc.comunity.dto.channel; -import lombok.AllArgsConstructor; import lombok.Getter; -@AllArgsConstructor @Getter public class ChannelCreateDto { private String channelName; private String nickname; + + public ChannelCreateDto(String channelName, String nickname) { + this.channelName = channelName; + this.nickname = nickname; + } } diff --git a/src/main/java/gdsc/comunity/dto/channel/ChannelJoinRequestDto.java b/src/main/java/gdsc/comunity/dto/channel/ChannelJoinRequestDto.java index 754fd11..f1c36db 100644 --- a/src/main/java/gdsc/comunity/dto/channel/ChannelJoinRequestDto.java +++ b/src/main/java/gdsc/comunity/dto/channel/ChannelJoinRequestDto.java @@ -1,13 +1,18 @@ package gdsc.comunity.dto.channel; -import lombok.AllArgsConstructor; import lombok.Getter; -@AllArgsConstructor @Getter public class ChannelJoinRequestDto { Long id; Long userId; Long channelId; String nickname; + + public ChannelJoinRequestDto(Long id, Long userId, Long channelId, String nickname) { + this.id = id; + this.userId = userId; + this.channelId = channelId; + this.nickname = nickname; + } } diff --git a/src/main/java/gdsc/comunity/dto/channel/ChannelNicknameDto.java b/src/main/java/gdsc/comunity/dto/channel/ChannelNicknameDto.java index c2758e7..8f37d2c 100644 --- a/src/main/java/gdsc/comunity/dto/channel/ChannelNicknameDto.java +++ b/src/main/java/gdsc/comunity/dto/channel/ChannelNicknameDto.java @@ -1,11 +1,14 @@ package gdsc.comunity.dto.channel; -import lombok.AllArgsConstructor; import lombok.Getter; -@AllArgsConstructor @Getter public class ChannelNicknameDto { private String nickname; private Long channelId; + + public ChannelNicknameDto(String nickname, Long channelId) { + this.nickname = nickname; + this.channelId = channelId; + } } diff --git a/src/main/java/gdsc/comunity/dto/chat/Chatting.java b/src/main/java/gdsc/comunity/dto/chat/Chatting.java index 3008adc..1af009e 100644 --- a/src/main/java/gdsc/comunity/dto/chat/Chatting.java +++ b/src/main/java/gdsc/comunity/dto/chat/Chatting.java @@ -2,11 +2,9 @@ import gdsc.comunity.entity.channel.Channel; import gdsc.comunity.entity.chat.ChatLog; -import lombok.AllArgsConstructor; import java.time.LocalDateTime; -@AllArgsConstructor public class Chatting { public final String message; public final String senderNickname; @@ -20,4 +18,10 @@ public ChatLog toEntity(Channel channel, Long senderId) { .sendTime(time) .build(); } + + public Chatting(String message, String senderNickname, LocalDateTime time) { + this.message = message; + this.senderNickname = senderNickname; + this.time = time; + } } diff --git a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java index ab75bf7..46cb72a 100644 --- a/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java +++ b/src/test/java/gdsc/comunity/service/channel/ChannelServiceImplTest.java @@ -35,16 +35,20 @@ @TestMethodOrder(MethodOrderer.MethodName.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class ChannelServiceImplTest { + private final ChannelServiceImpl channelService; + private final UserRepository userRepository; + private final ChannelRepository channelRepository; + private final UserChannelJpaRepository userChannelJpaRepository; + private final ChannelJoinRequestRepository channelJoinRequestRepository; + @Autowired - private ChannelServiceImpl channelService; - @Autowired - private UserRepository userRepository; - @Autowired - private ChannelRepository channelRepository; - @Autowired - private UserChannelJpaRepository userChannelJpaRepository; - @Autowired - private ChannelJoinRequestRepository channelJoinRequestRepository; + public ChannelServiceImplTest(ChannelServiceImpl channelService, UserRepository userRepository, ChannelRepository channelRepository, UserChannelJpaRepository userChannelJpaRepository, ChannelJoinRequestRepository channelJoinRequestRepository) { + this.channelService = channelService; + this.userRepository = userRepository; + this.channelRepository = channelRepository; + this.userChannelJpaRepository = userChannelJpaRepository; + this.channelJoinRequestRepository = channelJoinRequestRepository; + } @Test @DisplayName("채널 생성 성공")