From eeb6d8419072a9de33d77dd22b1d7494bff0706d Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 13:36:21 +0900 Subject: [PATCH 01/70] =?UTF-8?q?feat:=20[RoomController]=20=EB=B0=A9=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=9A=94=EC=B2=AD=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20endpoint=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Body의 방 설정 정보(RoomSettings)를 참고하여 새로운 방을 생성합니다. --- .../youtogether/room/dto/RoomSettings.java | 23 +++++++++++++++++++ .../room/presentation/RoomController.java | 18 +++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 src/main/java/site/youtogether/room/dto/RoomSettings.java create mode 100644 src/main/java/site/youtogether/room/presentation/RoomController.java diff --git a/src/main/java/site/youtogether/room/dto/RoomSettings.java b/src/main/java/site/youtogether/room/dto/RoomSettings.java new file mode 100644 index 0000000..2697e4c --- /dev/null +++ b/src/main/java/site/youtogether/room/dto/RoomSettings.java @@ -0,0 +1,23 @@ +package site.youtogether.room.dto; + +import org.hibernate.validator.constraints.Range; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.Getter; + +@Getter +public class RoomSettings { + + @NotBlank + @Size(min = 1, max = 30) + private String title; + + @Range(min = 2, max = 10) + private int capacity; + + @Pattern(regexp = "^[0-9a-zA-Z]{5,10}$") + private String password; + +} diff --git a/src/main/java/site/youtogether/room/presentation/RoomController.java b/src/main/java/site/youtogether/room/presentation/RoomController.java new file mode 100644 index 0000000..63ddb4e --- /dev/null +++ b/src/main/java/site/youtogether/room/presentation/RoomController.java @@ -0,0 +1,18 @@ +package site.youtogether.room.presentation; + +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import jakarta.validation.Valid; +import site.youtogether.room.dto.RoomSettings; + +@RestController +public class RoomController { + + @PostMapping("/room") + public String createRoom(@Valid @RequestBody RoomSettings roomSettings) { + return "test success"; + } + +} From 87f70ca7ae82137008f4eb58cbe8aaeef9ce15bd Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 14:33:36 +0900 Subject: [PATCH 02/70] =?UTF-8?q?fix:=20[RoomController]=20=EB=B0=A9=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=9A=94=EC=B2=AD=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20endpoint=20path=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit room → rooms --- .../java/site/youtogether/room/presentation/RoomController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/site/youtogether/room/presentation/RoomController.java b/src/main/java/site/youtogether/room/presentation/RoomController.java index 63ddb4e..f17cc61 100644 --- a/src/main/java/site/youtogether/room/presentation/RoomController.java +++ b/src/main/java/site/youtogether/room/presentation/RoomController.java @@ -10,7 +10,7 @@ @RestController public class RoomController { - @PostMapping("/room") + @PostMapping("/rooms") public String createRoom(@Valid @RequestBody RoomSettings roomSettings) { return "test success"; } From 30195fc00facbcd023d9cb426190aaa218f32d1a Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 14:35:31 +0900 Subject: [PATCH 03/70] =?UTF-8?q?feat:=20[RoomStorage]=20Request=20IP?= =?UTF-8?q?=EC=99=80=20Room=EC=9D=98=20mapping=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EB=A5=BC=20=EC=A0=80=EC=9E=A5=ED=95=98=EB=8A=94=20storage=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../youtogether/room/storage/RoomStorage.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/site/youtogether/room/storage/RoomStorage.java diff --git a/src/main/java/site/youtogether/room/storage/RoomStorage.java b/src/main/java/site/youtogether/room/storage/RoomStorage.java new file mode 100644 index 0000000..750eaad --- /dev/null +++ b/src/main/java/site/youtogether/room/storage/RoomStorage.java @@ -0,0 +1,19 @@ +package site.youtogether.room.storage; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.springframework.stereotype.Component; + +import site.youtogether.room.Room; + +@Component +public class RoomStorage { + + private final Map roomStorage = new ConcurrentHashMap<>(); + + public boolean existsByAddress(String address) { + return roomStorage.containsKey(address); + } + +} From 89ed5b739b5069b7ee6b7a57a0c386214fda8533 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 14:37:41 +0900 Subject: [PATCH 04/70] =?UTF-8?q?feat:=20[HostingRestrictionInterceptor]?= =?UTF-8?q?=20=EB=B0=A9=20=EC=83=9D=EC=84=B1=EC=9D=84=20=EC=A0=9C=ED=95=9C?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=9D=B8=ED=84=B0=EC=85=89=ED=84=B0=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 각 IP는 최대 1개의 방을 hosting 할 수 있습니다. --- .../HostingRestrictionInterceptor.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/main/java/site/youtogether/interceptor/HostingRestrictionInterceptor.java diff --git a/src/main/java/site/youtogether/interceptor/HostingRestrictionInterceptor.java b/src/main/java/site/youtogether/interceptor/HostingRestrictionInterceptor.java new file mode 100644 index 0000000..504c805 --- /dev/null +++ b/src/main/java/site/youtogether/interceptor/HostingRestrictionInterceptor.java @@ -0,0 +1,37 @@ +package site.youtogether.interceptor; + +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import site.youtogether.room.storage.RoomStorage; + +@Component +@RequiredArgsConstructor +public class HostingRestrictionInterceptor implements HandlerInterceptor { + + private final RoomStorage roomStorage; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String address = request.getLocalAddr(); + + if (isRoomCreationRequest(request) && isAlreadyHosting(address)) { + return false; + } + + return true; + } + + private boolean isRoomCreationRequest(HttpServletRequest request) { + return request.getMethod().equals(HttpMethod.POST.name()); + } + + private boolean isAlreadyHosting(String address) { + return roomStorage.existsByAddress(address); + } + +} From b37cd0bd3ae7f3f03e90561583641efed80cab86 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 14:38:08 +0900 Subject: [PATCH 05/70] =?UTF-8?q?feat:=20[WebConfig]=20=EB=B0=A9=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9D=84=20=EC=A0=9C=ED=95=9C=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EC=9D=B8=ED=84=B0=EC=85=89=ED=84=B0=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../site/youtogether/config/WebConfig.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/java/site/youtogether/config/WebConfig.java diff --git a/src/main/java/site/youtogether/config/WebConfig.java b/src/main/java/site/youtogether/config/WebConfig.java new file mode 100644 index 0000000..1adc99e --- /dev/null +++ b/src/main/java/site/youtogether/config/WebConfig.java @@ -0,0 +1,22 @@ +package site.youtogether.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import lombok.RequiredArgsConstructor; +import site.youtogether.interceptor.HostingRestrictionInterceptor; + +@Configuration +@RequiredArgsConstructor +public class WebConfig implements WebMvcConfigurer { + + private final HostingRestrictionInterceptor hostingRestrictionInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(hostingRestrictionInterceptor) + .addPathPatterns("/rooms"); + } + +} From 9910f82aa2ef268ef6582b1ee5376d1fe2c3bff3 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 16:46:35 +0900 Subject: [PATCH 06/70] =?UTF-8?q?feat:=20[Resolver]=20Address=20=EC=95=A0?= =?UTF-8?q?=EB=84=88=ED=85=8C=EC=9D=B4=EC=85=98=EC=9D=84=20=ED=86=B5?= =?UTF-8?q?=ED=95=B4=20IP=EB=A5=BC=20=EC=A0=84=EB=8B=AC=ED=95=98=EB=8A=94?= =?UTF-8?q?=20AddressResolver=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../site/youtogether/resolver/Address.java | 11 +++++++ .../resolver/AddressArgumentResolver.java | 32 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 src/main/java/site/youtogether/resolver/Address.java create mode 100644 src/main/java/site/youtogether/resolver/AddressArgumentResolver.java diff --git a/src/main/java/site/youtogether/resolver/Address.java b/src/main/java/site/youtogether/resolver/Address.java new file mode 100644 index 0000000..acc6793 --- /dev/null +++ b/src/main/java/site/youtogether/resolver/Address.java @@ -0,0 +1,11 @@ +package site.youtogether.resolver; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface Address { +} diff --git a/src/main/java/site/youtogether/resolver/AddressArgumentResolver.java b/src/main/java/site/youtogether/resolver/AddressArgumentResolver.java new file mode 100644 index 0000000..0786da7 --- /dev/null +++ b/src/main/java/site/youtogether/resolver/AddressArgumentResolver.java @@ -0,0 +1,32 @@ +package site.youtogether.resolver; + +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +import jakarta.servlet.http.HttpServletRequest; + +@Component +public class AddressArgumentResolver implements HandlerMethodArgumentResolver { + + @Override + public boolean supportsParameter(MethodParameter parameter) { + boolean hasAddressAnnotation = parameter.hasParameterAnnotation(Address.class); + boolean isStringType = String.class.isAssignableFrom(parameter.getParameterType()); + + return hasAddressAnnotation && isStringType; + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, + WebDataBinderFactory binderFactory) throws Exception { + HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); + + assert request != null; + return request.getLocalAddr(); + } + +} From 383a19be6408aa4fc805e7384c0545df5eb36da2 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 16:49:04 +0900 Subject: [PATCH 07/70] =?UTF-8?q?feat:=20[Util]=20=EB=9E=9C=EB=8D=A4?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=9E=84=EC=9D=98=EC=9D=98=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=EB=A5=BC=20=EB=8F=84=EC=B6=9C=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EC=9C=A0=ED=8B=B8=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../site/youtogether/util/RandomUtils.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/main/java/site/youtogether/util/RandomUtils.java diff --git a/src/main/java/site/youtogether/util/RandomUtils.java b/src/main/java/site/youtogether/util/RandomUtils.java new file mode 100644 index 0000000..a3f7ba1 --- /dev/null +++ b/src/main/java/site/youtogether/util/RandomUtils.java @@ -0,0 +1,41 @@ +package site.youtogether.util; + +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class RandomUtils { + + /** + * generate random room code + * length is 10 + * using a-z A-Z 0-9 + */ + public static String generateRoomCode() { + String randomString = UUID.randomUUID().toString().replaceAll("-", ""); + + return randomString.substring(0, 10); + } + + /** + * generate random user nickname + * sample list size is 20 + */ + public static String generateUserNickname() { + List samples = List.of( + "MysticTiger", "SilverPhoenix", "ElectricWanderer", "CrimsonDragon", "EmeraldSpecter", + "MidnightRider", "VelvetWhisperer", "CosmicStrider", "SolarGoddess", "ArcticShadow", + "EnigmaticSphinx", "ScarletSorcerer", "CelestialWatcher", "LunarJester", "SapphireDreamer", + "GoldenGlider", "CrimsonFalcon", "EchoingWhisper", "EmberPhoenix", "RadiantRebel" + ); + + int randomIndex = ThreadLocalRandom.current().nextInt(samples.size()); + + return samples.get(randomIndex); + } + +} From d08ba10774a87910fd15765db8e5cd8ec4e49c6e Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 16:50:05 +0900 Subject: [PATCH 08/70] =?UTF-8?q?feat:=20[WebConfig]=20IP=EB=A5=BC=20?= =?UTF-8?q?=EC=A0=84=EB=8B=AC=ED=95=98=EB=8A=94=20Resolver=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/config/WebConfig.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/site/youtogether/config/WebConfig.java b/src/main/java/site/youtogether/config/WebConfig.java index 1adc99e..9afbe58 100644 --- a/src/main/java/site/youtogether/config/WebConfig.java +++ b/src/main/java/site/youtogether/config/WebConfig.java @@ -1,17 +1,22 @@ package site.youtogether.config; +import java.util.List; + import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import lombok.RequiredArgsConstructor; import site.youtogether.interceptor.HostingRestrictionInterceptor; +import site.youtogether.resolver.AddressArgumentResolver; @Configuration @RequiredArgsConstructor public class WebConfig implements WebMvcConfigurer { private final HostingRestrictionInterceptor hostingRestrictionInterceptor; + private final AddressArgumentResolver addressArgumentResolver; @Override public void addInterceptors(InterceptorRegistry registry) { @@ -19,4 +24,9 @@ public void addInterceptors(InterceptorRegistry registry) { .addPathPatterns("/rooms"); } + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(addressArgumentResolver); + } + } From a456647e2580d3cd0dab1676458e3dd3c8a54f58 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 16:51:00 +0900 Subject: [PATCH 09/70] =?UTF-8?q?feat:=20[User]=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=9E=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/user/User.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/main/java/site/youtogether/user/User.java diff --git a/src/main/java/site/youtogether/user/User.java b/src/main/java/site/youtogether/user/User.java new file mode 100644 index 0000000..b2d8712 --- /dev/null +++ b/src/main/java/site/youtogether/user/User.java @@ -0,0 +1,11 @@ +package site.youtogether.user; + +import lombok.Builder; + +public record User(String address, String nickname, Role role) { + + @Builder + public User { + } + +} From c5fed4dff93cb0f790662dcd334636fb79da0bc8 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 16:52:07 +0900 Subject: [PATCH 10/70] =?UTF-8?q?feat:=20[Role]=20=EA=B6=8C=ED=95=9C=20Enu?= =?UTF-8?q?m=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/user/Role.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/site/youtogether/user/Role.java diff --git a/src/main/java/site/youtogether/user/Role.java b/src/main/java/site/youtogether/user/Role.java new file mode 100644 index 0000000..a1dc456 --- /dev/null +++ b/src/main/java/site/youtogether/user/Role.java @@ -0,0 +1,7 @@ +package site.youtogether.user; + +public enum Role { + + HOST, MANAGER, EDITOR, GUEST, VIEWER + +} From 08a193db61f314250f05d146184ee06a0f3c247b Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 16:52:25 +0900 Subject: [PATCH 11/70] =?UTF-8?q?feat:=20[Video]=20=EC=98=81=EC=83=81=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/video/Video.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/main/java/site/youtogether/video/Video.java diff --git a/src/main/java/site/youtogether/video/Video.java b/src/main/java/site/youtogether/video/Video.java new file mode 100644 index 0000000..6d16b07 --- /dev/null +++ b/src/main/java/site/youtogether/video/Video.java @@ -0,0 +1,11 @@ +package site.youtogether.video; + +import lombok.Builder; + +public record Video(String id, String title, String channel, String thumbnail) { + + @Builder + public Video { + } + +} From e8b6d4696c82eb20c26e431f20a4677eaacb880e Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 16:56:34 +0900 Subject: [PATCH 12/70] =?UTF-8?q?feat:=20[Room]=20=EB=B0=A9=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/room/Room.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/main/java/site/youtogether/room/Room.java diff --git a/src/main/java/site/youtogether/room/Room.java b/src/main/java/site/youtogether/room/Room.java new file mode 100644 index 0000000..bc9e7ab --- /dev/null +++ b/src/main/java/site/youtogether/room/Room.java @@ -0,0 +1,35 @@ +package site.youtogether.room; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import lombok.Builder; +import lombok.Getter; +import site.youtogether.user.User; +import site.youtogether.util.RandomUtils; +import site.youtogether.video.Video; + +@Getter +public class Room { + + private final String code; + private final String title; + private int capacity; + private String password; + private final Map participants = new ConcurrentHashMap<>(); + private final Map playlist = new LinkedHashMap<>(); + + @Builder + public Room(String title, int capacity, String password) { + this.code = RandomUtils.generateRoomCode(); + this.title = title; + this.capacity = capacity; + this.password = password; + } + + public void addParticipant(String address, User user) { + participants.put(address, user); + } + +} From cedca1766ef527a41fb95f34367f5576ad3aab13 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 16:57:38 +0900 Subject: [PATCH 13/70] =?UTF-8?q?feat:=20[RoomStorage]=20=EB=B0=A9=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=20=EB=B0=8F=20=EC=82=AD=EC=A0=9C=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/site/youtogether/room/storage/RoomStorage.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/site/youtogether/room/storage/RoomStorage.java b/src/main/java/site/youtogether/room/storage/RoomStorage.java index 750eaad..42a65f1 100644 --- a/src/main/java/site/youtogether/room/storage/RoomStorage.java +++ b/src/main/java/site/youtogether/room/storage/RoomStorage.java @@ -16,4 +16,12 @@ public boolean existsByAddress(String address) { return roomStorage.containsKey(address); } + public void save(String address, Room room) { + roomStorage.put(address, room); + } + + public void remove(String address) { + roomStorage.remove(address); + } + } From f8deeb528cf8ad7f1db20160304be7563c01d126 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 16:58:41 +0900 Subject: [PATCH 14/70] =?UTF-8?q?feat:=20[RoomService]=20=EB=B0=A9=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=8B=A8=EA=B3=84=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 새로운 방 생성에 성공하면 room code를 반환합니다. --- .../room/application/RoomService.java | 46 +++++++++++++++++++ .../site/youtogether/room/dto/RoomCode.java | 15 ++++++ 2 files changed, 61 insertions(+) create mode 100644 src/main/java/site/youtogether/room/application/RoomService.java create mode 100644 src/main/java/site/youtogether/room/dto/RoomCode.java diff --git a/src/main/java/site/youtogether/room/application/RoomService.java b/src/main/java/site/youtogether/room/application/RoomService.java new file mode 100644 index 0000000..2f2fe19 --- /dev/null +++ b/src/main/java/site/youtogether/room/application/RoomService.java @@ -0,0 +1,46 @@ +package site.youtogether.room.application; + +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; +import site.youtogether.room.Room; +import site.youtogether.room.dto.RoomCode; +import site.youtogether.room.dto.RoomSettings; +import site.youtogether.room.storage.RoomStorage; +import site.youtogether.user.Role; +import site.youtogether.user.User; +import site.youtogether.util.RandomUtils; + +@Service +@RequiredArgsConstructor +public class RoomService { + + private final RoomStorage roomStorage; + + public RoomCode create(String address, RoomSettings roomSettings) { + Room room = createRoom(roomSettings); + User host = createHost(room, address); + room.addParticipant(address, host); + + roomStorage.save(address, room); + + return new RoomCode(room); + } + + private Room createRoom(RoomSettings roomSettings) { + return Room.builder() + .title(roomSettings.getTitle()) + .capacity(roomSettings.getCapacity()) + .password(roomSettings.getPassword()) + .build(); + } + + private User createHost(Room room, String address) { + return User.builder() + .address(address) + .nickname(RandomUtils.generateUserNickname()) + .role(Role.HOST) + .build(); + } + +} diff --git a/src/main/java/site/youtogether/room/dto/RoomCode.java b/src/main/java/site/youtogether/room/dto/RoomCode.java new file mode 100644 index 0000000..44c8cbb --- /dev/null +++ b/src/main/java/site/youtogether/room/dto/RoomCode.java @@ -0,0 +1,15 @@ +package site.youtogether.room.dto; + +import lombok.Getter; +import site.youtogether.room.Room; + +@Getter +public class RoomCode { + + private final String roomCode; + + public RoomCode(Room room) { + this.roomCode = room.getCode(); + } + +} From 17c064daa994dedf5f44fcbad3340f801d2e0afa Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 16:59:11 +0900 Subject: [PATCH 15/70] =?UTF-8?q?feat:=20[RoomController]=20=EB=B0=A9=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=9A=94=EC=B2=AD=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EC=9D=91=EB=8B=B5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../youtogether/room/presentation/RoomController.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/site/youtogether/room/presentation/RoomController.java b/src/main/java/site/youtogether/room/presentation/RoomController.java index f17cc61..bedf0de 100644 --- a/src/main/java/site/youtogether/room/presentation/RoomController.java +++ b/src/main/java/site/youtogether/room/presentation/RoomController.java @@ -5,14 +5,21 @@ import org.springframework.web.bind.annotation.RestController; import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import site.youtogether.resolver.Address; +import site.youtogether.room.application.RoomService; +import site.youtogether.room.dto.RoomCode; import site.youtogether.room.dto.RoomSettings; @RestController +@RequiredArgsConstructor public class RoomController { + private final RoomService roomService; + @PostMapping("/rooms") - public String createRoom(@Valid @RequestBody RoomSettings roomSettings) { - return "test success"; + public RoomCode createRoom(@Address String address, @Valid @RequestBody RoomSettings roomSettings) { + return roomService.create(address, roomSettings); } } From d241c2793bdc7bd254d5a38856723d479f2c6735 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 17:29:42 +0900 Subject: [PATCH 16/70] =?UTF-8?q?feat:=20[ApiResponse]=20=ED=86=B5?= =?UTF-8?q?=EC=9D=BC=EB=90=9C=20=EC=9D=91=EB=8B=B5=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=ED=98=95=EC=8B=9D=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../youtogether/util/api/ApiResponse.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/main/java/site/youtogether/util/api/ApiResponse.java diff --git a/src/main/java/site/youtogether/util/api/ApiResponse.java b/src/main/java/site/youtogether/util/api/ApiResponse.java new file mode 100644 index 0000000..5ef58b7 --- /dev/null +++ b/src/main/java/site/youtogether/util/api/ApiResponse.java @@ -0,0 +1,32 @@ +package site.youtogether.util.api; + +import org.springframework.http.HttpStatus; + +import lombok.Getter; + +@Getter +public class ApiResponse { + + private final int code; + private final String status; + private final T data; + + public ApiResponse(HttpStatus status, T data) { + this.code = status.value(); + this.status = status.getReasonPhrase(); + this.data = data; + } + + public static ApiResponse of(HttpStatus status, T data) { + return new ApiResponse<>(status, data); + } + + public static ApiResponse ok(T data) { + return new ApiResponse<>(HttpStatus.OK, data); + } + + public static ApiResponse created(T data) { + return new ApiResponse<>(HttpStatus.CREATED, data); + } + +} From 3ab331edcbc773945a41debe649148858fa1c017 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 17:30:17 +0900 Subject: [PATCH 17/70] =?UTF-8?q?feat:=20[Exception]=20BindException=20Han?= =?UTF-8?q?dler=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/GlobalExceptionHandler.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/main/java/site/youtogether/exception/GlobalExceptionHandler.java diff --git a/src/main/java/site/youtogether/exception/GlobalExceptionHandler.java b/src/main/java/site/youtogether/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..ca51d1b --- /dev/null +++ b/src/main/java/site/youtogether/exception/GlobalExceptionHandler.java @@ -0,0 +1,39 @@ +package site.youtogether.exception; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.context.support.DefaultMessageSourceResolvable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindException; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import site.youtogether.util.api.ApiResponse; + +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(BindException.class) + public ResponseEntity> handleBindException(BindException exception) { + return ResponseEntity.badRequest().body( + ApiResponse.of(HttpStatus.BAD_REQUEST, + exception.getBindingResult().getFieldErrors().stream() + .collect(Collectors.groupingBy(FieldError::getField)) + .entrySet().stream() + .map(error -> { + Map fieldError = new HashMap<>(); + fieldError.put("field", error.getKey()); + fieldError.put("message", error.getValue().stream() + .map(DefaultMessageSourceResolvable::getDefaultMessage) + .collect(Collectors.joining(", "))); + return fieldError; + }) + ) + ); + } + +} From cf57508f8a3b11c13d6c8b285d1e7b92e41f1bf9 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 17:30:49 +0900 Subject: [PATCH 18/70] =?UTF-8?q?modify:=20[RoomController]=20=EB=B0=A9=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=9A=94=EC=B2=AD=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EC=9D=91=EB=8B=B5=20=ED=98=95=EC=8B=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../site/youtogether/room/presentation/RoomController.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/site/youtogether/room/presentation/RoomController.java b/src/main/java/site/youtogether/room/presentation/RoomController.java index bedf0de..6f72554 100644 --- a/src/main/java/site/youtogether/room/presentation/RoomController.java +++ b/src/main/java/site/youtogether/room/presentation/RoomController.java @@ -1,5 +1,7 @@ package site.youtogether.room.presentation; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @@ -10,6 +12,7 @@ import site.youtogether.room.application.RoomService; import site.youtogether.room.dto.RoomCode; import site.youtogether.room.dto.RoomSettings; +import site.youtogether.util.api.ApiResponse; @RestController @RequiredArgsConstructor @@ -18,8 +21,8 @@ public class RoomController { private final RoomService roomService; @PostMapping("/rooms") - public RoomCode createRoom(@Address String address, @Valid @RequestBody RoomSettings roomSettings) { - return roomService.create(address, roomSettings); + public ResponseEntity> createRoom(@Address String address, @Valid @RequestBody RoomSettings roomSettings) { + return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse.created(roomService.create(address, roomSettings))); } } From 66c82630858d295a27f1fa0f1164d31f8b05b2ac Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 17:35:00 +0900 Subject: [PATCH 19/70] =?UTF-8?q?modify:=20[Room]=20=EB=B0=A9=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=EA=B0=92=20=EB=B3=80=EA=B2=BD=20=EA=B0=80=EB=8A=A5?= =?UTF-8?q?=EC=84=B1=20=EB=B0=B0=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/room/Room.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/site/youtogether/room/Room.java b/src/main/java/site/youtogether/room/Room.java index bc9e7ab..17bd73d 100644 --- a/src/main/java/site/youtogether/room/Room.java +++ b/src/main/java/site/youtogether/room/Room.java @@ -15,8 +15,8 @@ public class Room { private final String code; private final String title; - private int capacity; - private String password; + private final int capacity; + private final String password; private final Map participants = new ConcurrentHashMap<>(); private final Map playlist = new LinkedHashMap<>(); From 80502622627978f5f1ea6f88575f23e96bc273a1 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 17:45:24 +0900 Subject: [PATCH 20/70] =?UTF-8?q?modify:=20[RoomService]=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EB=A7=A4=EA=B0=9C=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/site/youtogether/room/application/RoomService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/site/youtogether/room/application/RoomService.java b/src/main/java/site/youtogether/room/application/RoomService.java index 2f2fe19..0cc54d5 100644 --- a/src/main/java/site/youtogether/room/application/RoomService.java +++ b/src/main/java/site/youtogether/room/application/RoomService.java @@ -19,7 +19,7 @@ public class RoomService { public RoomCode create(String address, RoomSettings roomSettings) { Room room = createRoom(roomSettings); - User host = createHost(room, address); + User host = createHost(address); room.addParticipant(address, host); roomStorage.save(address, room); @@ -35,7 +35,7 @@ private Room createRoom(RoomSettings roomSettings) { .build(); } - private User createHost(Room room, String address) { + private User createHost(String address) { return User.builder() .address(address) .nickname(RandomUtils.generateUserNickname()) From 781fe13f8fe2df8f667731a1e9f13443d8bd7db1 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 18:09:03 +0900 Subject: [PATCH 21/70] =?UTF-8?q?build:=20spring=20boot=20starter=20data?= =?UTF-8?q?=20redis=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/build.gradle b/build.gradle index 279ab39..a5af9b9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,38 +1,39 @@ plugins { - id 'java' - id 'org.springframework.boot' version '3.2.3' - id 'io.spring.dependency-management' version '1.1.4' + id 'java' + id 'org.springframework.boot' version '3.2.3' + id 'io.spring.dependency-management' version '1.1.4' } group = 'site' version = '0.0.1-SNAPSHOT' java { - sourceCompatibility = '17' + sourceCompatibility = '17' } configurations { - compileOnly { - extendsFrom annotationProcessor - } + compileOnly { + extendsFrom annotationProcessor + } } repositories { - mavenCentral() + mavenCentral() } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'org.springframework.boot:spring-boot-starter-web' - compileOnly 'org.projectlombok:lombok' - annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { - useJUnitPlatform() + useJUnitPlatform() } jar { - enabled = false + enabled = false } From c04bceb8d58aa7c854805c2377263881222e77b4 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 21:04:22 +0900 Subject: [PATCH 22/70] =?UTF-8?q?feat:=20[RedisConfig]=20Redis=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=ED=8C=8C=EC=9D=BC=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../site/youtogether/config/RedisConfig.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/main/java/site/youtogether/config/RedisConfig.java diff --git a/src/main/java/site/youtogether/config/RedisConfig.java b/src/main/java/site/youtogether/config/RedisConfig.java new file mode 100644 index 0000000..ded974f --- /dev/null +++ b/src/main/java/site/youtogether/config/RedisConfig.java @@ -0,0 +1,34 @@ +package site.youtogether.config; + +import org.springframework.boot.autoconfigure.data.redis.RedisProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import lombok.RequiredArgsConstructor; + +@Configuration +@RequiredArgsConstructor +public class RedisConfig { + + private final RedisProperties redisProperties; + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + return new LettuceConnectionFactory(redisProperties.getHost(), redisProperties.getPort()); + } + + @Bean + public RedisTemplate redisStringTemplate() { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory()); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + + return redisTemplate; + } + +} From 44da2ffcae1e85429ee785c1b687a73f0131f7c0 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 21:07:52 +0900 Subject: [PATCH 23/70] =?UTF-8?q?modify:=20[RedisConfig]=20RedisTemplate?= =?UTF-8?q?=EC=9D=98=20Value=EB=A5=BC=20String=20Type=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=A0=9C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/config/RedisConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/site/youtogether/config/RedisConfig.java b/src/main/java/site/youtogether/config/RedisConfig.java index ded974f..34664e1 100644 --- a/src/main/java/site/youtogether/config/RedisConfig.java +++ b/src/main/java/site/youtogether/config/RedisConfig.java @@ -22,8 +22,8 @@ public RedisConnectionFactory redisConnectionFactory() { } @Bean - public RedisTemplate redisStringTemplate() { - RedisTemplate redisTemplate = new RedisTemplate<>(); + public RedisTemplate redisStringTemplate() { + RedisTemplate redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory()); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new StringRedisSerializer()); From 3fffeda753d2e0a185317ed88ccf2ca665237215 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 21:08:31 +0900 Subject: [PATCH 24/70] =?UTF-8?q?feat:=20[RedisStorage]=20RedisTemplate?= =?UTF-8?q?=EC=9D=84=20=EC=82=AC=EC=9A=A9=ED=95=9C=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../room/infrastructure/RedisStorage.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/java/site/youtogether/room/infrastructure/RedisStorage.java diff --git a/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java b/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java new file mode 100644 index 0000000..5a3e957 --- /dev/null +++ b/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java @@ -0,0 +1,33 @@ +package site.youtogether.room.infrastructure; + +import static site.youtogether.util.AppConstants.*; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class RedisStorage { + + private final RedisTemplate redisStringTemplate; + + public Boolean existsInHostingList(String address) { + return redisStringTemplate.opsForSet().isMember(HOSTING_KEY, address); + } + + public Boolean existsInWatchingList(String address) { + return redisStringTemplate.opsForSet().isMember(WATCHING_KEY, address); + } + + public void addHostingAddress(String address) { + redisStringTemplate.opsForSet().add(HOSTING_KEY, address); + } + + public void addParticipant(String roomCode, String address) { + String participantKey = PARTICIPANTS_KEY_PREFIX + roomCode; + redisStringTemplate.opsForSet().add(participantKey, address); + } + +} From 398ec6b8972be973a41cb16b3454972fa42955cd Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 21:09:37 +0900 Subject: [PATCH 25/70] =?UTF-8?q?modify:=20[HostingRestrictionInterceptor]?= =?UTF-8?q?=20repository=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RoomStorage → RedisStorage --- .../interceptor/HostingRestrictionInterceptor.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/site/youtogether/interceptor/HostingRestrictionInterceptor.java b/src/main/java/site/youtogether/interceptor/HostingRestrictionInterceptor.java index 504c805..8338851 100644 --- a/src/main/java/site/youtogether/interceptor/HostingRestrictionInterceptor.java +++ b/src/main/java/site/youtogether/interceptor/HostingRestrictionInterceptor.java @@ -7,19 +7,19 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import site.youtogether.room.storage.RoomStorage; +import site.youtogether.room.infrastructure.RedisStorage; @Component @RequiredArgsConstructor public class HostingRestrictionInterceptor implements HandlerInterceptor { - private final RoomStorage roomStorage; + private final RedisStorage redisStorage; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String address = request.getLocalAddr(); - if (isRoomCreationRequest(request) && isAlreadyHosting(address)) { + if (isRoomCreationRequest(request) && (isAlreadyHosting(address)) || isAlreadyWatching(address)) { return false; } @@ -31,7 +31,11 @@ private boolean isRoomCreationRequest(HttpServletRequest request) { } private boolean isAlreadyHosting(String address) { - return roomStorage.existsByAddress(address); + return redisStorage.existsInHostingList(address); + } + + private boolean isAlreadyWatching(String address) { + return redisStorage.existsInWatchingList(address); } } From 8ff5ded388bbc05725f77838c0c6885da84ba2da Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 21:10:13 +0900 Subject: [PATCH 26/70] =?UTF-8?q?rename:=20RandomUtils=20=E2=86=92=20Rando?= =?UTF-8?q?mUtil?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../site/youtogether/util/{RandomUtils.java => RandomUtil.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/site/youtogether/util/{RandomUtils.java => RandomUtil.java} (97%) diff --git a/src/main/java/site/youtogether/util/RandomUtils.java b/src/main/java/site/youtogether/util/RandomUtil.java similarity index 97% rename from src/main/java/site/youtogether/util/RandomUtils.java rename to src/main/java/site/youtogether/util/RandomUtil.java index a3f7ba1..ee55342 100644 --- a/src/main/java/site/youtogether/util/RandomUtils.java +++ b/src/main/java/site/youtogether/util/RandomUtil.java @@ -8,7 +8,7 @@ import lombok.NoArgsConstructor; @NoArgsConstructor(access = AccessLevel.PRIVATE) -public final class RandomUtils { +public final class RandomUtil { /** * generate random room code From afdfea7d539834eea3dbe221aaf8280065dc020c Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 21:12:17 +0900 Subject: [PATCH 27/70] =?UTF-8?q?modify:=20[RoomStorage]=20RedisTemplate?= =?UTF-8?q?=20=EB=8C=80=EC=8B=A0=20CrudRepository=EB=A5=BC=20=EC=9D=B4?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EB=8A=94=20=EB=B0=A9=EC=8B=9D=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/room/Room.java | 21 ++++++--------- .../room/infrastructure/RoomStorage.java | 11 ++++++++ .../youtogether/room/storage/RoomStorage.java | 27 ------------------- 3 files changed, 19 insertions(+), 40 deletions(-) create mode 100644 src/main/java/site/youtogether/room/infrastructure/RoomStorage.java delete mode 100644 src/main/java/site/youtogether/room/storage/RoomStorage.java diff --git a/src/main/java/site/youtogether/room/Room.java b/src/main/java/site/youtogether/room/Room.java index 17bd73d..3f8ed1c 100644 --- a/src/main/java/site/youtogether/room/Room.java +++ b/src/main/java/site/youtogether/room/Room.java @@ -1,35 +1,30 @@ package site.youtogether.room; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import org.springframework.data.annotation.Id; +import org.springframework.data.redis.core.RedisHash; import lombok.Builder; import lombok.Getter; -import site.youtogether.user.User; -import site.youtogether.util.RandomUtils; -import site.youtogether.video.Video; +import site.youtogether.util.AppConstants; +import site.youtogether.util.RandomUtil; +@RedisHash(value = "room", timeToLive = AppConstants.day) @Getter public class Room { + @Id private final String code; + private final String title; private final int capacity; private final String password; - private final Map participants = new ConcurrentHashMap<>(); - private final Map playlist = new LinkedHashMap<>(); @Builder public Room(String title, int capacity, String password) { - this.code = RandomUtils.generateRoomCode(); + this.code = RandomUtil.generateRoomCode(); this.title = title; this.capacity = capacity; this.password = password; } - public void addParticipant(String address, User user) { - participants.put(address, user); - } - } diff --git a/src/main/java/site/youtogether/room/infrastructure/RoomStorage.java b/src/main/java/site/youtogether/room/infrastructure/RoomStorage.java new file mode 100644 index 0000000..8ab5572 --- /dev/null +++ b/src/main/java/site/youtogether/room/infrastructure/RoomStorage.java @@ -0,0 +1,11 @@ +package site.youtogether.room.infrastructure; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import site.youtogether.room.Room; + +@Repository +public interface RoomStorage extends CrudRepository { + +} diff --git a/src/main/java/site/youtogether/room/storage/RoomStorage.java b/src/main/java/site/youtogether/room/storage/RoomStorage.java deleted file mode 100644 index 42a65f1..0000000 --- a/src/main/java/site/youtogether/room/storage/RoomStorage.java +++ /dev/null @@ -1,27 +0,0 @@ -package site.youtogether.room.storage; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.springframework.stereotype.Component; - -import site.youtogether.room.Room; - -@Component -public class RoomStorage { - - private final Map roomStorage = new ConcurrentHashMap<>(); - - public boolean existsByAddress(String address) { - return roomStorage.containsKey(address); - } - - public void save(String address, Room room) { - roomStorage.put(address, room); - } - - public void remove(String address) { - roomStorage.remove(address); - } - -} From c5888326085ce97740075904d717e83f3b1c0c00 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 21:12:28 +0900 Subject: [PATCH 28/70] =?UTF-8?q?modify:=20[UserStorage]=20RedisTemplate?= =?UTF-8?q?=20=EB=8C=80=EC=8B=A0=20CrudRepository=EB=A5=BC=20=EC=9D=B4?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EB=8A=94=20=EB=B0=A9=EC=8B=9D=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/user/User.java | 20 +++++++++++++++++-- .../user/infrastructure/UserStorage.java | 11 ++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 src/main/java/site/youtogether/user/infrastructure/UserStorage.java diff --git a/src/main/java/site/youtogether/user/User.java b/src/main/java/site/youtogether/user/User.java index b2d8712..6df6953 100644 --- a/src/main/java/site/youtogether/user/User.java +++ b/src/main/java/site/youtogether/user/User.java @@ -1,11 +1,27 @@ package site.youtogether.user; +import org.springframework.data.annotation.Id; +import org.springframework.data.redis.core.RedisHash; + import lombok.Builder; +import lombok.Getter; +import site.youtogether.util.AppConstants; + +@RedisHash(value = "user", timeToLive = AppConstants.day) +@Getter +public class User { + + @Id + private final String address; -public record User(String address, String nickname, Role role) { + private final String nickname; + private final Role role; @Builder - public User { + public User(String address, String nickname, Role role) { + this.address = address; + this.nickname = nickname; + this.role = role; } } diff --git a/src/main/java/site/youtogether/user/infrastructure/UserStorage.java b/src/main/java/site/youtogether/user/infrastructure/UserStorage.java new file mode 100644 index 0000000..d3b797a --- /dev/null +++ b/src/main/java/site/youtogether/user/infrastructure/UserStorage.java @@ -0,0 +1,11 @@ +package site.youtogether.user.infrastructure; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import site.youtogether.user.User; + +@Repository +public interface UserStorage extends CrudRepository { + +} From 636e26496405b65ceff5a6f71be6414867cb7b4b Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 21:13:40 +0900 Subject: [PATCH 29/70] =?UTF-8?q?feat:=20[AppConstants]=20=EC=83=81?= =?UTF-8?q?=EC=88=98=20=EA=B3=B5=EC=9C=A0=EB=A5=BC=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EC=9C=A0=ED=8B=B8=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/site/youtogether/util/AppConstants.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/main/java/site/youtogether/util/AppConstants.java diff --git a/src/main/java/site/youtogether/util/AppConstants.java b/src/main/java/site/youtogether/util/AppConstants.java new file mode 100644 index 0000000..66fc1fb --- /dev/null +++ b/src/main/java/site/youtogether/util/AppConstants.java @@ -0,0 +1,16 @@ +package site.youtogether.util; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class AppConstants { + + public static final String HOSTING_KEY = "hosting"; + public static final String WATCHING_KEY = "watching"; + public static final String ROOM_KEY_PREFIX = "room:"; + public static final String PARTICIPANTS_KEY_PREFIX = "participants:"; + public static final String USER_KEY_PREFIX = "user:"; + public static final long day = 86_400; + +} From 671f10e3702b6805ee81cf471f08e2c58e10e75f Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 21:14:06 +0900 Subject: [PATCH 30/70] =?UTF-8?q?style:=20=EC=A4=84=EB=B0=94=EA=BF=88=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../site/youtogether/room/presentation/RoomController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/site/youtogether/room/presentation/RoomController.java b/src/main/java/site/youtogether/room/presentation/RoomController.java index 6f72554..afa2c80 100644 --- a/src/main/java/site/youtogether/room/presentation/RoomController.java +++ b/src/main/java/site/youtogether/room/presentation/RoomController.java @@ -22,7 +22,8 @@ public class RoomController { @PostMapping("/rooms") public ResponseEntity> createRoom(@Address String address, @Valid @RequestBody RoomSettings roomSettings) { - return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse.created(roomService.create(address, roomSettings))); + return ResponseEntity.status(HttpStatus.CREATED) + .body(ApiResponse.created(roomService.create(address, roomSettings))); } } From 9c8ba9178e21ca4b3d005db4eef59ec8a1a6ab9e Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 21:15:47 +0900 Subject: [PATCH 31/70] =?UTF-8?q?modify:=20[RoomService]=20repository=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=EB=B0=A9=20=EC=83=9D=EC=84=B1=20=EB=8B=A8=EA=B3=84?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../room/application/RoomService.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/java/site/youtogether/room/application/RoomService.java b/src/main/java/site/youtogether/room/application/RoomService.java index 0cc54d5..1f59bb1 100644 --- a/src/main/java/site/youtogether/room/application/RoomService.java +++ b/src/main/java/site/youtogether/room/application/RoomService.java @@ -6,23 +6,30 @@ import site.youtogether.room.Room; import site.youtogether.room.dto.RoomCode; import site.youtogether.room.dto.RoomSettings; -import site.youtogether.room.storage.RoomStorage; +import site.youtogether.room.infrastructure.RedisStorage; +import site.youtogether.room.infrastructure.RoomStorage; import site.youtogether.user.Role; import site.youtogether.user.User; -import site.youtogether.util.RandomUtils; +import site.youtogether.user.infrastructure.UserStorage; +import site.youtogether.util.RandomUtil; @Service @RequiredArgsConstructor public class RoomService { + private final RedisStorage redisStorage; private final RoomStorage roomStorage; + private final UserStorage userStorage; public RoomCode create(String address, RoomSettings roomSettings) { Room room = createRoom(roomSettings); User host = createHost(address); - room.addParticipant(address, host); - roomStorage.save(address, room); + roomStorage.save(room); + userStorage.save(host); + + redisStorage.addHostingAddress(address); + redisStorage.addParticipant(room.getCode(), address); return new RoomCode(room); } @@ -38,7 +45,7 @@ private Room createRoom(RoomSettings roomSettings) { private User createHost(String address) { return User.builder() .address(address) - .nickname(RandomUtils.generateUserNickname()) + .nickname(RandomUtil.generateUserNickname()) .role(Role.HOST) .build(); } From 386b60907824a34098f428c4e65964f271a1bae4 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 8 Mar 2024 21:17:03 +0900 Subject: [PATCH 32/70] =?UTF-8?q?remove:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20Video=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/video/Video.java | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 src/main/java/site/youtogether/video/Video.java diff --git a/src/main/java/site/youtogether/video/Video.java b/src/main/java/site/youtogether/video/Video.java deleted file mode 100644 index 6d16b07..0000000 --- a/src/main/java/site/youtogether/video/Video.java +++ /dev/null @@ -1,11 +0,0 @@ -package site.youtogether.video; - -import lombok.Builder; - -public record Video(String id, String title, String channel, String thumbnail) { - - @Builder - public Video { - } - -} From e2c9786c713ddc2e683c7f9068e0df96f7597efd Mon Sep 17 00:00:00 2001 From: yeonise Date: Sun, 10 Mar 2024 14:41:49 +0900 Subject: [PATCH 33/70] =?UTF-8?q?remove:=20=EC=9D=B8=ED=84=B0=EC=85=89?= =?UTF-8?q?=ED=84=B0=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../site/youtogether/config/WebConfig.java | 11 +---- .../HostingRestrictionInterceptor.java | 41 ------------------- 2 files changed, 1 insertion(+), 51 deletions(-) delete mode 100644 src/main/java/site/youtogether/interceptor/HostingRestrictionInterceptor.java diff --git a/src/main/java/site/youtogether/config/WebConfig.java b/src/main/java/site/youtogether/config/WebConfig.java index 9afbe58..f49cd9d 100644 --- a/src/main/java/site/youtogether/config/WebConfig.java +++ b/src/main/java/site/youtogether/config/WebConfig.java @@ -4,29 +4,20 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import lombok.RequiredArgsConstructor; -import site.youtogether.interceptor.HostingRestrictionInterceptor; import site.youtogether.resolver.AddressArgumentResolver; @Configuration @RequiredArgsConstructor public class WebConfig implements WebMvcConfigurer { - private final HostingRestrictionInterceptor hostingRestrictionInterceptor; private final AddressArgumentResolver addressArgumentResolver; - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(hostingRestrictionInterceptor) - .addPathPatterns("/rooms"); - } - @Override public void addArgumentResolvers(List resolvers) { resolvers.add(addressArgumentResolver); } - + } diff --git a/src/main/java/site/youtogether/interceptor/HostingRestrictionInterceptor.java b/src/main/java/site/youtogether/interceptor/HostingRestrictionInterceptor.java deleted file mode 100644 index 8338851..0000000 --- a/src/main/java/site/youtogether/interceptor/HostingRestrictionInterceptor.java +++ /dev/null @@ -1,41 +0,0 @@ -package site.youtogether.interceptor; - -import org.springframework.http.HttpMethod; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.HandlerInterceptor; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import site.youtogether.room.infrastructure.RedisStorage; - -@Component -@RequiredArgsConstructor -public class HostingRestrictionInterceptor implements HandlerInterceptor { - - private final RedisStorage redisStorage; - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - String address = request.getLocalAddr(); - - if (isRoomCreationRequest(request) && (isAlreadyHosting(address)) || isAlreadyWatching(address)) { - return false; - } - - return true; - } - - private boolean isRoomCreationRequest(HttpServletRequest request) { - return request.getMethod().equals(HttpMethod.POST.name()); - } - - private boolean isAlreadyHosting(String address) { - return redisStorage.existsInHostingList(address); - } - - private boolean isAlreadyWatching(String address) { - return redisStorage.existsInWatchingList(address); - } - -} From 9e4190b9dc51403c007e9a8dfa9141e1ee1dc1a8 Mon Sep 17 00:00:00 2001 From: yeonise Date: Sun, 10 Mar 2024 15:51:09 +0900 Subject: [PATCH 34/70] =?UTF-8?q?feat:=20CustomException=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=84=A4=EC=A0=95=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/CustomException.java | 17 ++++++++ .../site/youtogether/exception/ErrorType.java | 21 +++++++++ .../exception/GlobalExceptionHandler.java | 43 ++++++++++++------- 3 files changed, 65 insertions(+), 16 deletions(-) create mode 100644 src/main/java/site/youtogether/exception/CustomException.java create mode 100644 src/main/java/site/youtogether/exception/ErrorType.java diff --git a/src/main/java/site/youtogether/exception/CustomException.java b/src/main/java/site/youtogether/exception/CustomException.java new file mode 100644 index 0000000..d491267 --- /dev/null +++ b/src/main/java/site/youtogether/exception/CustomException.java @@ -0,0 +1,17 @@ +package site.youtogether.exception; + +import org.springframework.http.HttpStatus; + +import lombok.Getter; + +@Getter +public class CustomException extends RuntimeException { + + private final HttpStatus status; + + public CustomException(ErrorType errorType) { + super(errorType.getMessage()); + this.status = errorType.getStatus(); + } + +} diff --git a/src/main/java/site/youtogether/exception/ErrorType.java b/src/main/java/site/youtogether/exception/ErrorType.java new file mode 100644 index 0000000..4f60eb3 --- /dev/null +++ b/src/main/java/site/youtogether/exception/ErrorType.java @@ -0,0 +1,21 @@ +package site.youtogether.exception; + +import org.springframework.http.HttpStatus; + +import lombok.Getter; + +@Getter +public enum ErrorType { + + // Room + SINGLE_ROOM_PARTICIPATION_VIOLATION(HttpStatus.BAD_REQUEST, "하나의 방에만 참가할 수 있습니다"); + + private final HttpStatus status; + private final String message; + + ErrorType(HttpStatus status, String message) { + this.status = status; + this.message = message; + } + +} diff --git a/src/main/java/site/youtogether/exception/GlobalExceptionHandler.java b/src/main/java/site/youtogether/exception/GlobalExceptionHandler.java index ca51d1b..8d75cb6 100644 --- a/src/main/java/site/youtogether/exception/GlobalExceptionHandler.java +++ b/src/main/java/site/youtogether/exception/GlobalExceptionHandler.java @@ -1,6 +1,7 @@ package site.youtogether.exception; -import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -19,21 +20,31 @@ public class GlobalExceptionHandler { @ExceptionHandler(BindException.class) public ResponseEntity> handleBindException(BindException exception) { - return ResponseEntity.badRequest().body( - ApiResponse.of(HttpStatus.BAD_REQUEST, - exception.getBindingResult().getFieldErrors().stream() - .collect(Collectors.groupingBy(FieldError::getField)) - .entrySet().stream() - .map(error -> { - Map fieldError = new HashMap<>(); - fieldError.put("field", error.getKey()); - fieldError.put("message", error.getValue().stream() - .map(DefaultMessageSourceResolvable::getDefaultMessage) - .collect(Collectors.joining(", "))); - return fieldError; - }) - ) - ); + return ResponseEntity.badRequest() + .body(ApiResponse.of(HttpStatus.BAD_REQUEST, + exception.getBindingResult().getFieldErrors().stream() + .collect(Collectors.groupingBy(FieldError::getField)) + .entrySet().stream() + .map(error -> { + Map fieldError = new LinkedHashMap<>(); + fieldError.put("type", error.getKey()); + fieldError.put("message", error.getValue().stream() + .map(DefaultMessageSourceResolvable::getDefaultMessage) + .collect(Collectors.joining(", "))); + return fieldError; + }) + ) + ); + } + + @ExceptionHandler(CustomException.class) + public ResponseEntity> handleCustomException(CustomException customException) { + Map error = new LinkedHashMap<>(2); + error.put("type", customException.getClass().getSimpleName()); + error.put("message", customException.getMessage()); + + return ResponseEntity.badRequest() + .body(ApiResponse.of(customException.getStatus(), List.of(error))); } } From 0c078df7676a9f091839ebfa7048519570aff8c8 Mon Sep 17 00:00:00 2001 From: yeonise Date: Sun, 10 Mar 2024 15:51:54 +0900 Subject: [PATCH 35/70] =?UTF-8?q?modify:=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=EC=9D=98=20TimeToLive=20=EA=B0=92=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/room/Room.java | 3 +-- src/main/java/site/youtogether/user/User.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/site/youtogether/room/Room.java b/src/main/java/site/youtogether/room/Room.java index 3f8ed1c..9407a0b 100644 --- a/src/main/java/site/youtogether/room/Room.java +++ b/src/main/java/site/youtogether/room/Room.java @@ -5,10 +5,9 @@ import lombok.Builder; import lombok.Getter; -import site.youtogether.util.AppConstants; import site.youtogether.util.RandomUtil; -@RedisHash(value = "room", timeToLive = AppConstants.day) +@RedisHash(value = "room") @Getter public class Room { diff --git a/src/main/java/site/youtogether/user/User.java b/src/main/java/site/youtogether/user/User.java index 6df6953..23b473b 100644 --- a/src/main/java/site/youtogether/user/User.java +++ b/src/main/java/site/youtogether/user/User.java @@ -5,9 +5,8 @@ import lombok.Builder; import lombok.Getter; -import site.youtogether.util.AppConstants; -@RedisHash(value = "user", timeToLive = AppConstants.day) +@RedisHash(value = "user") @Getter public class User { From 95aa9a2a313c97a965983fd38f841cac083c7607 Mon Sep 17 00:00:00 2001 From: yeonise Date: Sun, 10 Mar 2024 15:52:39 +0900 Subject: [PATCH 36/70] =?UTF-8?q?modify:=20=EC=B0=B8=EA=B0=80=20=EC=A4=91?= =?UTF-8?q?=EC=9D=B8=20IP=20=ED=99=95=EC=9D=B8=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EC=A7=91=ED=95=A9=EC=9D=84=20=ED=95=98=EB=82=98?= =?UTF-8?q?=EB=A1=9C=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../room/infrastructure/RedisStorage.java | 12 ++++-------- .../java/site/youtogether/util/AppConstants.java | 6 ++---- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java b/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java index 5a3e957..8120fbb 100644 --- a/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java +++ b/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java @@ -13,16 +13,12 @@ public class RedisStorage { private final RedisTemplate redisStringTemplate; - public Boolean existsInHostingList(String address) { - return redisStringTemplate.opsForSet().isMember(HOSTING_KEY, address); + public Boolean existsInActiveAddress(String address) { + return redisStringTemplate.opsForSet().isMember(ACTIVE_ADDRESS_KEY, address); } - public Boolean existsInWatchingList(String address) { - return redisStringTemplate.opsForSet().isMember(WATCHING_KEY, address); - } - - public void addHostingAddress(String address) { - redisStringTemplate.opsForSet().add(HOSTING_KEY, address); + public void addActiveAddress(String address) { + redisStringTemplate.opsForSet().add(ACTIVE_ADDRESS_KEY, address); } public void addParticipant(String roomCode, String address) { diff --git a/src/main/java/site/youtogether/util/AppConstants.java b/src/main/java/site/youtogether/util/AppConstants.java index 66fc1fb..1eec7f4 100644 --- a/src/main/java/site/youtogether/util/AppConstants.java +++ b/src/main/java/site/youtogether/util/AppConstants.java @@ -6,11 +6,9 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class AppConstants { - public static final String HOSTING_KEY = "hosting"; - public static final String WATCHING_KEY = "watching"; + public static final String ACTIVE_ADDRESS_KEY = "active"; public static final String ROOM_KEY_PREFIX = "room:"; - public static final String PARTICIPANTS_KEY_PREFIX = "participants:"; public static final String USER_KEY_PREFIX = "user:"; - public static final long day = 86_400; + public static final String PARTICIPANTS_KEY_PREFIX = "participants:"; } From f756962f3eccf1c1f4ba9b77a33ef11148964329 Mon Sep 17 00:00:00 2001 From: yeonise Date: Sun, 10 Mar 2024 15:53:49 +0900 Subject: [PATCH 37/70] =?UTF-8?q?modify:=20=EB=B0=A9=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=EA=B0=80=EB=8A=A5=20=EC=97=AC=EB=B6=80=EB=A5=BC=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=ED=95=98=EB=8A=94=20=EB=8B=A8=EA=B3=84=EB=A5=BC=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=20=EB=A0=88=EC=9D=B4=EC=96=B4?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=88=98=ED=96=89=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Interceptor → Service Layer --- ...leRoomParticipationViolationException.java | 12 ++++++++ .../room/application/RoomService.java | 30 +++++++++---------- 2 files changed, 26 insertions(+), 16 deletions(-) create mode 100644 src/main/java/site/youtogether/exception/room/SingleRoomParticipationViolationException.java diff --git a/src/main/java/site/youtogether/exception/room/SingleRoomParticipationViolationException.java b/src/main/java/site/youtogether/exception/room/SingleRoomParticipationViolationException.java new file mode 100644 index 0000000..47834bf --- /dev/null +++ b/src/main/java/site/youtogether/exception/room/SingleRoomParticipationViolationException.java @@ -0,0 +1,12 @@ +package site.youtogether.exception.room; + +import site.youtogether.exception.CustomException; +import site.youtogether.exception.ErrorType; + +public class SingleRoomParticipationViolationException extends CustomException { + + public SingleRoomParticipationViolationException() { + super(ErrorType.SINGLE_ROOM_PARTICIPATION_VIOLATION); + } + +} diff --git a/src/main/java/site/youtogether/room/application/RoomService.java b/src/main/java/site/youtogether/room/application/RoomService.java index 1f59bb1..4fcb394 100644 --- a/src/main/java/site/youtogether/room/application/RoomService.java +++ b/src/main/java/site/youtogether/room/application/RoomService.java @@ -3,6 +3,7 @@ import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; +import site.youtogether.exception.room.SingleRoomParticipationViolationException; import site.youtogether.room.Room; import site.youtogether.room.dto.RoomCode; import site.youtogether.room.dto.RoomSettings; @@ -22,32 +23,29 @@ public class RoomService { private final UserStorage userStorage; public RoomCode create(String address, RoomSettings roomSettings) { - Room room = createRoom(roomSettings); - User host = createHost(address); + if (redisStorage.existsInActiveAddress(address)) { + throw new SingleRoomParticipationViolationException(); + } - roomStorage.save(room); - userStorage.save(host); - - redisStorage.addHostingAddress(address); - redisStorage.addParticipant(room.getCode(), address); - - return new RoomCode(room); - } - - private Room createRoom(RoomSettings roomSettings) { - return Room.builder() + Room room = Room.builder() .title(roomSettings.getTitle()) .capacity(roomSettings.getCapacity()) .password(roomSettings.getPassword()) .build(); - } - private User createHost(String address) { - return User.builder() + User host = User.builder() .address(address) .nickname(RandomUtil.generateUserNickname()) .role(Role.HOST) .build(); + + roomStorage.save(room); + userStorage.save(host); + + redisStorage.addActiveAddress(address); + redisStorage.addParticipant(room.getCode(), address); + + return new RoomCode(room); } } From 7c10c7be79f6dba963e209488dab40fb2e1cb458 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 11 Mar 2024 12:48:46 +0900 Subject: [PATCH 38/70] =?UTF-8?q?modify:=20[ApiResponse]=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EC=8B=9C=20=EC=B2=98=EB=A6=AC=20=EA=B2=B0=EA=B3=BC?= =?UTF-8?q?=EB=A5=BC=20=EB=A9=94=EC=84=B8=EC=A7=80=EB=A1=9C=20=EC=95=88?= =?UTF-8?q?=EB=82=B4=ED=95=98=EB=8F=84=EB=A1=9D=20=EA=B5=AC=EC=A1=B0=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 --- .../exception/GlobalExceptionHandler.java | 5 +++-- .../room/presentation/RoomController.java | 3 ++- .../youtogether/util/api/ApiResponse.java | 16 ++++++++------- .../youtogether/util/api/ResponseResult.java | 20 +++++++++++++++++++ 4 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 src/main/java/site/youtogether/util/api/ResponseResult.java diff --git a/src/main/java/site/youtogether/exception/GlobalExceptionHandler.java b/src/main/java/site/youtogether/exception/GlobalExceptionHandler.java index 8d75cb6..38f01bb 100644 --- a/src/main/java/site/youtogether/exception/GlobalExceptionHandler.java +++ b/src/main/java/site/youtogether/exception/GlobalExceptionHandler.java @@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import site.youtogether.util.api.ApiResponse; +import site.youtogether.util.api.ResponseResult; @RestControllerAdvice public class GlobalExceptionHandler { @@ -21,7 +22,7 @@ public class GlobalExceptionHandler { @ExceptionHandler(BindException.class) public ResponseEntity> handleBindException(BindException exception) { return ResponseEntity.badRequest() - .body(ApiResponse.of(HttpStatus.BAD_REQUEST, + .body(ApiResponse.of(HttpStatus.BAD_REQUEST, ResponseResult.EXCEPTION_OCCURRED, exception.getBindingResult().getFieldErrors().stream() .collect(Collectors.groupingBy(FieldError::getField)) .entrySet().stream() @@ -44,7 +45,7 @@ public ResponseEntity> handleCustomException(CustomException error.put("message", customException.getMessage()); return ResponseEntity.badRequest() - .body(ApiResponse.of(customException.getStatus(), List.of(error))); + .body(ApiResponse.of(customException.getStatus(), ResponseResult.EXCEPTION_OCCURRED, List.of(error))); } } diff --git a/src/main/java/site/youtogether/room/presentation/RoomController.java b/src/main/java/site/youtogether/room/presentation/RoomController.java index afa2c80..86606c0 100644 --- a/src/main/java/site/youtogether/room/presentation/RoomController.java +++ b/src/main/java/site/youtogether/room/presentation/RoomController.java @@ -13,6 +13,7 @@ import site.youtogether.room.dto.RoomCode; import site.youtogether.room.dto.RoomSettings; import site.youtogether.util.api.ApiResponse; +import site.youtogether.util.api.ResponseResult; @RestController @RequiredArgsConstructor @@ -23,7 +24,7 @@ public class RoomController { @PostMapping("/rooms") public ResponseEntity> createRoom(@Address String address, @Valid @RequestBody RoomSettings roomSettings) { return ResponseEntity.status(HttpStatus.CREATED) - .body(ApiResponse.created(roomService.create(address, roomSettings))); + .body(ApiResponse.created(ResponseResult.ROOM_CREATION_SUCCESS, roomService.create(address, roomSettings))); } } diff --git a/src/main/java/site/youtogether/util/api/ApiResponse.java b/src/main/java/site/youtogether/util/api/ApiResponse.java index 5ef58b7..fc58825 100644 --- a/src/main/java/site/youtogether/util/api/ApiResponse.java +++ b/src/main/java/site/youtogether/util/api/ApiResponse.java @@ -9,24 +9,26 @@ public class ApiResponse { private final int code; private final String status; + private final String result; private final T data; - public ApiResponse(HttpStatus status, T data) { + public ApiResponse(HttpStatus status, ResponseResult result, T data) { this.code = status.value(); this.status = status.getReasonPhrase(); + this.result = result.getDescription(); this.data = data; } - public static ApiResponse of(HttpStatus status, T data) { - return new ApiResponse<>(status, data); + public static ApiResponse of(HttpStatus status, ResponseResult result, T data) { + return new ApiResponse<>(status, result, data); } - public static ApiResponse ok(T data) { - return new ApiResponse<>(HttpStatus.OK, data); + public static ApiResponse ok(ResponseResult result, T data) { + return new ApiResponse<>(HttpStatus.OK, result, data); } - public static ApiResponse created(T data) { - return new ApiResponse<>(HttpStatus.CREATED, data); + public static ApiResponse created(ResponseResult result, T data) { + return new ApiResponse<>(HttpStatus.CREATED, result, data); } } diff --git a/src/main/java/site/youtogether/util/api/ResponseResult.java b/src/main/java/site/youtogether/util/api/ResponseResult.java new file mode 100644 index 0000000..c615ec1 --- /dev/null +++ b/src/main/java/site/youtogether/util/api/ResponseResult.java @@ -0,0 +1,20 @@ +package site.youtogether.util.api; + +import lombok.Getter; + +@Getter +public enum ResponseResult { + + // Common + EXCEPTION_OCCURRED("예외가 발생했습니다"), + + // Room + ROOM_CREATION_SUCCESS("방 생성에 성공했습니다"); + + private final String description; + + ResponseResult(String description) { + this.description = description; + } + +} From 7eb7d901a5387cbb7f4a8789798f068aef9d579c Mon Sep 17 00:00:00 2001 From: yeonise Date: Thu, 14 Mar 2024 16:23:23 +0900 Subject: [PATCH 39/70] =?UTF-8?q?remove:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=84=A4=EC=A0=95=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.properties | 1 - 1 file changed, 1 deletion(-) delete mode 100644 src/main/resources/application.properties diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 8b13789..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - From 60b8012e4c2f05bd0b6f04347fdb3d590d6b5ae0 Mon Sep 17 00:00:00 2001 From: yeonise Date: Thu, 14 Mar 2024 16:24:47 +0900 Subject: [PATCH 40/70] =?UTF-8?q?modify:=20[RedisConfig]=20Redis=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/config/RedisConfig.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/site/youtogether/config/RedisConfig.java b/src/main/java/site/youtogether/config/RedisConfig.java index 34664e1..b731bb3 100644 --- a/src/main/java/site/youtogether/config/RedisConfig.java +++ b/src/main/java/site/youtogether/config/RedisConfig.java @@ -4,6 +4,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; @@ -18,7 +19,10 @@ public class RedisConfig { @Bean public RedisConnectionFactory redisConnectionFactory() { - return new LettuceConnectionFactory(redisProperties.getHost(), redisProperties.getPort()); + RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(redisProperties.getHost(), redisProperties.getPort()); + redisStandaloneConfiguration.setPassword(redisProperties.getPassword()); + + return new LettuceConnectionFactory(redisStandaloneConfiguration); } @Bean From d32d0ba40c1f09ed23fddb9d9c3f1bfcd604e348 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 15 Mar 2024 18:36:11 +0900 Subject: [PATCH 41/70] =?UTF-8?q?feat:=20SessionCookieInterceptor=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 세션 쿠키를 확인하여 세션 코드를 전달합니다. 세션 쿠키가 없다면 새로운 세션을 생성하고 응답에 포함시킵니다. --- .../site/youtogether/config/WebConfig.java | 15 ++++- .../interceptor/SessionCookieInterceptor.java | 65 +++++++++++++++++++ 2 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 src/main/java/site/youtogether/interceptor/SessionCookieInterceptor.java diff --git a/src/main/java/site/youtogether/config/WebConfig.java b/src/main/java/site/youtogether/config/WebConfig.java index f49cd9d..68e42e8 100644 --- a/src/main/java/site/youtogether/config/WebConfig.java +++ b/src/main/java/site/youtogether/config/WebConfig.java @@ -4,20 +4,29 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import lombok.RequiredArgsConstructor; -import site.youtogether.resolver.AddressArgumentResolver; +import site.youtogether.interceptor.SessionCookieInterceptor; +import site.youtogether.resolver.SessionCodeArgumentResolver; @Configuration @RequiredArgsConstructor public class WebConfig implements WebMvcConfigurer { - private final AddressArgumentResolver addressArgumentResolver; + private final SessionCookieInterceptor sessionCookieInterceptor; + private final SessionCodeArgumentResolver sessionCodeArgumentResolver; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(sessionCookieInterceptor) + .addPathPatterns("/**"); + } @Override public void addArgumentResolvers(List resolvers) { - resolvers.add(addressArgumentResolver); + resolvers.add(sessionCodeArgumentResolver); } } diff --git a/src/main/java/site/youtogether/interceptor/SessionCookieInterceptor.java b/src/main/java/site/youtogether/interceptor/SessionCookieInterceptor.java new file mode 100644 index 0000000..e5d0183 --- /dev/null +++ b/src/main/java/site/youtogether/interceptor/SessionCookieInterceptor.java @@ -0,0 +1,65 @@ +package site.youtogether.interceptor; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseCookie; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import site.youtogether.config.property.CookieProperties; +import site.youtogether.user.User; +import site.youtogether.user.infrastructure.UserStorage; +import site.youtogether.util.AppConstants; +import site.youtogether.util.RandomUtil; + +@Component +@RequiredArgsConstructor +public class SessionCookieInterceptor implements HandlerInterceptor { + + private final CookieProperties cookieProperties; + private final UserStorage userStorage; + + /** + * If there is no session cookie in the request, it creates a new one and saves it. + * If a session cookie is present, it saves the found cookie in the attributes. + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + Cookie[] cookies = request.getCookies(); + + if (cookies != null) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals(cookieProperties.getName())) { + request.setAttribute(AppConstants.SESSION_CODE, cookie.getValue()); + + return true; + } + } + } + + ResponseCookie sessionCookie = ResponseCookie.from(cookieProperties.getName(), RandomUtil.generateSessionCode()) + .domain(cookieProperties.getDomain()) + .path(cookieProperties.getPath()) + .sameSite(cookieProperties.getSameSite()) + .maxAge(cookieProperties.getExpiry()) + .httpOnly(true) + .secure(true) + .build(); + + response.setHeader(HttpHeaders.SET_COOKIE, sessionCookie.toString()); + request.setAttribute(AppConstants.SESSION_CODE, sessionCookie.getValue()); + + User user = User.builder() + .sessionCode(sessionCookie.getValue()) + .address(request.getRemoteAddr()) + .build(); + + userStorage.save(user); + + return true; + } + +} From 740bb203bc155c685999b62800ca4740c07aa77c Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 15 Mar 2024 18:37:41 +0900 Subject: [PATCH 42/70] =?UTF-8?q?modify:=20[Resolver]=20IP=20=EC=A3=BC?= =?UTF-8?q?=EC=86=8C=20=E2=86=92=20=EC=84=B8=EC=85=98=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=EB=84=98=EA=B8=B0=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resolver/{Address.java => SessionCode.java} | 2 +- ...umentResolver.java => SessionCodeArgumentResolver.java} | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) rename src/main/java/site/youtogether/resolver/{Address.java => SessionCode.java} (89%) rename src/main/java/site/youtogether/resolver/{AddressArgumentResolver.java => SessionCodeArgumentResolver.java} (83%) diff --git a/src/main/java/site/youtogether/resolver/Address.java b/src/main/java/site/youtogether/resolver/SessionCode.java similarity index 89% rename from src/main/java/site/youtogether/resolver/Address.java rename to src/main/java/site/youtogether/resolver/SessionCode.java index acc6793..e82f698 100644 --- a/src/main/java/site/youtogether/resolver/Address.java +++ b/src/main/java/site/youtogether/resolver/SessionCode.java @@ -7,5 +7,5 @@ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) -public @interface Address { +public @interface SessionCode { } diff --git a/src/main/java/site/youtogether/resolver/AddressArgumentResolver.java b/src/main/java/site/youtogether/resolver/SessionCodeArgumentResolver.java similarity index 83% rename from src/main/java/site/youtogether/resolver/AddressArgumentResolver.java rename to src/main/java/site/youtogether/resolver/SessionCodeArgumentResolver.java index 0786da7..08abb97 100644 --- a/src/main/java/site/youtogether/resolver/AddressArgumentResolver.java +++ b/src/main/java/site/youtogether/resolver/SessionCodeArgumentResolver.java @@ -8,13 +8,14 @@ import org.springframework.web.method.support.ModelAndViewContainer; import jakarta.servlet.http.HttpServletRequest; +import site.youtogether.util.AppConstants; @Component -public class AddressArgumentResolver implements HandlerMethodArgumentResolver { +public class SessionCodeArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { - boolean hasAddressAnnotation = parameter.hasParameterAnnotation(Address.class); + boolean hasAddressAnnotation = parameter.hasParameterAnnotation(SessionCode.class); boolean isStringType = String.class.isAssignableFrom(parameter.getParameterType()); return hasAddressAnnotation && isStringType; @@ -26,7 +27,7 @@ public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer m HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); assert request != null; - return request.getLocalAddr(); + return request.getAttribute(AppConstants.SESSION_CODE); } } From 6891ae0444521faa8d6ddd6a5eb0135b25e60332 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 15 Mar 2024 18:38:42 +0900 Subject: [PATCH 43/70] =?UTF-8?q?feat:=20Property=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EA=B4=80=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EB=B0=8F=20CookieProperties=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../youtogether/config/PropertiesConfig.java | 14 ++++++++++++++ .../config/property/CookieProperties.java | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/main/java/site/youtogether/config/PropertiesConfig.java create mode 100644 src/main/java/site/youtogether/config/property/CookieProperties.java diff --git a/src/main/java/site/youtogether/config/PropertiesConfig.java b/src/main/java/site/youtogether/config/PropertiesConfig.java new file mode 100644 index 0000000..70a1468 --- /dev/null +++ b/src/main/java/site/youtogether/config/PropertiesConfig.java @@ -0,0 +1,14 @@ +package site.youtogether.config; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import site.youtogether.config.property.CookieProperties; + +@Configuration +@EnableConfigurationProperties(value = { + CookieProperties.class +}) +public class PropertiesConfig { + +} diff --git a/src/main/java/site/youtogether/config/property/CookieProperties.java b/src/main/java/site/youtogether/config/property/CookieProperties.java new file mode 100644 index 0000000..26671c3 --- /dev/null +++ b/src/main/java/site/youtogether/config/property/CookieProperties.java @@ -0,0 +1,19 @@ +package site.youtogether.config.property; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@ConfigurationProperties("cookie") +@RequiredArgsConstructor +@Getter +public class CookieProperties { + + private final String name; + private final String domain; + private final String path; + private final String sameSite; + private final int expiry; + +} From 932fcca439865a27e82d591ba7af540605a7bd38 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 15 Mar 2024 18:39:40 +0900 Subject: [PATCH 44/70] =?UTF-8?q?modify:=20IP=20=EC=A3=BC=EC=86=8C=20?= =?UTF-8?q?=E2=86=92=20=EC=84=B8=EC=85=98=20=EC=BD=94=EB=93=9C=EB=A5=BC=20?= =?UTF-8?q?=EC=9D=B8=EC=9E=90=EB=A1=9C=20=EB=B0=9B=EB=8F=84=EB=A1=9D=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 --- .../site/youtogether/room/presentation/RoomController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/site/youtogether/room/presentation/RoomController.java b/src/main/java/site/youtogether/room/presentation/RoomController.java index 86606c0..0e392e1 100644 --- a/src/main/java/site/youtogether/room/presentation/RoomController.java +++ b/src/main/java/site/youtogether/room/presentation/RoomController.java @@ -8,7 +8,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import site.youtogether.resolver.Address; +import site.youtogether.resolver.SessionCode; import site.youtogether.room.application.RoomService; import site.youtogether.room.dto.RoomCode; import site.youtogether.room.dto.RoomSettings; @@ -22,9 +22,9 @@ public class RoomController { private final RoomService roomService; @PostMapping("/rooms") - public ResponseEntity> createRoom(@Address String address, @Valid @RequestBody RoomSettings roomSettings) { + public ResponseEntity> createRoom(@SessionCode String sessionCode, @Valid @RequestBody RoomSettings roomSettings) { return ResponseEntity.status(HttpStatus.CREATED) - .body(ApiResponse.created(ResponseResult.ROOM_CREATION_SUCCESS, roomService.create(address, roomSettings))); + .body(ApiResponse.created(ResponseResult.ROOM_CREATION_SUCCESS, roomService.create(sessionCode, roomSettings))); } } From 3ab304d1a40d8f633c986c102189387ef1559ff2 Mon Sep 17 00:00:00 2001 From: yeonise Date: Fri, 15 Mar 2024 18:42:35 +0900 Subject: [PATCH 45/70] =?UTF-8?q?modify:=20=EB=B0=A9=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=ED=9D=90=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 세션 코드로 사용자 정보를 가져옵니다. 2. 닉네임과 방장 권한을 부여한 사용자 정보를 PUT 합니다. 3. 방을 생성하고 저장합니다. 4. 참가자 그룹에 세션 코드를 추가합니다. 5. 생성한 방의 코드를 반환합니다. --- src/main/java/site/youtogether/room/Room.java | 15 ++++++++--- .../room/application/RoomService.java | 27 ++++++++++--------- .../room/infrastructure/RedisStorage.java | 13 +++------ src/main/java/site/youtogether/user/User.java | 6 +++-- .../site/youtogether/util/AppConstants.java | 4 +-- .../site/youtogether/util/RandomUtil.java | 11 ++++++++ 6 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/main/java/site/youtogether/room/Room.java b/src/main/java/site/youtogether/room/Room.java index 9407a0b..da22df3 100644 --- a/src/main/java/site/youtogether/room/Room.java +++ b/src/main/java/site/youtogether/room/Room.java @@ -1,10 +1,14 @@ package site.youtogether.room; +import java.util.HashMap; +import java.util.Map; + import org.springframework.data.annotation.Id; import org.springframework.data.redis.core.RedisHash; import lombok.Builder; import lombok.Getter; +import site.youtogether.user.User; import site.youtogether.util.RandomUtil; @RedisHash(value = "room") @@ -14,16 +18,21 @@ public class Room { @Id private final String code; - private final String title; private final int capacity; + private final String title; private final String password; + private final String host; + private final Map participants = new HashMap<>(10); @Builder - public Room(String title, int capacity, String password) { + public Room(String title, int capacity, String password, User host) { this.code = RandomUtil.generateRoomCode(); - this.title = title; this.capacity = capacity; + this.title = title; this.password = password; + this.host = host.getSessionCode(); + + participants.put(host.getSessionCode(), host); } } diff --git a/src/main/java/site/youtogether/room/application/RoomService.java b/src/main/java/site/youtogether/room/application/RoomService.java index 4fcb394..9551853 100644 --- a/src/main/java/site/youtogether/room/application/RoomService.java +++ b/src/main/java/site/youtogether/room/application/RoomService.java @@ -22,28 +22,29 @@ public class RoomService { private final RoomStorage roomStorage; private final UserStorage userStorage; - public RoomCode create(String address, RoomSettings roomSettings) { - if (redisStorage.existsInActiveAddress(address)) { + public RoomCode create(String sessionCode, RoomSettings roomSettings) { + if (redisStorage.isParticipant(sessionCode)) { throw new SingleRoomParticipationViolationException(); } - Room room = Room.builder() - .title(roomSettings.getTitle()) - .capacity(roomSettings.getCapacity()) - .password(roomSettings.getPassword()) - .build(); - + User user = userStorage.findById(sessionCode).orElseThrow(); User host = User.builder() - .address(address) + .sessionCode(user.getSessionCode()) + .address(user.getAddress()) .nickname(RandomUtil.generateUserNickname()) .role(Role.HOST) .build(); - roomStorage.save(room); - userStorage.save(host); + Room room = Room.builder() + .capacity(roomSettings.getCapacity()) + .title(roomSettings.getTitle()) + .password(roomSettings.getPassword()) + .host(host) + .build(); - redisStorage.addActiveAddress(address); - redisStorage.addParticipant(room.getCode(), address); + userStorage.save(host); + roomStorage.save(room); + redisStorage.addParticipant(sessionCode); return new RoomCode(room); } diff --git a/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java b/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java index 8120fbb..531582d 100644 --- a/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java +++ b/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java @@ -13,17 +13,12 @@ public class RedisStorage { private final RedisTemplate redisStringTemplate; - public Boolean existsInActiveAddress(String address) { - return redisStringTemplate.opsForSet().isMember(ACTIVE_ADDRESS_KEY, address); + public Boolean isParticipant(String sessionCode) { + return redisStringTemplate.opsForSet().isMember(PARTICIPANTS_KEY, sessionCode); } - public void addActiveAddress(String address) { - redisStringTemplate.opsForSet().add(ACTIVE_ADDRESS_KEY, address); - } - - public void addParticipant(String roomCode, String address) { - String participantKey = PARTICIPANTS_KEY_PREFIX + roomCode; - redisStringTemplate.opsForSet().add(participantKey, address); + public void addParticipant(String sessionCode) { + redisStringTemplate.opsForSet().add(PARTICIPANTS_KEY, sessionCode); } } diff --git a/src/main/java/site/youtogether/user/User.java b/src/main/java/site/youtogether/user/User.java index 23b473b..93f92e4 100644 --- a/src/main/java/site/youtogether/user/User.java +++ b/src/main/java/site/youtogether/user/User.java @@ -11,13 +11,15 @@ public class User { @Id - private final String address; + private final String sessionCode; + private final String address; private final String nickname; private final Role role; @Builder - public User(String address, String nickname, Role role) { + public User(String sessionCode, String address, String nickname, Role role) { + this.sessionCode = sessionCode; this.address = address; this.nickname = nickname; this.role = role; diff --git a/src/main/java/site/youtogether/util/AppConstants.java b/src/main/java/site/youtogether/util/AppConstants.java index 1eec7f4..d722028 100644 --- a/src/main/java/site/youtogether/util/AppConstants.java +++ b/src/main/java/site/youtogether/util/AppConstants.java @@ -6,9 +6,9 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class AppConstants { - public static final String ACTIVE_ADDRESS_KEY = "active"; + public static final String PARTICIPANTS_KEY = "participants"; public static final String ROOM_KEY_PREFIX = "room:"; public static final String USER_KEY_PREFIX = "user:"; - public static final String PARTICIPANTS_KEY_PREFIX = "participants:"; + public static final String SESSION_CODE = "SESSION_CODE"; } diff --git a/src/main/java/site/youtogether/util/RandomUtil.java b/src/main/java/site/youtogether/util/RandomUtil.java index ee55342..5deb204 100644 --- a/src/main/java/site/youtogether/util/RandomUtil.java +++ b/src/main/java/site/youtogether/util/RandomUtil.java @@ -21,6 +21,17 @@ public static String generateRoomCode() { return randomString.substring(0, 10); } + /** + * generate random session code + * length is 20 + * using a-z A-Z 0-9 + */ + public static String generateSessionCode() { + String randomString = UUID.randomUUID().toString().replaceAll("-", ""); + + return randomString.substring(0, 20); + } + /** * generate random user nickname * sample list size is 20 From 78801022ace13f8d08c32da17d2af31d9a7062a3 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 14:41:53 +0900 Subject: [PATCH 46/70] =?UTF-8?q?modify:=20session=20code=20=E2=86=92=20ip?= =?UTF-8?q?=20address=20resolver=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resolver/{SessionCode.java => Address.java} | 2 +- ...eArgumentResolver.java => AddressArgumentResolver.java} | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) rename src/main/java/site/youtogether/resolver/{SessionCode.java => Address.java} (89%) rename src/main/java/site/youtogether/resolver/{SessionCodeArgumentResolver.java => AddressArgumentResolver.java} (83%) diff --git a/src/main/java/site/youtogether/resolver/SessionCode.java b/src/main/java/site/youtogether/resolver/Address.java similarity index 89% rename from src/main/java/site/youtogether/resolver/SessionCode.java rename to src/main/java/site/youtogether/resolver/Address.java index e82f698..acc6793 100644 --- a/src/main/java/site/youtogether/resolver/SessionCode.java +++ b/src/main/java/site/youtogether/resolver/Address.java @@ -7,5 +7,5 @@ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) -public @interface SessionCode { +public @interface Address { } diff --git a/src/main/java/site/youtogether/resolver/SessionCodeArgumentResolver.java b/src/main/java/site/youtogether/resolver/AddressArgumentResolver.java similarity index 83% rename from src/main/java/site/youtogether/resolver/SessionCodeArgumentResolver.java rename to src/main/java/site/youtogether/resolver/AddressArgumentResolver.java index 08abb97..3c58b8e 100644 --- a/src/main/java/site/youtogether/resolver/SessionCodeArgumentResolver.java +++ b/src/main/java/site/youtogether/resolver/AddressArgumentResolver.java @@ -8,14 +8,13 @@ import org.springframework.web.method.support.ModelAndViewContainer; import jakarta.servlet.http.HttpServletRequest; -import site.youtogether.util.AppConstants; @Component -public class SessionCodeArgumentResolver implements HandlerMethodArgumentResolver { +public class AddressArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { - boolean hasAddressAnnotation = parameter.hasParameterAnnotation(SessionCode.class); + boolean hasAddressAnnotation = parameter.hasParameterAnnotation(Address.class); boolean isStringType = String.class.isAssignableFrom(parameter.getParameterType()); return hasAddressAnnotation && isStringType; @@ -27,7 +26,7 @@ public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer m HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); assert request != null; - return request.getAttribute(AppConstants.SESSION_CODE); + return request.getRemoteAddr(); } } From c3e8b5b8c7c4bb97aa9adc5e623e90601583d26b Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 14:42:27 +0900 Subject: [PATCH 47/70] =?UTF-8?q?remove:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=9D=B8=ED=84=B0=EC=85=89?= =?UTF-8?q?=ED=84=B0=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../interceptor/SessionCookieInterceptor.java | 65 ------------------- 1 file changed, 65 deletions(-) delete mode 100644 src/main/java/site/youtogether/interceptor/SessionCookieInterceptor.java diff --git a/src/main/java/site/youtogether/interceptor/SessionCookieInterceptor.java b/src/main/java/site/youtogether/interceptor/SessionCookieInterceptor.java deleted file mode 100644 index e5d0183..0000000 --- a/src/main/java/site/youtogether/interceptor/SessionCookieInterceptor.java +++ /dev/null @@ -1,65 +0,0 @@ -package site.youtogether.interceptor; - -import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseCookie; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.HandlerInterceptor; - -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import site.youtogether.config.property.CookieProperties; -import site.youtogether.user.User; -import site.youtogether.user.infrastructure.UserStorage; -import site.youtogether.util.AppConstants; -import site.youtogether.util.RandomUtil; - -@Component -@RequiredArgsConstructor -public class SessionCookieInterceptor implements HandlerInterceptor { - - private final CookieProperties cookieProperties; - private final UserStorage userStorage; - - /** - * If there is no session cookie in the request, it creates a new one and saves it. - * If a session cookie is present, it saves the found cookie in the attributes. - */ - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - Cookie[] cookies = request.getCookies(); - - if (cookies != null) { - for (Cookie cookie : cookies) { - if (cookie.getName().equals(cookieProperties.getName())) { - request.setAttribute(AppConstants.SESSION_CODE, cookie.getValue()); - - return true; - } - } - } - - ResponseCookie sessionCookie = ResponseCookie.from(cookieProperties.getName(), RandomUtil.generateSessionCode()) - .domain(cookieProperties.getDomain()) - .path(cookieProperties.getPath()) - .sameSite(cookieProperties.getSameSite()) - .maxAge(cookieProperties.getExpiry()) - .httpOnly(true) - .secure(true) - .build(); - - response.setHeader(HttpHeaders.SET_COOKIE, sessionCookie.toString()); - request.setAttribute(AppConstants.SESSION_CODE, sessionCookie.getValue()); - - User user = User.builder() - .sessionCode(sessionCookie.getValue()) - .address(request.getRemoteAddr()) - .build(); - - userStorage.save(user); - - return true; - } - -} From 57eac7b0891317d062e5177ca1f1a9dfc5962df1 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 14:42:49 +0900 Subject: [PATCH 48/70] =?UTF-8?q?modify:=20WebConfig=EC=97=90=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/site/youtogether/config/WebConfig.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/main/java/site/youtogether/config/WebConfig.java b/src/main/java/site/youtogether/config/WebConfig.java index 68e42e8..f49cd9d 100644 --- a/src/main/java/site/youtogether/config/WebConfig.java +++ b/src/main/java/site/youtogether/config/WebConfig.java @@ -4,29 +4,20 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import lombok.RequiredArgsConstructor; -import site.youtogether.interceptor.SessionCookieInterceptor; -import site.youtogether.resolver.SessionCodeArgumentResolver; +import site.youtogether.resolver.AddressArgumentResolver; @Configuration @RequiredArgsConstructor public class WebConfig implements WebMvcConfigurer { - private final SessionCookieInterceptor sessionCookieInterceptor; - private final SessionCodeArgumentResolver sessionCodeArgumentResolver; - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(sessionCookieInterceptor) - .addPathPatterns("/**"); - } + private final AddressArgumentResolver addressArgumentResolver; @Override public void addArgumentResolvers(List resolvers) { - resolvers.add(sessionCodeArgumentResolver); + resolvers.add(addressArgumentResolver); } } From 059e75df6c653b827f901ac348b6f315c335d3f8 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 14:43:37 +0900 Subject: [PATCH 49/70] =?UTF-8?q?remove:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=A0=80=EC=9E=A5=EC=86=8C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../room/infrastructure/RedisStorage.java | 24 ------------------- 1 file changed, 24 deletions(-) delete mode 100644 src/main/java/site/youtogether/room/infrastructure/RedisStorage.java diff --git a/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java b/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java deleted file mode 100644 index 531582d..0000000 --- a/src/main/java/site/youtogether/room/infrastructure/RedisStorage.java +++ /dev/null @@ -1,24 +0,0 @@ -package site.youtogether.room.infrastructure; - -import static site.youtogether.util.AppConstants.*; - -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Repository; - -import lombok.RequiredArgsConstructor; - -@Repository -@RequiredArgsConstructor -public class RedisStorage { - - private final RedisTemplate redisStringTemplate; - - public Boolean isParticipant(String sessionCode) { - return redisStringTemplate.opsForSet().isMember(PARTICIPANTS_KEY, sessionCode); - } - - public void addParticipant(String sessionCode) { - redisStringTemplate.opsForSet().add(PARTICIPANTS_KEY, sessionCode); - } - -} From 174f134abd775c8a2dd6ffb398bf9b13f9472ec9 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 14:44:42 +0900 Subject: [PATCH 50/70] =?UTF-8?q?feat:=20[RoomController]=20=EC=BF=A0?= =?UTF-8?q?=ED=82=A4=EC=99=80=20=EA=B4=80=EB=A0=A8=EB=90=9C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=EC=9D=84=20=EC=B2=98=EB=A6=AC=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=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 --- .../room/presentation/RoomController.java | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/main/java/site/youtogether/room/presentation/RoomController.java b/src/main/java/site/youtogether/room/presentation/RoomController.java index 0e392e1..32413f9 100644 --- a/src/main/java/site/youtogether/room/presentation/RoomController.java +++ b/src/main/java/site/youtogether/room/presentation/RoomController.java @@ -1,17 +1,27 @@ package site.youtogether.room.presentation; +import static site.youtogether.util.AppConstants.*; + +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseCookie; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import site.youtogether.resolver.SessionCode; +import site.youtogether.config.property.CookieProperties; +import site.youtogether.exception.room.SingleRoomParticipationViolationException; +import site.youtogether.resolver.Address; import site.youtogether.room.application.RoomService; import site.youtogether.room.dto.RoomCode; import site.youtogether.room.dto.RoomSettings; +import site.youtogether.util.RandomUtil; import site.youtogether.util.api.ApiResponse; import site.youtogether.util.api.ResponseResult; @@ -19,12 +29,36 @@ @RequiredArgsConstructor public class RoomController { + private final CookieProperties cookieProperties; private final RoomService roomService; @PostMapping("/rooms") - public ResponseEntity> createRoom(@SessionCode String sessionCode, @Valid @RequestBody RoomSettings roomSettings) { + public ResponseEntity> createRoom(@CookieValue(value = SESSION_COOKIE_NAME, required = false) Cookie sessionCookie, + @Address String address, @Valid @RequestBody RoomSettings roomSettings, HttpServletResponse response) { + // Check if a session cookie already exists. + if (sessionCookie != null) { + throw new SingleRoomParticipationViolationException(); + } + + // Generate a new session code and set it as a cookie. + ResponseCookie cookie = ResponseCookie.from(cookieProperties.getName(), RandomUtil.generateSessionCode()) + .domain(cookieProperties.getDomain()) + .path(cookieProperties.getPath()) + .sameSite(cookieProperties.getSameSite()) + .maxAge(cookieProperties.getExpiry()) + .httpOnly(true) + .secure(true) + .build(); + + // Create a new room with the generated session code. + RoomCode roomCode = roomService.create(cookie.getValue(), address, roomSettings); + + // Add the cookie to the response header. + response.setHeader(HttpHeaders.SET_COOKIE, cookie.toString()); + + // Return a response indicating successful room creation. return ResponseEntity.status(HttpStatus.CREATED) - .body(ApiResponse.created(ResponseResult.ROOM_CREATION_SUCCESS, roomService.create(sessionCode, roomSettings))); + .body(ApiResponse.created(ResponseResult.ROOM_CREATION_SUCCESS, roomCode)); } } From e12450e824a2dbd84a52dba962aaabf185e0f749 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 14:45:28 +0900 Subject: [PATCH 51/70] =?UTF-8?q?modify:=20[RoomService]=20=EB=B0=A9=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=8B=A8=EA=B3=84=20=EA=B0=84=EC=86=8C?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../youtogether/room/application/RoomService.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/main/java/site/youtogether/room/application/RoomService.java b/src/main/java/site/youtogether/room/application/RoomService.java index 9551853..fa0333d 100644 --- a/src/main/java/site/youtogether/room/application/RoomService.java +++ b/src/main/java/site/youtogether/room/application/RoomService.java @@ -3,11 +3,9 @@ import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; -import site.youtogether.exception.room.SingleRoomParticipationViolationException; import site.youtogether.room.Room; import site.youtogether.room.dto.RoomCode; import site.youtogether.room.dto.RoomSettings; -import site.youtogether.room.infrastructure.RedisStorage; import site.youtogether.room.infrastructure.RoomStorage; import site.youtogether.user.Role; import site.youtogether.user.User; @@ -18,19 +16,13 @@ @RequiredArgsConstructor public class RoomService { - private final RedisStorage redisStorage; private final RoomStorage roomStorage; private final UserStorage userStorage; - public RoomCode create(String sessionCode, RoomSettings roomSettings) { - if (redisStorage.isParticipant(sessionCode)) { - throw new SingleRoomParticipationViolationException(); - } - - User user = userStorage.findById(sessionCode).orElseThrow(); + public RoomCode create(String sessionCode, String address, RoomSettings roomSettings) { User host = User.builder() - .sessionCode(user.getSessionCode()) - .address(user.getAddress()) + .sessionCode(sessionCode) + .address(address) .nickname(RandomUtil.generateUserNickname()) .role(Role.HOST) .build(); @@ -44,7 +36,6 @@ public RoomCode create(String sessionCode, RoomSettings roomSettings) { userStorage.save(host); roomStorage.save(room); - redisStorage.addParticipant(sessionCode); return new RoomCode(room); } From 8d47e76b4d839c5e622b533e77caf6228597c9b1 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 14:46:21 +0900 Subject: [PATCH 52/70] =?UTF-8?q?rename:=20=EC=83=81=EC=88=98=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SESSION_CODE → SESSION_COOKIE_NAME --- src/main/java/site/youtogether/util/AppConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/site/youtogether/util/AppConstants.java b/src/main/java/site/youtogether/util/AppConstants.java index d722028..8c25d54 100644 --- a/src/main/java/site/youtogether/util/AppConstants.java +++ b/src/main/java/site/youtogether/util/AppConstants.java @@ -9,6 +9,6 @@ public final class AppConstants { public static final String PARTICIPANTS_KEY = "participants"; public static final String ROOM_KEY_PREFIX = "room:"; public static final String USER_KEY_PREFIX = "user:"; - public static final String SESSION_CODE = "SESSION_CODE"; + public static final String SESSION_COOKIE_NAME = "YTSession"; } From 5fd9b4285fffc04b288af5295f64e08e101e34d1 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 14:47:15 +0900 Subject: [PATCH 53/70] =?UTF-8?q?remove:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../youtogether/YouTogetherApplicationTests.java | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 src/test/java/site/youtogether/YouTogetherApplicationTests.java diff --git a/src/test/java/site/youtogether/YouTogetherApplicationTests.java b/src/test/java/site/youtogether/YouTogetherApplicationTests.java deleted file mode 100644 index fd8b01b..0000000 --- a/src/test/java/site/youtogether/YouTogetherApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package site.youtogether; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class YouTogetherApplicationTests { - - @Test - void contextLoads() { - } - -} From effde5ba996bc5c79e643cfd8c04b06a5636720e Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 15:36:56 +0900 Subject: [PATCH 54/70] =?UTF-8?q?feat:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=20=EC=84=A4=EC=A0=95=20=EB=B0=8F=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit min-coverage-overall을 80에서 70으로 변경하였습니다. --- .github/workflows/test-report.yml | 4 +- build.gradle | 47 +++++++++++++++++++ .../youtogether/IntegrationTestSupport.java | 10 ++++ .../site/youtogether/RestDocsSupport.java | 22 +++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 src/test/java/site/youtogether/IntegrationTestSupport.java create mode 100644 src/test/java/site/youtogether/RestDocsSupport.java diff --git a/.github/workflows/test-report.yml b/.github/workflows/test-report.yml index aaef3a5..e607be4 100644 --- a/.github/workflows/test-report.yml +++ b/.github/workflows/test-report.yml @@ -55,5 +55,5 @@ jobs: title: Test Coverage Report paths: ${{ github.workspace }}/build/reports/jacoco/test/jacocoTestReport.xml token: ${{ secrets.ACCESS_TOKEN }} - min-coverage-overall: 80 - min-coverage-changed-files: 50 + min-coverage-overall: 70 + min-coverage-changed-files: 40 diff --git a/build.gradle b/build.gradle index a5af9b9..0876b4b 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,8 @@ plugins { id 'java' id 'org.springframework.boot' version '3.2.3' id 'io.spring.dependency-management' version '1.1.4' + id 'org.asciidoctor.jvm.convert' version '3.3.2' + id 'jacoco' } group = 'site' @@ -15,6 +17,8 @@ configurations { compileOnly { extendsFrom annotationProcessor } + + asciidoctorExt } repositories { @@ -27,11 +31,54 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-redis' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' + asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' + testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() + + finalizedBy jacocoTestReport +} + +ext { + snippetsDir = file('build/generated-snippets') +} + +asciidoctor { + inputs.dir snippetsDir + configurations 'asciidoctorExt' + + sources { + include("**/index.adoc") + } + + baseDirFollowsSourceFile() + dependsOn test +} + +bootJar { + dependsOn asciidoctor + + from("${asciidoctor.outputDir}") { + into 'static/docs' + } +} + +jacoco { + toolVersion = "0.8.8" +} + +jacocoTestReport { + dependsOn test + + reports { + xml.required = true + html.required = true + } + + finalizedBy 'jacocoTestCoverageVerification' } jar { diff --git a/src/test/java/site/youtogether/IntegrationTestSupport.java b/src/test/java/site/youtogether/IntegrationTestSupport.java new file mode 100644 index 0000000..3c28942 --- /dev/null +++ b/src/test/java/site/youtogether/IntegrationTestSupport.java @@ -0,0 +1,10 @@ +package site.youtogether; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest +@ActiveProfiles("test") +public abstract class IntegrationTestSupport { + +} diff --git a/src/test/java/site/youtogether/RestDocsSupport.java b/src/test/java/site/youtogether/RestDocsSupport.java new file mode 100644 index 0000000..d368b0b --- /dev/null +++ b/src/test/java/site/youtogether/RestDocsSupport.java @@ -0,0 +1,22 @@ +package site.youtogether; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.test.web.servlet.MockMvc; + +import com.fasterxml.jackson.databind.ObjectMapper; + +@WebMvcTest(controllers = { + +}) +@AutoConfigureRestDocs +public abstract class RestDocsSupport { + + @Autowired + protected MockMvc mockMvc; + + @Autowired + protected ObjectMapper objectMapper; + +} From ee007693ff23f957de5951424e24a22b359c56ab Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 16:42:41 +0900 Subject: [PATCH 55/70] =?UTF-8?q?test:=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?-=20=EB=B0=A9=20=EC=83=9D=EC=84=B1=20=EC=84=B1=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../site/youtogether/room/dto/RoomCode.java | 2 + .../youtogether/room/dto/RoomSettings.java | 10 ++ .../site/youtogether/RestDocsSupport.java | 16 ++- .../room/presentation/RoomControllerTest.java | 99 +++++++++++++++++++ 4 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 src/test/java/site/youtogether/room/presentation/RoomControllerTest.java diff --git a/src/main/java/site/youtogether/room/dto/RoomCode.java b/src/main/java/site/youtogether/room/dto/RoomCode.java index 44c8cbb..19bd203 100644 --- a/src/main/java/site/youtogether/room/dto/RoomCode.java +++ b/src/main/java/site/youtogether/room/dto/RoomCode.java @@ -1,8 +1,10 @@ package site.youtogether.room.dto; +import lombok.AllArgsConstructor; import lombok.Getter; import site.youtogether.room.Room; +@AllArgsConstructor @Getter public class RoomCode { diff --git a/src/main/java/site/youtogether/room/dto/RoomSettings.java b/src/main/java/site/youtogether/room/dto/RoomSettings.java index 2697e4c..e146c9d 100644 --- a/src/main/java/site/youtogether/room/dto/RoomSettings.java +++ b/src/main/java/site/youtogether/room/dto/RoomSettings.java @@ -5,8 +5,11 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; +import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; +@NoArgsConstructor @Getter public class RoomSettings { @@ -20,4 +23,11 @@ public class RoomSettings { @Pattern(regexp = "^[0-9a-zA-Z]{5,10}$") private String password; + @Builder + public RoomSettings(String title, int capacity, String password) { + this.title = title; + this.capacity = capacity; + this.password = password; + } + } diff --git a/src/test/java/site/youtogether/RestDocsSupport.java b/src/test/java/site/youtogether/RestDocsSupport.java index d368b0b..ff65587 100644 --- a/src/test/java/site/youtogether/RestDocsSupport.java +++ b/src/test/java/site/youtogether/RestDocsSupport.java @@ -3,14 +3,22 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; import org.springframework.test.web.servlet.MockMvc; import com.fasterxml.jackson.databind.ObjectMapper; -@WebMvcTest(controllers = { +import site.youtogether.config.PropertiesConfig; +import site.youtogether.config.property.CookieProperties; +import site.youtogether.room.application.RoomService; +import site.youtogether.room.presentation.RoomController; +@WebMvcTest(controllers = { + RoomController.class }) @AutoConfigureRestDocs +@Import(PropertiesConfig.class) public abstract class RestDocsSupport { @Autowired @@ -19,4 +27,10 @@ public abstract class RestDocsSupport { @Autowired protected ObjectMapper objectMapper; + @Autowired + protected CookieProperties cookieProperties; + + @MockBean + protected RoomService roomService; + } diff --git a/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java b/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java new file mode 100644 index 0000000..302b222 --- /dev/null +++ b/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java @@ -0,0 +1,99 @@ +package site.youtogether.room.presentation; + +import static org.mockito.BDDMockito.*; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.*; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; + +import site.youtogether.RestDocsSupport; +import site.youtogether.room.dto.RoomCode; +import site.youtogether.room.dto.RoomSettings; +import site.youtogether.util.api.ResponseResult; + +class RoomControllerTest extends RestDocsSupport { + + @Test + @DisplayName("방 생성 성공") + void createRoomSuccess() throws Exception { + // given + // Setting up request data for creating a room + RoomSettings roomSettings = RoomSettings.builder() + .title("재밌는 쇼츠 같이 보기") + .capacity(10) + .password(null) + .build(); + + // Setting up response data for the created room + RoomCode roomCode = new RoomCode("1e7050f7d7"); + given(roomService.create(anyString(), anyString(), any(RoomSettings.class))) + .willReturn(roomCode); + + // when / then + String cookieName = cookieProperties.getName(); + + mockMvc.perform(post("/rooms") + .content(objectMapper.writeValueAsString(roomSettings)) + .contentType(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isCreated()) + .andExpect(cookie().exists(cookieName)) + .andExpect(cookie().domain(cookieName, cookieProperties.getDomain())) + .andExpect(cookie().path(cookieName, cookieProperties.getPath())) + .andExpect(cookie().sameSite(cookieName, cookieProperties.getSameSite())) + .andExpect(cookie().maxAge(cookieName, cookieProperties.getExpiry())) + .andExpect(cookie().httpOnly(cookieName, true)) + .andExpect(cookie().secure(cookieName, true)) + .andExpect(jsonPath("$.code").value(HttpStatus.CREATED.value())) + .andExpect(jsonPath("$.status").value(HttpStatus.CREATED.getReasonPhrase())) + .andExpect(jsonPath("$.result").value(ResponseResult.ROOM_CREATION_SUCCESS.getDescription())) + .andExpect(jsonPath("$.data.roomCode").value(roomCode.getRoomCode())) + .andDo(document("create-room-success", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestFields( + fieldWithPath("title").type(JsonFieldType.STRING).description("제목"), + fieldWithPath("capacity").type(JsonFieldType.NUMBER).description("정원"), + fieldWithPath("password").type(JsonFieldType.STRING).description("비밀번호").optional() + ), + responseFields( + fieldWithPath("code").type(JsonFieldType.NUMBER).description("코드"), + fieldWithPath("status").type(JsonFieldType.STRING).description("상태"), + fieldWithPath("result").type(JsonFieldType.STRING).description("결과"), + fieldWithPath("data").type(JsonFieldType.OBJECT).description("응답 데이터"), + fieldWithPath("data.roomCode").type(JsonFieldType.STRING).description("방 식별 코드") + ) + )); + } + + @Test + @DisplayName("방 생성 실패: 요청 데이터 오류가 발생했습니다") + void createRoomFail_RoomSettingError() { + // given + + // when + + // then + + } + + @Test + @DisplayName("방 생성 실패: 다수의 방에 참가할 수 없습니다") + void createRoomFail_SingleRoomParticipantViolation() { + // given + + // when + + // then + + } + +} From 622257edefa0b6d597e836695c9870bea4592055 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 16:43:06 +0900 Subject: [PATCH 56/70] =?UTF-8?q?docs:=20optional=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../restdocs/templates/request-fields.snippet | 14 ++++++++++++++ .../restdocs/templates/response-fields.snippet | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/test/resources/org/springframework/restdocs/templates/request-fields.snippet create mode 100644 src/test/resources/org/springframework/restdocs/templates/response-fields.snippet diff --git a/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet b/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet new file mode 100644 index 0000000..16960f2 --- /dev/null +++ b/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet @@ -0,0 +1,14 @@ +==== Request Fields +|=== +|Path|Type|Optional|Description + +{{#fields}} + +|{{#tableCellContent}}`+{{path}}+`{{/tableCellContent}} +|{{#tableCellContent}}`+{{type}}+`{{/tableCellContent}} +|{{#tableCellContent}}{{#optional}}O{{/optional}}{{/tableCellContent}} +|{{#tableCellContent}}{{description}}{{/tableCellContent}} + +{{/fields}} + +|=== diff --git a/src/test/resources/org/springframework/restdocs/templates/response-fields.snippet b/src/test/resources/org/springframework/restdocs/templates/response-fields.snippet new file mode 100644 index 0000000..80008b7 --- /dev/null +++ b/src/test/resources/org/springframework/restdocs/templates/response-fields.snippet @@ -0,0 +1,14 @@ +==== Response Fields +|=== +|Path|Type|Optional|Description + +{{#fields}} + +|{{#tableCellContent}}`+{{path}}+`{{/tableCellContent}} +|{{#tableCellContent}}`+{{type}}+`{{/tableCellContent}} +|{{#tableCellContent}}{{#optional}}O{{/optional}}{{/tableCellContent}} +|{{#tableCellContent}}{{description}}{{/tableCellContent}} + +{{/fields}} + +|=== From 51889052527b205221c7905214df6bf84e7aedc4 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 16:43:42 +0900 Subject: [PATCH 57/70] =?UTF-8?q?docs:=20API=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20-=20=EB=B0=A9=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=84=B1=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/api/room.adoc | 15 +++++++++++++++ src/docs/asciidoc/index.adoc | 13 +++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/docs/asciidoc/api/room.adoc create mode 100644 src/docs/asciidoc/index.adoc diff --git a/src/docs/asciidoc/api/room.adoc b/src/docs/asciidoc/api/room.adoc new file mode 100644 index 0000000..671ddb1 --- /dev/null +++ b/src/docs/asciidoc/api/room.adoc @@ -0,0 +1,15 @@ +[[Room-API]] +== Room API + +[[create-room-success]] +=== 방 생성 성공 + +==== HTTP Request + +include::{snippets}/create-room-success/http-request.adoc[] +include::{snippets}/create-room-success/request-fields.adoc[] + +==== HTTP Response + +include::{snippets}/create-room-success/http-response.adoc[] +include::{snippets}/create-room-success/response-fields.adoc[] diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc new file mode 100644 index 0000000..40d4274 --- /dev/null +++ b/src/docs/asciidoc/index.adoc @@ -0,0 +1,13 @@ +ifndef::snippets[] +:snippets: ../../build/generated-snippets +endif::[] + += YouTogether API Document +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: left +:toclevels: 2 +:sectlinks: + +include::api/room.adoc[] From f51af908d11a74f1af4a54987e564e00bd7ff0b3 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 16:55:58 +0900 Subject: [PATCH 58/70] =?UTF-8?q?test:=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?-=20=EB=B0=A9=20=EC=83=9D=EC=84=B1=20=EC=8B=A4=ED=8C=A8=20?= =?UTF-8?q?=EC=98=88=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 요청 데이터에서 오류가 발생한 경우에 대한 예제를 추가합니다. (BindException.class) --- .../room/presentation/RoomControllerTest.java | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java b/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java index 302b222..67f72cc 100644 --- a/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java +++ b/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java @@ -76,13 +76,43 @@ void createRoomSuccess() throws Exception { @Test @DisplayName("방 생성 실패: 요청 데이터 오류가 발생했습니다") - void createRoomFail_RoomSettingError() { + void createRoomFail_RoomSettingError() throws Exception { // given + // Setting up request data for creating a room + RoomSettings roomSettings = RoomSettings.builder() + .title(" ") + .capacity(11) + .password("a1b2") + .build(); - // when - - // then - + // when / then + mockMvc.perform(post("/rooms") + .content(objectMapper.writeValueAsString(roomSettings)) + .contentType(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isBadRequest()) + .andExpect(cookie().doesNotExist(cookieProperties.getName())) + .andExpect(jsonPath("$.code").value(HttpStatus.BAD_REQUEST.value())) + .andExpect(jsonPath("$.status").value(HttpStatus.BAD_REQUEST.getReasonPhrase())) + .andExpect(jsonPath("$.result").value(ResponseResult.EXCEPTION_OCCURRED.getDescription())) + .andExpect(jsonPath("$.data").isArray()) + .andDo(document("create-room-fail-room-setting-error", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestFields( + fieldWithPath("title").type(JsonFieldType.STRING).description("제목"), + fieldWithPath("capacity").type(JsonFieldType.NUMBER).description("정원"), + fieldWithPath("password").type(JsonFieldType.STRING).description("비밀번호").optional() + ), + responseFields( + fieldWithPath("code").type(JsonFieldType.NUMBER).description("코드"), + fieldWithPath("status").type(JsonFieldType.STRING).description("상태"), + fieldWithPath("result").type(JsonFieldType.STRING).description("결과"), + fieldWithPath("data").type(JsonFieldType.ARRAY).description("응답 데이터"), + fieldWithPath("data[].type").type(JsonFieldType.STRING).description("오류 타입"), + fieldWithPath("data[].message").type(JsonFieldType.STRING).description("오류 메시지") + ) + )); } @Test From 58c21b359a92bbfa34c6d7eafe9c7ab1436874bb Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 16:56:29 +0900 Subject: [PATCH 59/70] =?UTF-8?q?docs:=20API=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20-=20=EB=B0=A9=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=8B=A4=ED=8C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 요청 데이터에서 오류가 발생한 경우에 대한 예제를 추가합니다. (BindException.class) --- src/docs/asciidoc/api/room.adoc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/docs/asciidoc/api/room.adoc b/src/docs/asciidoc/api/room.adoc index 671ddb1..4535374 100644 --- a/src/docs/asciidoc/api/room.adoc +++ b/src/docs/asciidoc/api/room.adoc @@ -13,3 +13,16 @@ include::{snippets}/create-room-success/request-fields.adoc[] include::{snippets}/create-room-success/http-response.adoc[] include::{snippets}/create-room-success/response-fields.adoc[] + +[[create-room-fail-room-setting-error]] +=== 방 생성 실패: 요청 데이터 오류가 발생했습니다 + +==== HTTP Request + +include::{snippets}/create-room-fail-room-setting-error/http-request.adoc[] +include::{snippets}/create-room-fail-room-setting-error/request-fields.adoc[] + +==== HTTP Response + +include::{snippets}/create-room-fail-room-setting-error/http-response.adoc[] +include::{snippets}/create-room-fail-room-setting-error/response-fields.adoc[] From 33748c4e2d678a352f4ef25b1d9d6610989cefd4 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 17:17:04 +0900 Subject: [PATCH 60/70] =?UTF-8?q?test:=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?-=20=EB=B0=A9=20=EC=83=9D=EC=84=B1=20=EC=8B=A4=ED=8C=A8=20?= =?UTF-8?q?=EC=98=88=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 세션 쿠키를 갖고 있다는 것은 이미 방에 참가 중임을 암시합니다. 따라서 새로운 방을 생성할 수 없습니다. --- .../room/presentation/RoomControllerTest.java | 48 +++++++++++++++++-- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java b/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java index 67f72cc..a305245 100644 --- a/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java +++ b/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java @@ -7,6 +7,7 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.*; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import static site.youtogether.exception.ErrorType.*; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -14,7 +15,9 @@ import org.springframework.http.MediaType; import org.springframework.restdocs.payload.JsonFieldType; +import jakarta.servlet.http.Cookie; import site.youtogether.RestDocsSupport; +import site.youtogether.exception.room.SingleRoomParticipationViolationException; import site.youtogether.room.dto.RoomCode; import site.youtogether.room.dto.RoomSettings; import site.youtogether.util.api.ResponseResult; @@ -117,13 +120,48 @@ void createRoomFail_RoomSettingError() throws Exception { @Test @DisplayName("방 생성 실패: 다수의 방에 참가할 수 없습니다") - void createRoomFail_SingleRoomParticipantViolation() { + void createRoomFail_SingleRoomParticipantViolation() throws Exception { // given + // Setting up session cookie and request data for creating a room + // This indicates that a session cookie is already present, implying participation in a room + Cookie sessionCookie = new Cookie(cookieProperties.getName(), "a85192c998454a1ea055"); + RoomSettings roomSettings = RoomSettings.builder() + .title("재밌는 쇼츠 같이 보기") + .capacity(10) + .password(null) + .build(); - // when - - // then - + // when / then + mockMvc.perform(post("/rooms") + .content(objectMapper.writeValueAsString(roomSettings)) + .contentType(MediaType.APPLICATION_JSON) + .cookie(sessionCookie)) + .andDo(print()) + .andExpect(status().isBadRequest()) + .andExpect(cookie().doesNotExist(cookieProperties.getName())) + .andExpect(jsonPath("$.code").value(SINGLE_ROOM_PARTICIPATION_VIOLATION.getStatus().value())) + .andExpect(jsonPath("$.status").value(SINGLE_ROOM_PARTICIPATION_VIOLATION.getStatus().getReasonPhrase())) + .andExpect(jsonPath("$.result").value(ResponseResult.EXCEPTION_OCCURRED.getDescription())) + .andExpect(jsonPath("$.data").isArray()) + .andExpect(jsonPath("$.data[0].type").value(SingleRoomParticipationViolationException.class.getSimpleName())) + .andExpect(jsonPath("$.data[0].message").value(SINGLE_ROOM_PARTICIPATION_VIOLATION.getMessage())) + .andDo(document("create-room-fail-single-room-participant-violation", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestFields( + fieldWithPath("title").type(JsonFieldType.STRING).description("제목"), + fieldWithPath("capacity").type(JsonFieldType.NUMBER).description("정원"), + fieldWithPath("password").type(JsonFieldType.STRING).description("비밀번호").optional() + ), + responseFields( + fieldWithPath("code").type(JsonFieldType.NUMBER).description("코드"), + fieldWithPath("status").type(JsonFieldType.STRING).description("상태"), + fieldWithPath("result").type(JsonFieldType.STRING).description("결과"), + fieldWithPath("data").type(JsonFieldType.ARRAY).description("응답 데이터"), + fieldWithPath("data[].type").type(JsonFieldType.STRING).description("오류 타입"), + fieldWithPath("data[].message").type(JsonFieldType.STRING).description("오류 메시지") + ) + )); } } From 9be2447509af0597f7aff17ea9d0ee8eba72b5ed Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 17:17:33 +0900 Subject: [PATCH 61/70] =?UTF-8?q?docs:=20API=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20-=20=EB=B0=A9=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=8B=A4=ED=8C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 세션 쿠키를 갖고 있다는 것은 이미 방에 참가 중임을 암시합니다. 따라서 새로운 방을 생성할 수 없습니다. --- src/docs/asciidoc/api/room.adoc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/docs/asciidoc/api/room.adoc b/src/docs/asciidoc/api/room.adoc index 4535374..e50ec41 100644 --- a/src/docs/asciidoc/api/room.adoc +++ b/src/docs/asciidoc/api/room.adoc @@ -26,3 +26,16 @@ include::{snippets}/create-room-fail-room-setting-error/request-fields.adoc[] include::{snippets}/create-room-fail-room-setting-error/http-response.adoc[] include::{snippets}/create-room-fail-room-setting-error/response-fields.adoc[] + +[[create-room-fail-single-room-participant-violation]] +=== 방 생성 실패: 다수의 방에 참가할 수 없습니다 + +==== HTTP Request + +include::{snippets}/create-room-fail-single-room-participant-violation/http-request.adoc[] +include::{snippets}/create-room-fail-single-room-participant-violation/request-fields.adoc[] + +==== HTTP Response + +include::{snippets}/create-room-fail-single-room-participant-violation/http-response.adoc[] +include::{snippets}/create-room-fail-single-room-participant-violation/response-fields.adoc[] From ff569237edff96acb89b78e890c99d5ec30a2210 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 17:58:34 +0900 Subject: [PATCH 62/70] =?UTF-8?q?style:=20API=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=ED=98=95=EC=8B=9D=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20CSS=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/api/room.adoc | 4 ++ src/docs/asciidoc/docinfo.html | 79 +++++++++++++++++++++++++++++++++ src/docs/asciidoc/index.adoc | 1 + 3 files changed, 84 insertions(+) create mode 100644 src/docs/asciidoc/docinfo.html diff --git a/src/docs/asciidoc/api/room.adoc b/src/docs/asciidoc/api/room.adoc index e50ec41..9248ebd 100644 --- a/src/docs/asciidoc/api/room.adoc +++ b/src/docs/asciidoc/api/room.adoc @@ -14,6 +14,8 @@ include::{snippets}/create-room-success/request-fields.adoc[] include::{snippets}/create-room-success/http-response.adoc[] include::{snippets}/create-room-success/response-fields.adoc[] +{nbsp} + [[create-room-fail-room-setting-error]] === 방 생성 실패: 요청 데이터 오류가 발생했습니다 @@ -27,6 +29,8 @@ include::{snippets}/create-room-fail-room-setting-error/request-fields.adoc[] include::{snippets}/create-room-fail-room-setting-error/http-response.adoc[] include::{snippets}/create-room-fail-room-setting-error/response-fields.adoc[] +{nbsp} + [[create-room-fail-single-room-participant-violation]] === 방 생성 실패: 다수의 방에 참가할 수 없습니다 diff --git a/src/docs/asciidoc/docinfo.html b/src/docs/asciidoc/docinfo.html new file mode 100644 index 0000000..f979079 --- /dev/null +++ b/src/docs/asciidoc/docinfo.html @@ -0,0 +1,79 @@ + + + + + + + + + diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index 40d4274..93638dc 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -9,5 +9,6 @@ endif::[] :toc: left :toclevels: 2 :sectlinks: +:docinfo: shared include::api/room.adoc[] From 497807fcfe3626b31e5ce65887b9c1c308a5dafa Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 21:11:39 +0900 Subject: [PATCH 63/70] =?UTF-8?q?refactor:=20=EA=B0=99=EC=9D=80=20?= =?UTF-8?q?=EC=97=AD=ED=95=A0=EC=9D=84=20=EC=88=98=ED=96=89=ED=95=98?= =?UTF-8?q?=EB=8A=94=202=EA=B0=9C=EC=9D=98=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=ED=95=98=EB=82=98=EB=A1=9C=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/room/Room.java | 4 +++- .../room/presentation/RoomController.java | 2 +- .../site/youtogether/util/AppConstants.java | 2 ++ .../java/site/youtogether/util/RandomUtil.java | 18 +++--------------- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/main/java/site/youtogether/room/Room.java b/src/main/java/site/youtogether/room/Room.java index da22df3..641551a 100644 --- a/src/main/java/site/youtogether/room/Room.java +++ b/src/main/java/site/youtogether/room/Room.java @@ -1,5 +1,7 @@ package site.youtogether.room; +import static site.youtogether.util.AppConstants.*; + import java.util.HashMap; import java.util.Map; @@ -26,7 +28,7 @@ public class Room { @Builder public Room(String title, int capacity, String password, User host) { - this.code = RandomUtil.generateRoomCode(); + this.code = RandomUtil.generateRandomCode(ROOM_CODE_LENGTH); this.capacity = capacity; this.title = title; this.password = password; diff --git a/src/main/java/site/youtogether/room/presentation/RoomController.java b/src/main/java/site/youtogether/room/presentation/RoomController.java index 32413f9..8e2ba32 100644 --- a/src/main/java/site/youtogether/room/presentation/RoomController.java +++ b/src/main/java/site/youtogether/room/presentation/RoomController.java @@ -41,7 +41,7 @@ public ResponseEntity> createRoom(@CookieValue(value = SES } // Generate a new session code and set it as a cookie. - ResponseCookie cookie = ResponseCookie.from(cookieProperties.getName(), RandomUtil.generateSessionCode()) + ResponseCookie cookie = ResponseCookie.from(cookieProperties.getName(), RandomUtil.generateRandomCode(SESSION_CODE_LENGTH)) .domain(cookieProperties.getDomain()) .path(cookieProperties.getPath()) .sameSite(cookieProperties.getSameSite()) diff --git a/src/main/java/site/youtogether/util/AppConstants.java b/src/main/java/site/youtogether/util/AppConstants.java index 8c25d54..463cd5c 100644 --- a/src/main/java/site/youtogether/util/AppConstants.java +++ b/src/main/java/site/youtogether/util/AppConstants.java @@ -10,5 +10,7 @@ public final class AppConstants { public static final String ROOM_KEY_PREFIX = "room:"; public static final String USER_KEY_PREFIX = "user:"; public static final String SESSION_COOKIE_NAME = "YTSession"; + public static final int ROOM_CODE_LENGTH = 10; + public static final int SESSION_CODE_LENGTH = 20; } diff --git a/src/main/java/site/youtogether/util/RandomUtil.java b/src/main/java/site/youtogether/util/RandomUtil.java index 5deb204..b072174 100644 --- a/src/main/java/site/youtogether/util/RandomUtil.java +++ b/src/main/java/site/youtogether/util/RandomUtil.java @@ -11,25 +11,13 @@ public final class RandomUtil { /** - * generate random room code - * length is 10 + * generate random code * using a-z A-Z 0-9 */ - public static String generateRoomCode() { + public static String generateRandomCode(int length) { String randomString = UUID.randomUUID().toString().replaceAll("-", ""); - return randomString.substring(0, 10); - } - - /** - * generate random session code - * length is 20 - * using a-z A-Z 0-9 - */ - public static String generateSessionCode() { - String randomString = UUID.randomUUID().toString().replaceAll("-", ""); - - return randomString.substring(0, 20); + return randomString.substring(0, length); } /** From 9801d233003098885e3a5c110b718b21d534b153 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 21:48:43 +0900 Subject: [PATCH 64/70] =?UTF-8?q?fix:=20[Room]=20RedisHash=20deserialize?= =?UTF-8?q?=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EA=B8=B0=EB=B3=B8=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9E=90=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20final=20?= =?UTF-8?q?=ED=82=A4=EC=9B=8C=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/room/Room.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/site/youtogether/room/Room.java b/src/main/java/site/youtogether/room/Room.java index 641551a..02f943a 100644 --- a/src/main/java/site/youtogether/room/Room.java +++ b/src/main/java/site/youtogether/room/Room.java @@ -8,23 +8,26 @@ import org.springframework.data.annotation.Id; import org.springframework.data.redis.core.RedisHash; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import site.youtogether.user.User; import site.youtogether.util.RandomUtil; @RedisHash(value = "room") +@NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter public class Room { @Id - private final String code; + private String code; - private final int capacity; - private final String title; - private final String password; - private final String host; - private final Map participants = new HashMap<>(10); + private int capacity; + private String title; + private String password; + private User host; + private Map participants = new HashMap<>(10); @Builder public Room(String title, int capacity, String password, User host) { @@ -32,7 +35,7 @@ public Room(String title, int capacity, String password, User host) { this.capacity = capacity; this.title = title; this.password = password; - this.host = host.getSessionCode(); + this.host = host; participants.put(host.getSessionCode(), host); } From 933dd66076ca9da93cef4f878b27908d41443106 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 21:58:14 +0900 Subject: [PATCH 65/70] =?UTF-8?q?test:=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84=20-=20?= =?UTF-8?q?=EB=B0=A9=20=EC=83=9D=EC=84=B1=20=EC=84=B1=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../room/application/RoomServiceTest.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/test/java/site/youtogether/room/application/RoomServiceTest.java diff --git a/src/test/java/site/youtogether/room/application/RoomServiceTest.java b/src/test/java/site/youtogether/room/application/RoomServiceTest.java new file mode 100644 index 0000000..8152fda --- /dev/null +++ b/src/test/java/site/youtogether/room/application/RoomServiceTest.java @@ -0,0 +1,69 @@ +package site.youtogether.room.application; + +import static org.assertj.core.api.Assertions.*; +import static site.youtogether.util.AppConstants.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import site.youtogether.IntegrationTestSupport; +import site.youtogether.room.Room; +import site.youtogether.room.dto.RoomCode; +import site.youtogether.room.dto.RoomSettings; +import site.youtogether.room.infrastructure.RoomStorage; +import site.youtogether.user.Role; +import site.youtogether.user.User; +import site.youtogether.user.infrastructure.UserStorage; + +class RoomServiceTest extends IntegrationTestSupport { + + @Autowired + private RoomService roomService; + + @Autowired + private RoomStorage roomStorage; + + @Autowired + private UserStorage userStorage; + + @BeforeEach + void clean() { + roomStorage.deleteAll(); + userStorage.deleteAll(); + } + + @Test + @DisplayName("새로운 방과 해당 방의 HOST를 생성할 수 있다") + void createSuccess() { + // given + String sessionCode = "7644a835e52e45dfa385"; + String address = "127.0.0.1"; + RoomSettings roomSettings = RoomSettings.builder() + .capacity(10) + .title("재밌는 쇼츠 같이 보기") + .password(null) + .build(); + + // when + RoomCode roomCode = roomService.create(sessionCode, address, roomSettings); + + // then + Room room = roomStorage.findById(roomCode.getRoomCode()).orElseThrow(); + User user = userStorage.findById(sessionCode).orElseThrow(); + + assertThat(roomCode.getRoomCode()).hasSize(ROOM_CODE_LENGTH); + assertThat(roomCode.getRoomCode()).isEqualTo(room.getCode()); + assertThat(room.getCapacity()).isEqualTo(10); + assertThat(room.getTitle()).isEqualTo("재밌는 쇼츠 같이 보기"); + assertThat(room.getPassword()).isNull(); + assertThat(room.getHost().getSessionCode()).isEqualTo(sessionCode); + assertThat(room.getParticipants()).hasSize(1); + assertThat(user.getSessionCode()).isEqualTo(sessionCode); + assertThat(user.getAddress()).isEqualTo(address); + assertThat(user.getNickname()).isNotBlank(); + assertThat(user.getRole()).isEqualTo(Role.HOST); + } + +} From d8b68d066c8cbdcbe4b4b2d27f5d535d1c80907d Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 21:59:33 +0900 Subject: [PATCH 66/70] =?UTF-8?q?style:=20builder=20=EC=88=9C=EC=84=9C=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../room/presentation/RoomControllerTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java b/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java index a305245..e1bf9f2 100644 --- a/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java +++ b/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java @@ -30,8 +30,8 @@ void createRoomSuccess() throws Exception { // given // Setting up request data for creating a room RoomSettings roomSettings = RoomSettings.builder() - .title("재밌는 쇼츠 같이 보기") .capacity(10) + .title("재밌는 쇼츠 같이 보기") .password(null) .build(); @@ -63,8 +63,8 @@ void createRoomSuccess() throws Exception { preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), requestFields( - fieldWithPath("title").type(JsonFieldType.STRING).description("제목"), fieldWithPath("capacity").type(JsonFieldType.NUMBER).description("정원"), + fieldWithPath("title").type(JsonFieldType.STRING).description("제목"), fieldWithPath("password").type(JsonFieldType.STRING).description("비밀번호").optional() ), responseFields( @@ -83,8 +83,8 @@ void createRoomFail_RoomSettingError() throws Exception { // given // Setting up request data for creating a room RoomSettings roomSettings = RoomSettings.builder() - .title(" ") .capacity(11) + .title(" ") .password("a1b2") .build(); @@ -103,8 +103,8 @@ void createRoomFail_RoomSettingError() throws Exception { preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), requestFields( - fieldWithPath("title").type(JsonFieldType.STRING).description("제목"), fieldWithPath("capacity").type(JsonFieldType.NUMBER).description("정원"), + fieldWithPath("title").type(JsonFieldType.STRING).description("제목"), fieldWithPath("password").type(JsonFieldType.STRING).description("비밀번호").optional() ), responseFields( @@ -126,8 +126,8 @@ void createRoomFail_SingleRoomParticipantViolation() throws Exception { // This indicates that a session cookie is already present, implying participation in a room Cookie sessionCookie = new Cookie(cookieProperties.getName(), "a85192c998454a1ea055"); RoomSettings roomSettings = RoomSettings.builder() - .title("재밌는 쇼츠 같이 보기") .capacity(10) + .title("재밌는 쇼츠 같이 보기") .password(null) .build(); @@ -149,8 +149,8 @@ void createRoomFail_SingleRoomParticipantViolation() throws Exception { preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), requestFields( - fieldWithPath("title").type(JsonFieldType.STRING).description("제목"), fieldWithPath("capacity").type(JsonFieldType.NUMBER).description("정원"), + fieldWithPath("title").type(JsonFieldType.STRING).description("제목"), fieldWithPath("password").type(JsonFieldType.STRING).description("비밀번호").optional() ), responseFields( From 1528c7f8f50298080c962bb8e6ac398e32af20f5 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 22:08:27 +0900 Subject: [PATCH 67/70] chore: Add configuration for test job with Redis service --- .github/workflows/test-report.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/test-report.yml b/.github/workflows/test-report.yml index e607be4..4783cdc 100644 --- a/.github/workflows/test-report.yml +++ b/.github/workflows/test-report.yml @@ -16,6 +16,12 @@ jobs: test: runs-on: ubuntu-latest + services: + redis: + image: redis:latest + ports: + - 6380:6379 + steps: - name: Check out uses: actions/checkout@v3 From be11bd7558b660c3f0b80232512b8fb4b0f84291 Mon Sep 17 00:00:00 2001 From: yeonise Date: Mon, 18 Mar 2024 22:20:31 +0900 Subject: [PATCH 68/70] chore: Add script to copy application.yml files --- .github/workflows/test-report.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/test-report.yml b/.github/workflows/test-report.yml index 4783cdc..741cec5 100644 --- a/.github/workflows/test-report.yml +++ b/.github/workflows/test-report.yml @@ -32,6 +32,16 @@ jobs: distribution: 'temurin' java-version: '17' + - name: Copy application.yml + run: | + mkdir ./src/main/resources + touch ./src/main/resources/application.yml + echo "${{ secrets.APPLICATION }}" > ./src/main/resources/application.yml + touch ./src/main/resources/application-test.yml + echo "${{ secrets.APPLICATION_TEST }}" > ./src/main/resources/application-test.yml + touch ./src/main/resources/application-release.yml + echo "${{ secrets.APPLICATION_RELEASE }}" > ./src/main/resources/application-release.yml + - name: Cache Gradle packages uses: actions/cache@v3 with: From 888a000116476d9d8290353f8a17525c0109f050 Mon Sep 17 00:00:00 2001 From: yeonise Date: Wed, 20 Mar 2024 20:43:55 +0900 Subject: [PATCH 69/70] =?UTF-8?q?test:=20orElseThrow()=20=E2=86=92=20get()?= =?UTF-8?q?=EC=9D=84=20=ED=86=B5=ED=95=B4=20=EA=B0=92=EC=9D=84=20=EA=B0=80?= =?UTF-8?q?=EC=A0=B8=EC=98=A4=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../site/youtogether/room/application/RoomServiceTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/site/youtogether/room/application/RoomServiceTest.java b/src/test/java/site/youtogether/room/application/RoomServiceTest.java index 8152fda..7a8ac5a 100644 --- a/src/test/java/site/youtogether/room/application/RoomServiceTest.java +++ b/src/test/java/site/youtogether/room/application/RoomServiceTest.java @@ -50,8 +50,8 @@ void createSuccess() { RoomCode roomCode = roomService.create(sessionCode, address, roomSettings); // then - Room room = roomStorage.findById(roomCode.getRoomCode()).orElseThrow(); - User user = userStorage.findById(sessionCode).orElseThrow(); + Room room = roomStorage.findById(roomCode.getRoomCode()).get(); + User user = userStorage.findById(sessionCode).get(); assertThat(roomCode.getRoomCode()).hasSize(ROOM_CODE_LENGTH); assertThat(roomCode.getRoomCode()).isEqualTo(room.getCode()); From a8b230dc2bf9d09c7d6379e4aea3fee1e7709f6e Mon Sep 17 00:00:00 2001 From: yeonise Date: Wed, 20 Mar 2024 21:02:16 +0900 Subject: [PATCH 70/70] =?UTF-8?q?feat:=20[RoomSettings]=20validation=20mes?= =?UTF-8?q?sage=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/site/youtogether/room/dto/RoomSettings.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/site/youtogether/room/dto/RoomSettings.java b/src/main/java/site/youtogether/room/dto/RoomSettings.java index e146c9d..c9f26ec 100644 --- a/src/main/java/site/youtogether/room/dto/RoomSettings.java +++ b/src/main/java/site/youtogether/room/dto/RoomSettings.java @@ -13,14 +13,14 @@ @Getter public class RoomSettings { - @NotBlank - @Size(min = 1, max = 30) + @NotBlank(message = "공백이 아닌 문자를 1개 이상 입력해 주세요") + @Size(min = 1, max = 30, message = "제목은 {min}자 이상 {max}자 이하로 입력해 주세요") private String title; - @Range(min = 2, max = 10) + @Range(min = 2, max = 10, message = "정원은 {min}명 이상 {max}명 이하로 입력해 주세요") private int capacity; - @Pattern(regexp = "^[0-9a-zA-Z]{5,10}$") + @Pattern(regexp = "^[0-9a-zA-Z]{5,10}$", message = "비밀번호는 5자 이상 10자 이하의 영문 또는 숫자로 입력해 주세요") private String password; @Builder