diff --git a/.github/workflows/sprint-mission1-pr-test.yml b/.github/workflows/sprint-mission1-pr-test.yml index 893253cb7..1799da75f 100644 --- a/.github/workflows/sprint-mission1-pr-test.yml +++ b/.github/workflows/sprint-mission1-pr-test.yml @@ -3,7 +3,7 @@ name: sprint mission 1 PR Test on: push: branches: - - 'part1-백재우-sprint1' + - '*' pull_request: branches: - 'part1-백재우' diff --git a/README.md b/README.md index 19562fc1b..a2c8b8195 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,22 @@ - [생성자 초기화 시에 값이 없음을 나타내주어야 할까?](https://github.com/jaewoo9797/TIL/blob/main/java/%E2%9C%85At%20Initialized%20field%20null.md) - [static factory method 나도 한 번 사용해보자!](https://github.com/jaewoo9797/TIL/blob/main/java/%E2%9C%85%20%5BJAVA%5D%20%EC%A0%95%EC%A0%81%20%ED%8C%A9%ED%86%A0%EB%A6%AC%20%EB%A9%94%EC%86%8C%EB%93%9C.md) - [Optional method `of`, `ofNullable` 어떻게 사용하는 걸까?](https://github.com/jaewoo9797/TIL/blob/main/java/%E2%9C%85%20Optional.of%20%EC%99%80%20Optional.ofNullalbe.md) + +## 🌱 스프린트 미션 2 +### 고민하고 학습했던 내용 정리 +요구사항에 파일에 저장, 수정, 삭제 등의 FileRepository 를 구현해야 했다. `File` 관련 기능을 처음 접해 학습 +- [File-STUDY](https://github.com/jaewoo9797/file-study) + + +## 🌱 스프린트 미션 3 +### 고민하고 학습했던 내용 정리 + + +## 🌱 스프린트 미션 4 +### 고민하고 학습했던 내용 정리 +- [RequestMapping](https://github.com/jaewoo9797/TIL/blob/main/Spring/boot/RequestMapping.md) + +모든 요청을 `@RequestMapping`으로 구현하였는데, 왜 이런 요구사항이 있었는지 고민하고, 다른 방법은 없는지 알아보았습니다. +이에 `@RequestMapping`과 각각의 short cut 어노테이션과의 차이점을 알아보고, 속성에 관해서 정리. + +- []() \ No newline at end of file diff --git a/codeit-bootcamp-spring/1-sprint-mission/.gitattributes b/codeit-bootcamp-spring/1-sprint-mission/.gitattributes new file mode 100644 index 000000000..8af972cde --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/.gitattributes @@ -0,0 +1,3 @@ +/gradlew text eol=lf +*.bat text eol=crlf +*.jar binary diff --git a/codeit-bootcamp-spring/1-sprint-mission/.gitignore b/codeit-bootcamp-spring/1-sprint-mission/.gitignore index babb7212a..c2065bc26 100644 --- a/codeit-bootcamp-spring/1-sprint-mission/.gitignore +++ b/codeit-bootcamp-spring/1-sprint-mission/.gitignore @@ -1,22 +1,11 @@ +HELP.md .gradle build/ !gradle/wrapper/gradle-wrapper.jar !**/src/main/**/build/ !**/src/test/**/build/ -### IntelliJ IDEA ### -.idea/modules.xml -.idea/jarRepositories.xml -.idea/compiler.xml -.idea/libraries/ -*.iws -*.iml -*.ipr -out/ -!**/src/main/**/out/ -!**/src/test/**/out/ - -### Eclipse ### +### STS ### .apt_generated .classpath .factorypath @@ -28,6 +17,15 @@ bin/ !**/src/main/**/bin/ !**/src/test/**/bin/ +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + ### NetBeans ### /nbproject/private/ /nbbuild/ @@ -37,11 +35,3 @@ bin/ ### VS Code ### .vscode/ - -### Mac OS ### -.DS_Store - - -/build -/build/test-results/ -/build/reports/ diff --git a/codeit-bootcamp-spring/1-sprint-mission/README.md b/codeit-bootcamp-spring/1-sprint-mission/README.md index afa5c7d95..e69de29bb 100644 --- a/codeit-bootcamp-spring/1-sprint-mission/README.md +++ b/codeit-bootcamp-spring/1-sprint-mission/README.md @@ -1,93 +0,0 @@ -간단하게 얼른 하고 끝내버리자. -1. 서비스 구현체를 구현하라. -> 기존 유저 서비스의 구현 - -## 로직 생각해보기 -객체 직렬화를 사용해서 할 경우, 바이너리로 저장된다. 수정을 하고 싶은 경우 특정 부분만 삭제하거나, 수정하는 것이 어렵다 -=> 모든 저장 내용을 읽어들이고 파일을 새롭게 쓰는 방법이 쉬운 방법이다. - -성능적으로 보면, 매우 안좋다고 볼 수 있다. 만약 파일에 저장된 데이터가 매우 많을 경우를 생각하면 읽고 새롭게 쓰고 하면 성능저하가 당연하다. - -데이터가 많을 경우 데이터베이스를 이용하는 것이 좋다. - -요구사항 -기본 요구사항 -File IO를 통한 데이터 영속화 -- [ ] 다음의 조건을 만족하는 서비스 인터페이스의 구현체를 작성하세요. - -- [ ] 클래스 패키지명: com.sprint.mission.discodeit.service.file - -- [ ] 클래스 네이밍 규칙: File[인터페이스 이름] - -- [ ] JCF 대신 FileIO와 객체 직렬화를 활용해 메소드를 구현하세요. - -객체 직렬화/역직렬화 가이드 - -- [ ] Application에서 서비스 구현체를 File*Service로 바꾸어 테스트해보세요. - -서비스 구현체 분석 -- [ ] JCF*Service 구현체와 File*Service 구현체를 비교하여 공통점과 차이점을 발견해보세요. -- [ ] "비즈니스 로직"과 관련된 코드를 식별해보세요. -- [ ] "저장 로직"과 관련된 코드를 식별해보세요. -레포지토리 설계 및 구현 -- [ ] "저장 로직"과 관련된 기능을 도메인 모델 별 인터페이스로 선언하세요. -- [ ] 인터페이스 패키지명: com.sprint.mission.discodeit.repository -- [ ] 인터페이스 네이밍 규칙: [도메인 모델 이름]Repository -- [ ] 다음의 조건을 만족하는 레포지토리 인터페이스의 구현체를 작성하세요. -- [ ] 클래스 패키지명: com.sprint.mission.discodeit.repository.jcf -- [ ] 클래스 네이밍 규칙: JCF[인터페이스 이름] -- [ ] 기존에 구현한 JCF*Service 구현체의 "저장 로직"과 관련된 코드를 참고하여 구현하세요. -- [ ] 다음의 조건을 만족하는 레포지토리 인터페이스의 구현체를 작성하세요. -- [ ] 클래스 패키지명: com.sprint.mission.discodeit.repository.file -- [ ] 클래스 네이밍 규칙: File[인터페이스 이름] -- [ ] 기존에 구현한 File*Service 구현체의 "저장 로직"과 관련된 코드를 참고하여 구현하세요. -심화 요구 사항 -관심사 분리를 통한 레이어 간 의존성 주입 -- [ ] 다음의 조건을 만족하는 서비스 인터페이스의 구현체를 작성하세요. -- [ ] 클래스 패키지명: com.sprint.mission.discodeit.service.basic -- [ ] 클래스 네이밍 규칙: Basic[인터페이스 이름] -- [ ] 기존에 구현한 서비스 구현체의 "비즈니스 로직"과 관련된 코드를 참고하여 구현하세요. -- [ ] 필요한 Repository 인터페이스를 필드로 선언하고 생성자를 통해 초기화하세요. -- [ ] "저장 로직"은 Repository 인터페이스 필드를 활용하세요. (직접 구현하지 마세요.) -- [ ] Basic*Service 구현체를 활용하여 테스트해보세요. -코드 템플릿 - -```java - - -public class JavaApplication { - static User setupUser(UserService userService) { - User user = userService.create("woody", "woody@codeit.com", "woody1234"); - return user; - } - - static Channel setupChannel(ChannelService channelService) { - Channel channel = channelService.create(ChannelType.PUBLIC, "공지", "공지 채널입니다."); - return channel; - } - - static void messageCreateTest(MessageService messageService, Channel channel, User author) { - Message message = messageService.create("안녕하세요.", channel.getId(), author.getId()); - System.out.println("메시지 생성: " + message.getId()); - } - - public static void main(String[] args) { - // 서비스 초기화 - // TODO Basic*Service 구현체를 초기화하세요. - UserService userService; - ChannelService channelService; - MessageService messageService; - - // 셋업 - User user = setupUser(userService); - Channel channel = setupChannel(channelService); - // 테스트 - messageCreateTest(messageService, channel, user); - } -} -``` - -- [ ] JCF*Repository 구현체를 활용하여 테스트해보세요. - -- [ ] File*Repository 구현체를 활용하여 테스트해보세요. - -- [ ] 이전에 작성했던 코드(JCF*Service 또는 File*Service)와 비교해 어떤 차이가 있는지 정리해보세요. \ No newline at end of file diff --git a/codeit-bootcamp-spring/1-sprint-mission/build.gradle b/codeit-bootcamp-spring/1-sprint-mission/build.gradle index 96c0ec188..f211234fa 100644 --- a/codeit-bootcamp-spring/1-sprint-mission/build.gradle +++ b/codeit-bootcamp-spring/1-sprint-mission/build.gradle @@ -1,32 +1,36 @@ plugins { id 'java' + id 'org.springframework.boot' version '3.4.0' + id 'io.spring.dependency-management' version '1.1.7' } group = 'com.sprint.mission' -version = '1.0-SNAPSHOT' +version = '0.0.1-SNAPSHOT' + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} repositories { mavenCentral() } dependencies { - testImplementation platform('org.junit:junit-bom:5.10.0') - testImplementation 'org.junit.jupiter:junit-jupiter' - - // https://mvnrepository.com/artifact/org.mockito/mockito-core - testImplementation 'org.mockito:mockito-core:4.11.0' - // https://mvnrepository.com/artifact/org.assertj/assertj-core - testImplementation 'org.assertj:assertj-core:3.24.2' - - // https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator - implementation 'org.hibernate.validator:hibernate-validator:8.0.2.Final' - // https://mvnrepository.com/artifact/org.glassfish.expressly/expressly - implementation 'org.glassfish.expressly:expressly:5.0.0' - // https://mvnrepository.com/artifact/com.google.guava/guava - implementation 'com.google.guava:guava:33.2.1-jre' - + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } -test { +tasks.named('test') { useJUnitPlatform() -} \ No newline at end of file +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/gradle/wrapper/gradle-wrapper.jar b/codeit-bootcamp-spring/1-sprint-mission/gradle/wrapper/gradle-wrapper.jar index 249e5832f..a4b76b953 100644 Binary files a/codeit-bootcamp-spring/1-sprint-mission/gradle/wrapper/gradle-wrapper.jar and b/codeit-bootcamp-spring/1-sprint-mission/gradle/wrapper/gradle-wrapper.jar differ diff --git a/codeit-bootcamp-spring/1-sprint-mission/gradle/wrapper/gradle-wrapper.properties b/codeit-bootcamp-spring/1-sprint-mission/gradle/wrapper/gradle-wrapper.properties index 5fcc82948..e18bc253b 100644 --- a/codeit-bootcamp-spring/1-sprint-mission/gradle/wrapper/gradle-wrapper.properties +++ b/codeit-bootcamp-spring/1-sprint-mission/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ -#Tue Jan 07 00:58:32 KST 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/codeit-bootcamp-spring/1-sprint-mission/gradlew b/codeit-bootcamp-spring/1-sprint-mission/gradlew index 1b6c78733..f5feea6d6 100644 --- a/codeit-bootcamp-spring/1-sprint-mission/gradlew +++ b/codeit-bootcamp-spring/1-sprint-mission/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +82,12 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +134,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +201,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -205,6 +217,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/codeit-bootcamp-spring/1-sprint-mission/gradlew.bat b/codeit-bootcamp-spring/1-sprint-mission/gradlew.bat index 107acd32c..9d21a2183 100644 --- a/codeit-bootcamp-spring/1-sprint-mission/gradlew.bat +++ b/codeit-bootcamp-spring/1-sprint-mission/gradlew.bat @@ -13,8 +13,10 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +27,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,13 +43,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -56,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -75,13 +78,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/codeit-bootcamp-spring/1-sprint-mission/settings.gradle b/codeit-bootcamp-spring/1-sprint-mission/settings.gradle index b71004546..2437dfb29 100644 --- a/codeit-bootcamp-spring/1-sprint-mission/settings.gradle +++ b/codeit-bootcamp-spring/1-sprint-mission/settings.gradle @@ -1,2 +1 @@ -rootProject.name = '1-sprint-mission' - +rootProject.name = 'discodeit' diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/DiscodeitApplication.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/DiscodeitApplication.java new file mode 100644 index 000000000..2ac54d9f3 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/DiscodeitApplication.java @@ -0,0 +1,12 @@ +package com.sprint.mission.discodeit; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DiscodeitApplication { + + public static void main(String[] args) { + SpringApplication.run(DiscodeitApplication.class, args); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/JavaApplication.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/JavaApplication.java deleted file mode 100644 index 77f17a2da..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/JavaApplication.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.sprint.mission.discodeit; - -import com.sprint.mission.discodeit.config.factory.ApplicationFileFactory; -import com.sprint.mission.discodeit.entity.channel.dto.ChannelResponse; -import com.sprint.mission.discodeit.entity.channel.dto.CreateNewChannelRequest; -import com.sprint.mission.discodeit.entity.message.dto.DirectMessageInfoResponse; -import com.sprint.mission.discodeit.entity.message.dto.SendDirectMessageRequest; -import com.sprint.mission.discodeit.entity.user.dto.RegisterUserRequest; -import com.sprint.mission.discodeit.entity.user.dto.UserInfoResponse; -import java.io.IOException; -import java.util.UUID; - -public class JavaApplication { - private static final ApplicationFileFactory app = ApplicationFileFactory.getInstance(); - - public static void main(String[] args) throws IOException { - UserInfoResponse user = registerUser(); - ChannelResponse channelResponse = registerChannel(user.uuid(), "스프링부트_1기"); - UserInfoResponse receiveMessageUserTemp = registerUser(); - DirectMessageInfoResponse sendDirectMessage = sendDirectMessage(user.uuid(), receiveMessageUserTemp.uuid(), "안녕하세요"); - } - - private static UserInfoResponse registerUser() { - var userService = app.getUserService(); - var registerRequest = new RegisterUserRequest("홍길동"); - return userService.register(registerRequest); - } - - private static ChannelResponse registerChannel(UUID userId, String channelName) { - var channelService = app.getChannelService(); - var channelCreateRequest = new CreateNewChannelRequest(userId, channelName); - return channelService.createChannelOrThrow(channelCreateRequest); - } - - private static DirectMessageInfoResponse sendDirectMessage(UUID sendUserId, UUID receiveUserId, String message) { - var directMessageService = app.getDirectMessageService(); - var sendDirectMessageRequest = new SendDirectMessageRequest(sendUserId, receiveUserId, message); - return directMessageService.sendMessage(sendDirectMessageRequest); - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/error/ErrorCode.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/error/ErrorCode.java deleted file mode 100644 index 4935ca0f4..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/error/ErrorCode.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.sprint.mission.discodeit.common.error; - -public enum ErrorCode { - - /** - * 1000 ~ 1999 User 관련 에러 - */ - USER_NOT_FOUND(1_000, "존재하지 않는 유저입니다."), - - USER_NAME_NULL(1_001, "유저의 이름은 반드시 존재해야합니다."), - - USER_NAME_LENGTH_OUT_OF_RANGE(1_002, "유저 이름의 길이 제한을 확인해주세요."), - - USER_NOT_PARTICIPATED_CHANNEL(1_003, "유저가 참여하지 않은 방입니다."), - - /** - * 2000 ~ 2999 Channel 관련 에러 - */ - CHANNEL_NOT_FOUND(2_000, "존재하지 않는 채널입니다."), - CHANNEL_NOT_EQUAL_CREATOR(2_001, "채널을 생성한 사람만 채널이름을 변경할 수 있습니다."), - ; - - private final int errorCode; - private final String errorMessage; - - - ErrorCode(int errorCode, String message) { - this.errorCode = errorCode; - this.errorMessage = message; - } - - public int getErrorCode() { - return errorCode; - } - - public String getErrorMessage() { - return errorMessage; - } - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/error/channel/ChannelException.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/error/channel/ChannelException.java deleted file mode 100644 index 83e1970e1..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/error/channel/ChannelException.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.sprint.mission.discodeit.common.error.channel; - -import com.sprint.mission.discodeit.common.error.ErrorCode; -import java.util.UUID; - -public class ChannelException extends RuntimeException { - - private ChannelException(String message) { - super(message); - } - - private ChannelException(String message, Throwable cause) { - super(message, cause); - } - - public static ChannelException of(ErrorCode message) { - return new ChannelException(message.getErrorMessage()); - } - - public static ChannelException ofNotFound(ErrorCode message, UUID causeInputParameter) { - var format = - String.format( - "%s : input Channel Id = %s", - message.getErrorMessage(), - causeInputParameter.toString() - ); - - return new ChannelException(format); - } - - public static ChannelException ofNotCreatorName( - ErrorCode message, - String creatorName - ) { - var format = String.format( - "%s : 채널 생성자 %s 가 아닙니다.", - message.getErrorMessage(), creatorName - ); - - return new ChannelException(format); - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/error/user/UserException.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/error/user/UserException.java deleted file mode 100644 index 0aa9953b3..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/error/user/UserException.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.sprint.mission.discodeit.common.error.user; - -import com.sprint.mission.discodeit.common.error.ErrorCode; - -public class UserException extends RuntimeException { - - public UserException(String message) { - super(message); - } - - public UserException(String message, Throwable cause) { - super(message, cause); - } - - public static UserException of(ErrorCode message) { - return new UserException(message.getErrorMessage()); - } - - public static UserException of(String message, Throwable cause) { - return new UserException(message, cause); - } - - - public static UserException ofNotJoinChannel( - ErrorCode message, String id - ) { - var format = String.format( - "%s : not participated channel id %s", - message.getErrorMessage(), id - ); - - return new UserException(format); - } - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/objectstream/AppendableObjectOutputStream.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/objectstream/AppendableObjectOutputStream.java deleted file mode 100644 index fd6d5ec7d..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/objectstream/AppendableObjectOutputStream.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.sprint.mission.discodeit.common.objectstream; - -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.io.OutputStream; - -public class AppendableObjectOutputStream extends ObjectOutputStream { - - - private boolean append; - private boolean initialized; - private DataOutputStream dout; - - protected AppendableObjectOutputStream(boolean append) throws IOException, SecurityException { - super(); - this.append = append; - this.initialized = true; - } - - public AppendableObjectOutputStream(OutputStream out, boolean append) throws IOException { - super(out); - this.append = append; - this.initialized = true; - this.dout = new DataOutputStream(out); - this.writeStreamHeader(); - } - - @Override - protected void writeStreamHeader() throws IOException { - if (!this.initialized || this.append) return; - if (dout != null) { - dout.writeShort(STREAM_MAGIC); - dout.writeShort(STREAM_VERSION); - } - } -} -/** - * https://stackoverflow.com/questions/1194656/appending-to-an-objectoutputstream - */ diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/validation/ValidationUtils.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/validation/ValidationUtils.java deleted file mode 100644 index 6f0c68f22..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/common/validation/ValidationUtils.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.sprint.mission.discodeit.common.validation; - -import jakarta.validation.ConstraintViolation; -import jakarta.validation.Validation; -import jakarta.validation.ValidationException; -import jakarta.validation.Validator; -import jakarta.validation.ValidatorFactory; -import java.util.Set; -import java.util.StringJoiner; -import java.util.stream.Collectors; - -public class ValidationUtils { - - // TODO hibernate-validator 공식 문서 참조. 응용 하지를 못했음 => 모든 에러 잡아주는 객체 or 서비스 ? 일단 두고 각 객체에 검증 로직 추가해야함 - private static final ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); - private static final Validator validator = factory.getValidator(); - - public static void validate(T object) { - Set> violations = validator.validate(object); - String errorMessage = violations.stream() - .map(ConstraintViolation::getMessage) - .collect(Collectors.joining("\n")); - throw new ValidationException(String.valueOf(errorMessage)); - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/config/factory/AppFactory.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/config/factory/AppFactory.java deleted file mode 100644 index 9ac10981b..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/config/factory/AppFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.sprint.mission.discodeit.config.factory; - -import com.sprint.mission.discodeit.repository.jcf.channel.ChannelRepository; -import com.sprint.mission.discodeit.repository.jcf.message.ChannelMessage.ChannelMessageRepository; -import com.sprint.mission.discodeit.repository.jcf.message.directMessage.DirectMessageRepository; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.service.channel.ChannelService; -import com.sprint.mission.discodeit.service.message.channelMessage.ChannelMessageService; -import com.sprint.mission.discodeit.service.message.directMessage.DirectMessageService; -import com.sprint.mission.discodeit.service.user.UserService; - -public interface AppFactory { - - UserService getUserService(); - - UserRepository getUserRepository(); - - ChannelRepository getChannelRepository(); - - ChannelService getChannelService(); - - DirectMessageService getDirectMessageService(); - - DirectMessageRepository getDirectMessageRepository(); - - ChannelMessageRepository getChannelMessageRepository(); - - ChannelMessageService getChannelMessageService(); -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/config/factory/ApplicationFileFactory.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/config/factory/ApplicationFileFactory.java deleted file mode 100644 index 5fbd4063d..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/config/factory/ApplicationFileFactory.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.sprint.mission.discodeit.config.factory; - -import com.sprint.mission.discodeit.repository.file.channel.FileChannelRepository; -import com.sprint.mission.discodeit.repository.file.message.FileChannelMessageRepository; -import com.sprint.mission.discodeit.repository.file.message.FileDirectMessageRepository; -import com.sprint.mission.discodeit.repository.file.user.FileUserRepository; -import com.sprint.mission.discodeit.repository.jcf.channel.ChannelRepository; -import com.sprint.mission.discodeit.repository.jcf.message.ChannelMessage.ChannelMessageRepository; -import com.sprint.mission.discodeit.repository.jcf.message.directMessage.DirectMessageRepository; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.service.channel.ChannelService; -import com.sprint.mission.discodeit.service.jcf.JCFChannelMessageService; -import com.sprint.mission.discodeit.service.jcf.JCFChannelService; -import com.sprint.mission.discodeit.service.jcf.JCFDirectMessageService; -import com.sprint.mission.discodeit.service.jcf.JCFUserService; -import com.sprint.mission.discodeit.service.message.channelMessage.ChannelMessageService; -import com.sprint.mission.discodeit.service.message.directMessage.DirectMessageService; -import com.sprint.mission.discodeit.service.user.UserService; - -public class ApplicationFileFactory implements AppFactory { - - private static ApplicationFileFactory INSTANCE; - - - private final UserRepository userRepository; - private final UserService userService; - - private final ChannelRepository channelRepository; - private final ChannelService channelService; - - private final DirectMessageService directMessageService; - private final DirectMessageRepository directMessageRepository; - - private final ChannelMessageService channelMessageService; - private final ChannelMessageRepository channelMessageRepository; - - private static class SingleInstanceHolder { - private static final ApplicationFileFactory INSTANCE = - new ApplicationFileFactory(); - } - - public static synchronized ApplicationFileFactory getInstance() { - return SingleInstanceHolder.INSTANCE; - } - - - private ApplicationFileFactory() { - this.userRepository = FileUserRepository.getInstance(); - this.channelRepository = FileChannelRepository.getInstance(); - this.directMessageRepository = FileDirectMessageRepository.getInstance(); - this.channelMessageRepository = FileChannelMessageRepository.getInstance(); - - this.userService = JCFUserService.getInstance(userRepository); - this.channelService = JCFChannelService.getInstance(userRepository, channelRepository); - this.directMessageService = JCFDirectMessageService.getInstance(directMessageRepository, userRepository); - this.channelMessageService = JCFChannelMessageService.getInstance(userRepository, channelRepository, - channelMessageRepository); - } - - - @Override - public UserService getUserService() { - return userService; - } - - @Override - public UserRepository getUserRepository() { - return userRepository; - } - - @Override - public ChannelRepository getChannelRepository() { - return channelRepository; - } - - @Override - public ChannelService getChannelService() { - return channelService; - } - - @Override - public DirectMessageService getDirectMessageService() { - return directMessageService; - } - - @Override - public DirectMessageRepository getDirectMessageRepository() { - return directMessageRepository; - } - - @Override - public ChannelMessageRepository getChannelMessageRepository() { - return channelMessageRepository; - } - - @Override - public ChannelMessageService getChannelMessageService() { - return channelMessageService; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/config/factory/ApplicationInMemoryFactory.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/config/factory/ApplicationInMemoryFactory.java deleted file mode 100644 index 2c44fa0af..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/config/factory/ApplicationInMemoryFactory.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.sprint.mission.discodeit.config.factory; - -import com.sprint.mission.discodeit.repository.jcf.channel.ChannelRepository; -import com.sprint.mission.discodeit.repository.jcf.channel.JCFChannelRepositoryInMemory; -import com.sprint.mission.discodeit.repository.jcf.message.ChannelMessage.ChannelMessageRepository; -import com.sprint.mission.discodeit.repository.jcf.message.ChannelMessage.JCFChannelMessageRepositoryInMemory; -import com.sprint.mission.discodeit.repository.jcf.message.directMessage.DirectMessageRepository; -import com.sprint.mission.discodeit.repository.jcf.message.directMessage.JCFDirectMessageRepositoryInMemory; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.repository.jcf.user.JCFUserRepositoryInMemory; -import com.sprint.mission.discodeit.service.channel.ChannelService; -import com.sprint.mission.discodeit.service.jcf.JCFChannelMessageService; -import com.sprint.mission.discodeit.service.jcf.JCFChannelService; -import com.sprint.mission.discodeit.service.jcf.JCFDirectMessageService; -import com.sprint.mission.discodeit.service.jcf.JCFUserService; -import com.sprint.mission.discodeit.service.message.channelMessage.ChannelMessageService; -import com.sprint.mission.discodeit.service.message.directMessage.DirectMessageService; -import com.sprint.mission.discodeit.service.user.UserService; - -/** - * 빈으로 관리되는 스프링과 다르게 정확히 어떻게 구현해야하는지 알기가 어려웠음 - */ -public class ApplicationInMemoryFactory implements AppFactory { - private static ApplicationInMemoryFactory INSTANCE; - - private final UserRepository userRepository; - private final UserService userService; - - private final ChannelRepository channelRepository; - private final ChannelService channelService; - - private final DirectMessageService directMessageService; - private final DirectMessageRepository directMessageRepository; - - private final ChannelMessageService channelMessageService; - private final ChannelMessageRepository channelMessageRepository; - - private static class SingleInstanceHolder { - private static final ApplicationInMemoryFactory INSTANCE = - new ApplicationInMemoryFactory(); - } - private ApplicationInMemoryFactory() { - this.userRepository = JCFUserRepositoryInMemory.getInstance(); - this.channelRepository = JCFChannelRepositoryInMemory.getChannelRepositoryInMemory(); - this.directMessageRepository = JCFDirectMessageRepositoryInMemory.getInstance(); - this.channelMessageRepository = JCFChannelMessageRepositoryInMemory.getInstance(); - - this.userService = JCFUserService.getInstance(userRepository); - this.channelService = JCFChannelService.getInstance(userRepository, channelRepository); - this.directMessageService = JCFDirectMessageService.getInstance(directMessageRepository, userRepository); - this.channelMessageService = JCFChannelMessageService.getInstance(userRepository, channelRepository, channelMessageRepository); - } - - public static synchronized ApplicationInMemoryFactory getInstance() { - return SingleInstanceHolder.INSTANCE; - } - - @Override - public UserService getUserService() { - return userService; - } - - @Override - public ChannelService getChannelService() { - return channelService; - } - - @Override - public UserRepository getUserRepository() { - return userRepository; - } - - @Override - public ChannelRepository getChannelRepository() { - return channelRepository; - } - - @Override - public DirectMessageService getDirectMessageService() { - return directMessageService; - } - - @Override - public DirectMessageRepository getDirectMessageRepository() { - return directMessageRepository; - } - - @Override - public ChannelMessageRepository getChannelMessageRepository() { - return channelMessageRepository; - } - - @Override - public ChannelMessageService getChannelMessageService() { - return channelMessageService; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/BinaryContent/BinaryContentController.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/BinaryContent/BinaryContentController.java new file mode 100644 index 000000000..9983e3cc4 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/BinaryContent/BinaryContentController.java @@ -0,0 +1,35 @@ +package com.sprint.mission.discodeit.controller.BinaryContent; + +import com.sprint.mission.discodeit.entity.BinaryContent; +import com.sprint.mission.discodeit.service.BinaryContentService; +import java.util.List; +import java.util.UUID; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/binary-content") +public class BinaryContentController { + + private final BinaryContentService binaryContentService; + + public BinaryContentController(BinaryContentService binaryContentService) { + this.binaryContentService = binaryContentService; + } + + @RequestMapping(value = "/{binaryContentId}", method = RequestMethod.GET) + public ResponseEntity findById(@PathVariable UUID binaryContentId) { + return ResponseEntity.ok(binaryContentService.find(binaryContentId)); + } + + @RequestMapping(method = RequestMethod.POST) + public ResponseEntity> findAll( + @RequestBody List binaryIds + ) { + return ResponseEntity.ok(binaryContentService.findAllByIdIn(binaryIds)); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/channel/ChannelController.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/channel/ChannelController.java new file mode 100644 index 000000000..1c314d193 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/channel/ChannelController.java @@ -0,0 +1,67 @@ +package com.sprint.mission.discodeit.controller.channel; + +import com.sprint.mission.discodeit.dto.data.ChannelDto; +import com.sprint.mission.discodeit.dto.request.PrivateChannelCreateRequest; +import com.sprint.mission.discodeit.dto.request.PublicChannelCreateRequest; +import com.sprint.mission.discodeit.dto.request.PublicChannelUpdateRequest; +import com.sprint.mission.discodeit.service.ChannelService; +import java.net.URI; +import java.util.List; +import java.util.UUID; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/channel") +public class ChannelController { + + private final ChannelService channelService; + + public ChannelController(ChannelService channelService) { + this.channelService = channelService; + } + + @RequestMapping(value = "/all/{userId}", method = RequestMethod.GET) + public ResponseEntity> getAll( + @PathVariable(name = "userId") UUID userId + ) { + return ResponseEntity.ok(channelService.findAllByUserId(userId)); + } + + @RequestMapping(value = "/public", method = RequestMethod.POST) + public ResponseEntity createPublicChannel( + @RequestBody PublicChannelCreateRequest publicChannelCreateRequest + ) { + channelService.create(publicChannelCreateRequest); + return ResponseEntity.created(URI.create("/")).build(); + } + + @RequestMapping(value = "/private", method = RequestMethod.POST) + public ResponseEntity createPrivateChannel( + @RequestBody PrivateChannelCreateRequest privateChannelCreateRequest + ) { + channelService.create(privateChannelCreateRequest); + return ResponseEntity.created(URI.create("/")).build(); + } + + @RequestMapping(value = "/{channelId}", method = RequestMethod.PATCH) + public ResponseEntity updateChannel( + @PathVariable(name = "channelId") UUID channelId, + @RequestBody PublicChannelUpdateRequest publicChannelUpdateRequest + ) { + channelService.update(channelId, publicChannelUpdateRequest); + return ResponseEntity.noContent().build(); + } + + @RequestMapping(value = "/{channelId}", method = RequestMethod.DELETE) + public ResponseEntity deleteChannel( + @PathVariable(name = "channelId") UUID channelId + ) { + channelService.delete(channelId); + return ResponseEntity.ok().build(); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/message/MessageController.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/message/MessageController.java new file mode 100644 index 000000000..bcd6192b8 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/message/MessageController.java @@ -0,0 +1,79 @@ +package com.sprint.mission.discodeit.controller.message; + +import com.sprint.mission.discodeit.dto.request.BinaryContentCreateRequest; +import com.sprint.mission.discodeit.dto.request.MessageCreateRequest; +import com.sprint.mission.discodeit.dto.request.MessageUpdateRequest; +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.service.MessageService; +import java.io.IOException; +import java.net.URI; +import java.util.List; +import java.util.UUID; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +@RestController +@RequestMapping("/api/message") +public class MessageController { + + private final MessageService messageService; + + public MessageController(MessageService messageService) { + this.messageService = messageService; + } + + @RequestMapping(value = "/{channelId}", method = RequestMethod.GET) + public ResponseEntity> findByAllChannel( + @PathVariable(name = "channelId") UUID channelId + ) { + return ResponseEntity.ok(messageService.findAllByChannelId(channelId)); + } + + @RequestMapping( + method = RequestMethod.POST, consumes = {MediaType.MULTIPART_FORM_DATA_VALUE} + ) + public ResponseEntity createMessage( + @RequestPart(name = "messageCreateRequest") MessageCreateRequest messageCreateRequest, + @RequestPart(name = "binary-content-create-request", required = false) List binaryContentCreateRequest + ) { + List binaryContents = binaryContentCreateRequest.stream() + .map(file -> { + try { + return new BinaryContentCreateRequest( + file.getOriginalFilename(), + file.getContentType(), + file.getBytes() + ); + } catch (IOException e) { + throw new RuntimeException(e); + } + }) + .toList(); + messageService.create(messageCreateRequest, binaryContents); + return ResponseEntity.created(URI.create("/")).build(); + } + + @RequestMapping(value = "/{messageId}", method = RequestMethod.PATCH) + public ResponseEntity updateMessage( + @PathVariable(name = "messageId") UUID messageId, + @RequestBody MessageUpdateRequest messageUpdateRequest + ) { + messageService.update(messageId, messageUpdateRequest); + return ResponseEntity.noContent().build(); + } + + @RequestMapping(value = "/{messageId}", method = RequestMethod.DELETE) + public ResponseEntity deleteMessage( + @PathVariable(name = "messageId") UUID messageId + ) { + messageService.delete(messageId); + return ResponseEntity.ok().build(); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/message/MessageReadStatusController.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/message/MessageReadStatusController.java new file mode 100644 index 000000000..992274377 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/message/MessageReadStatusController.java @@ -0,0 +1,51 @@ +package com.sprint.mission.discodeit.controller.message; + +import com.sprint.mission.discodeit.dto.request.ReadStatusCreateRequest; +import com.sprint.mission.discodeit.dto.request.ReadStatusUpdateRequest; +import com.sprint.mission.discodeit.entity.ReadStatus; +import com.sprint.mission.discodeit.service.ReadStatusService; +import java.net.URI; +import java.util.List; +import java.util.UUID; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/read-status") +public class MessageReadStatusController { + + private final ReadStatusService readStatusService; + + public MessageReadStatusController(ReadStatusService readStatusService) { + this.readStatusService = readStatusService; + } + + @RequestMapping(value = "/{userId}", method = RequestMethod.GET) + public ResponseEntity> findByUserId( + @PathVariable(name = "userId") UUID userId + ) { + return ResponseEntity.ok(readStatusService.findAllByUserId(userId)); + } + + @RequestMapping(method = RequestMethod.POST) + public ResponseEntity createReadStatus( + @RequestBody ReadStatusCreateRequest readStatusCreateRequest + ) { + readStatusService.create(readStatusCreateRequest); + return ResponseEntity.created(URI.create("/")).build(); + } + + @RequestMapping(value = "/{userId}", method = RequestMethod.PATCH) + public ResponseEntity updateReadStatusByChannelId( + @PathVariable(name = "userId") UUID userId, + @RequestBody ReadStatusUpdateRequest readStatusUpdateRequest + ) { + List allByUserId = readStatusService.findAllByUserId(userId); + allByUserId.stream().map(ReadStatus::getId).forEach(it -> readStatusService.update(it, readStatusUpdateRequest)); + return ResponseEntity.noContent().build(); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/user/AuthController.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/user/AuthController.java new file mode 100644 index 000000000..aa572a137 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/user/AuthController.java @@ -0,0 +1,28 @@ +package com.sprint.mission.discodeit.controller.user; + +import com.sprint.mission.discodeit.dto.request.LoginRequest; +import com.sprint.mission.discodeit.service.AuthService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/auth") +public class AuthController { + + private final AuthService authService; + + public AuthController(AuthService authService) { + this.authService = authService; + } + + @RequestMapping(method = RequestMethod.POST) + public ResponseEntity login( + @RequestBody LoginRequest loginRequest + ) { + authService.login(loginRequest); + return ResponseEntity.ok().build(); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/user/UserController.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/user/UserController.java new file mode 100644 index 000000000..ab1344225 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/user/UserController.java @@ -0,0 +1,76 @@ +package com.sprint.mission.discodeit.controller.user; + +import com.sprint.mission.discodeit.dto.data.UserDto; +import com.sprint.mission.discodeit.dto.request.BinaryContentCreateRequest; +import com.sprint.mission.discodeit.dto.request.UserCreateRequest; +import com.sprint.mission.discodeit.dto.request.UserUpdateRequest; +import com.sprint.mission.discodeit.service.UserService; +import java.io.IOException; +import java.net.URI; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +@RestController +@RequestMapping("/api/user") +public class UserController { + + private final UserService userService; + + public UserController(UserService userService) { + this.userService = userService; + } + + @RequestMapping(method = RequestMethod.POST, consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) + public ResponseEntity createUser( + @RequestPart(name = "user-create-request") UserCreateRequest userCreateRequest, + @RequestPart(name = "binary-content-create-request", required = false) MultipartFile binaryContentCreateRequest + ) { + BinaryContentCreateRequest binaryContent = null; + if (Objects.nonNull(binaryContentCreateRequest)) { + try { + binaryContent = new BinaryContentCreateRequest( + binaryContentCreateRequest.getOriginalFilename(), + binaryContentCreateRequest.getContentType(), + binaryContentCreateRequest.getBytes()); + } catch (IOException exception) { + throw new IllegalArgumentException(exception); + } + } + userService.create(userCreateRequest, Optional.ofNullable(binaryContent)); + return ResponseEntity.created(URI.create("/")).build(); + } + + @RequestMapping(value = "/findAll", method = RequestMethod.GET) + public ResponseEntity> findAll() { + return ResponseEntity.ok(userService.findAll()); + } + + @RequestMapping(value = "/{userId}", method = RequestMethod.PATCH) + public ResponseEntity updateUser( + @PathVariable(name = "userId") UUID userId, + @RequestBody UserUpdateRequest userUpdateRequest, + @RequestBody(required = false) BinaryContentCreateRequest binaryContentCreateRequest + ) { + userService.update(userId, userUpdateRequest, Optional.ofNullable(binaryContentCreateRequest)); + return ResponseEntity.noContent().build(); + } + + @RequestMapping(value = "/{userId}", method = RequestMethod.DELETE) + public ResponseEntity deleteUser( + @PathVariable(name = "userId") UUID userId + ) { + userService.delete(userId); + return ResponseEntity.ok().build(); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/user/UserStatusController.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/user/UserStatusController.java new file mode 100644 index 000000000..12b2439bc --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/user/UserStatusController.java @@ -0,0 +1,31 @@ +package com.sprint.mission.discodeit.controller.user; + +import com.sprint.mission.discodeit.dto.request.UserStatusUpdateRequest; +import com.sprint.mission.discodeit.service.UserStatusService; +import java.util.UUID; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/user-status") +public class UserStatusController { + + private UserStatusService userStatusService; + + public UserStatusController(UserStatusService userStatusService) { + this.userStatusService = userStatusService; + } + + @RequestMapping(value = "/{userId}", method = RequestMethod.PATCH) + public ResponseEntity updateUserStatus( + @PathVariable(name = "userId") UUID userId, + @RequestBody UserStatusUpdateRequest userStatusUpdateRequest + ) { + userStatusService.updateByUserId(userId, userStatusUpdateRequest); + return ResponseEntity.noContent().build(); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/view/ViewController.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/view/ViewController.java new file mode 100644 index 000000000..ca6d1d1bf --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/controller/view/ViewController.java @@ -0,0 +1,16 @@ +package com.sprint.mission.discodeit.controller.view; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +public class ViewController { + + @RequestMapping(value = "/", method = RequestMethod.GET) + public String displayMainPage() { + + return "user-list"; + } + +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/data/ChannelDto.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/data/ChannelDto.java new file mode 100644 index 000000000..3528a0089 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/data/ChannelDto.java @@ -0,0 +1,16 @@ +package com.sprint.mission.discodeit.dto.data; + +import com.sprint.mission.discodeit.entity.ChannelType; +import java.time.Instant; +import java.util.List; +import java.util.UUID; + +public record ChannelDto( + UUID id, + ChannelType type, + String name, + String description, + List participantIds, + Instant lastMessageAt +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/data/UserDto.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/data/UserDto.java new file mode 100644 index 000000000..a2d33a91f --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/data/UserDto.java @@ -0,0 +1,17 @@ +package com.sprint.mission.discodeit.dto.data; + +import com.sprint.mission.discodeit.entity.User; +import java.time.Instant; +import java.util.UUID; + +public record UserDto( + UUID id, + Instant createdAt, + Instant updatedAt, + String username, + String email, + UUID profileId, + Boolean online +) { + +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/BinaryContentCreateRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/BinaryContentCreateRequest.java new file mode 100644 index 000000000..b787a127d --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/BinaryContentCreateRequest.java @@ -0,0 +1,8 @@ +package com.sprint.mission.discodeit.dto.request; + +public record BinaryContentCreateRequest( + String fileName, + String contentType, + byte[] bytes +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/LoginRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/LoginRequest.java new file mode 100644 index 000000000..2ab978e2a --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/LoginRequest.java @@ -0,0 +1,7 @@ +package com.sprint.mission.discodeit.dto.request; + +public record LoginRequest( + String username, + String password +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/MessageCreateRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/MessageCreateRequest.java new file mode 100644 index 000000000..dd8c3d24c --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/MessageCreateRequest.java @@ -0,0 +1,10 @@ +package com.sprint.mission.discodeit.dto.request; + +import java.util.UUID; + +public record MessageCreateRequest( + String content, + UUID channelId, + UUID authorId +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/MessageUpdateRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/MessageUpdateRequest.java new file mode 100644 index 000000000..d1830fbb9 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/MessageUpdateRequest.java @@ -0,0 +1,6 @@ +package com.sprint.mission.discodeit.dto.request; + +public record MessageUpdateRequest( + String newContent +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/PrivateChannelCreateRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/PrivateChannelCreateRequest.java new file mode 100644 index 000000000..6b203baa7 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/PrivateChannelCreateRequest.java @@ -0,0 +1,9 @@ +package com.sprint.mission.discodeit.dto.request; + +import java.util.List; +import java.util.UUID; + +public record PrivateChannelCreateRequest( + List participantIds +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/PublicChannelCreateRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/PublicChannelCreateRequest.java new file mode 100644 index 000000000..c5b15cc33 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/PublicChannelCreateRequest.java @@ -0,0 +1,7 @@ +package com.sprint.mission.discodeit.dto.request; + +public record PublicChannelCreateRequest( + String name, + String description +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/PublicChannelUpdateRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/PublicChannelUpdateRequest.java new file mode 100644 index 000000000..6c0234162 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/PublicChannelUpdateRequest.java @@ -0,0 +1,7 @@ +package com.sprint.mission.discodeit.dto.request; + +public record PublicChannelUpdateRequest( + String newName, + String newDescription +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/ReadStatusCreateRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/ReadStatusCreateRequest.java new file mode 100644 index 000000000..f2d520af9 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/ReadStatusCreateRequest.java @@ -0,0 +1,11 @@ +package com.sprint.mission.discodeit.dto.request; + +import java.time.Instant; +import java.util.UUID; + +public record ReadStatusCreateRequest( + UUID userId, + UUID channelId, + Instant lastReadAt +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/ReadStatusUpdateRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/ReadStatusUpdateRequest.java new file mode 100644 index 000000000..3921ffc75 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/ReadStatusUpdateRequest.java @@ -0,0 +1,8 @@ +package com.sprint.mission.discodeit.dto.request; + +import java.time.Instant; + +public record ReadStatusUpdateRequest( + Instant newLastReadAt +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/UserCreateRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/UserCreateRequest.java new file mode 100644 index 000000000..e1daa625b --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/UserCreateRequest.java @@ -0,0 +1,8 @@ +package com.sprint.mission.discodeit.dto.request; + +public record UserCreateRequest( + String username, + String email, + String password +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/UserStatusCreateRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/UserStatusCreateRequest.java new file mode 100644 index 000000000..272a0d4c7 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/UserStatusCreateRequest.java @@ -0,0 +1,10 @@ +package com.sprint.mission.discodeit.dto.request; + +import java.time.Instant; +import java.util.UUID; + +public record UserStatusCreateRequest( + UUID userId, + Instant lastActiveAt +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/UserStatusUpdateRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/UserStatusUpdateRequest.java new file mode 100644 index 000000000..9a001937a --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/UserStatusUpdateRequest.java @@ -0,0 +1,8 @@ +package com.sprint.mission.discodeit.dto.request; + +import java.time.Instant; + +public record UserStatusUpdateRequest( + Instant newLastActiveAt +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/UserUpdateRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/UserUpdateRequest.java new file mode 100644 index 000000000..d1da4c7a3 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/dto/request/UserUpdateRequest.java @@ -0,0 +1,8 @@ +package com.sprint.mission.discodeit.dto.request; + +public record UserUpdateRequest( + String newUsername, + String newEmail, + String newPassword +) { +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/BinaryContent.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/BinaryContent.java new file mode 100644 index 000000000..5c827e35f --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/BinaryContent.java @@ -0,0 +1,28 @@ +package com.sprint.mission.discodeit.entity; + +import java.io.Serializable; +import java.time.Instant; +import java.util.UUID; +import lombok.Getter; + +@Getter +public class BinaryContent implements Serializable { + private static final long serialVersionUID = 1L; + private UUID id; + private Instant createdAt; + // + private String fileName; + private Long size; + private String contentType; + private byte[] bytes; + + public BinaryContent(String fileName, Long size, String contentType, byte[] bytes) { + this.id = UUID.randomUUID(); + this.createdAt = Instant.now(); + // + this.fileName = fileName; + this.size = size; + this.contentType = contentType; + this.bytes = bytes; + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/Channel.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/Channel.java new file mode 100644 index 000000000..ef004c060 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/Channel.java @@ -0,0 +1,43 @@ +package com.sprint.mission.discodeit.entity; + +import java.io.Serializable; +import java.time.Instant; +import java.util.UUID; +import lombok.Getter; + +@Getter +public class Channel implements Serializable { + private static final long serialVersionUID = 1L; + private UUID id; + private Instant createdAt; + private Instant updatedAt; + // + private ChannelType type; + private String name; + private String description; + + public Channel(ChannelType type, String name, String description) { + this.id = UUID.randomUUID(); + this.createdAt = Instant.now(); + // + this.type = type; + this.name = name; + this.description = description; + } + + public void update(String newName, String newDescription) { + boolean anyValueUpdated = false; + if (newName != null && !newName.equals(this.name)) { + this.name = newName; + anyValueUpdated = true; + } + if (newDescription != null && !newDescription.equals(this.description)) { + this.description = newDescription; + anyValueUpdated = true; + } + + if (anyValueUpdated) { + this.updatedAt = Instant.now(); + } + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/ChannelType.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/ChannelType.java new file mode 100644 index 000000000..9a2ff3f0f --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/ChannelType.java @@ -0,0 +1,6 @@ +package com.sprint.mission.discodeit.entity; + +public enum ChannelType { + PUBLIC, + PRIVATE, +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/Message.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/Message.java new file mode 100644 index 000000000..2a68eaa92 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/Message.java @@ -0,0 +1,44 @@ +package com.sprint.mission.discodeit.entity; + +import java.io.Serializable; +import java.time.Instant; +import java.util.List; +import java.util.UUID; +import lombok.Getter; + +@Getter +public class Message implements Serializable { + private static final long serialVersionUID = 1L; + + private UUID id; + private Instant createdAt; + private Instant updatedAt; + // + private String content; + // + private UUID channelId; + private UUID authorId; + private List attachmentIds; + + public Message(String content, UUID channelId, UUID authorId, List attachmentIds) { + this.id = UUID.randomUUID(); + this.createdAt = Instant.now(); + // + this.content = content; + this.channelId = channelId; + this.authorId = authorId; + this.attachmentIds = attachmentIds; + } + + public void update(String newContent) { + boolean anyValueUpdated = false; + if (newContent != null && !newContent.equals(this.content)) { + this.content = newContent; + anyValueUpdated = true; + } + + if (anyValueUpdated) { + this.updatedAt = Instant.now(); + } + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/ReadStatus.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/ReadStatus.java new file mode 100644 index 000000000..2ab5c54ff --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/ReadStatus.java @@ -0,0 +1,39 @@ +package com.sprint.mission.discodeit.entity; + +import java.io.Serializable; +import java.time.Instant; +import java.util.UUID; +import lombok.Getter; + +@Getter +public class ReadStatus implements Serializable { + private static final long serialVersionUID = 1L; + private UUID id; + private Instant createdAt; + private Instant updatedAt; + // + private UUID userId; + private UUID channelId; + private Instant lastReadAt; + + public ReadStatus(UUID userId, UUID channelId, Instant lastReadAt) { + this.id = UUID.randomUUID(); + this.createdAt = Instant.now(); + // + this.userId = userId; + this.channelId = channelId; + this.lastReadAt = lastReadAt; + } + + public void update(Instant newLastReadAt) { + boolean anyValueUpdated = false; + if (newLastReadAt != null && !newLastReadAt.equals(this.lastReadAt)) { + this.lastReadAt = newLastReadAt; + anyValueUpdated = true; + } + + if (anyValueUpdated) { + this.updatedAt = Instant.now(); + } + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/User.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/User.java new file mode 100644 index 000000000..4998c29c6 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/User.java @@ -0,0 +1,54 @@ +package com.sprint.mission.discodeit.entity; + +import java.io.Serializable; +import java.time.Instant; +import java.util.UUID; +import lombok.Getter; + +@Getter +public class User implements Serializable { + private static final long serialVersionUID = 1L; + + private UUID id; + private Instant createdAt; + private Instant updatedAt; + // + private String username; + private String email; + private String password; + private UUID profileId; // BinaryContent + + public User(String username, String email, String password, UUID profileId) { + this.id = UUID.randomUUID(); + this.createdAt = Instant.now(); + // + this.username = username; + this.email = email; + this.password = password; + this.profileId = profileId; + } + + public void update(String newUsername, String newEmail, String newPassword, UUID newProfileId) { + boolean anyValueUpdated = false; + if (newUsername != null && !newUsername.equals(this.username)) { + this.username = newUsername; + anyValueUpdated = true; + } + if (newEmail != null && !newEmail.equals(this.email)) { + this.email = newEmail; + anyValueUpdated = true; + } + if (newPassword != null && !newPassword.equals(this.password)) { + this.password = newPassword; + anyValueUpdated = true; + } + if (newProfileId != null && !newProfileId.equals(this.profileId)) { + this.profileId = newProfileId; + anyValueUpdated = true; + } + + if (anyValueUpdated) { + this.updatedAt = Instant.now(); + } + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/UserStatus.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/UserStatus.java new file mode 100644 index 000000000..829009d31 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/UserStatus.java @@ -0,0 +1,44 @@ +package com.sprint.mission.discodeit.entity; + +import java.io.Serializable; +import java.time.Duration; +import java.time.Instant; +import java.util.UUID; +import lombok.Getter; + +@Getter +public class UserStatus implements Serializable { + private static final long serialVersionUID = 1L; + private UUID id; + private Instant createdAt; + private Instant updatedAt; + // + private UUID userId; + private Instant lastActiveAt; + + public UserStatus(UUID userId, Instant lastActiveAt) { + this.id = UUID.randomUUID(); + this.createdAt = Instant.now(); + // + this.userId = userId; + this.lastActiveAt = lastActiveAt; + } + + public void update(Instant lastActiveAt) { + boolean anyValueUpdated = false; + if (lastActiveAt != null && !lastActiveAt.equals(this.lastActiveAt)) { + this.lastActiveAt = lastActiveAt; + anyValueUpdated = true; + } + + if (anyValueUpdated) { + this.updatedAt = Instant.now(); + } + } + + public Boolean isOnline() { + Instant instantFiveMinutesAgo = Instant.now().minus(Duration.ofMinutes(5)); + + return lastActiveAt.isAfter(instantFiveMinutesAgo); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/Channel.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/Channel.java deleted file mode 100644 index c0340df6a..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/Channel.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.sprint.mission.discodeit.entity.channel; - -import com.google.common.base.Preconditions; -import com.sprint.mission.discodeit.common.error.ErrorCode; -import com.sprint.mission.discodeit.common.error.channel.ChannelException; -import com.sprint.mission.discodeit.entity.common.AbstractUUIDEntity; -import com.sprint.mission.discodeit.entity.user.entity.User; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; - -public class Channel extends AbstractUUIDEntity { - - @NotNull - @Size( - min = 3, max = 50, - message = "create channel must be between {min} and {max} : reject channel name `${validatedValue}`" - ) - private String channelName; - - private final User creator; - - /** - * ==> 코드 리뷰 받고 싶은 부분 - * 필드에 참여한 유저의 객체를 참조하고 있는 자료구조를 추가하고 싶습니다. ex) private ParticipatedUser participatedUsers - * 생각되는 문제는 순환참조로 어떻게 끊어줄 수 있을까입니다 - * 1. userId 만 저장하고 있는 자료구조 -> 데이터베이스식은 객체지향 코딩에서 거리가 먼것 같아 저는 지양합니다. - * 2. User 객체를 담은 자료구조 -> 유저가 소유한 채널 중 해당 채널을 찾아, 채널에 대한 정보를 참조한다. - * -> 채널에 참가한 유저 객체를 참조한다 .. 무한루프.. - * 3. 생각되는 문제점 : 디비는 스프링부트로 기능이 있는것으로 알지만, 파일 시스템으로 직접 구현할 경우 막막함, - * 일단 해보지 않았지만, 어떤 방식으로 생각해야하는지 ? - */ - - - private Channel(String channelName, User creator) { - this.channelName = channelName; - this.creator = creator; - } - - public static Channel createOfChannelNameAndUser( - String channelName, - User creator - ) { - - return new Channel(channelName, creator); - } - - public static Channel createDefaultNameAndUser(User user) { - - return new Channel("Default Channel Name", user); - } - - public void changeName(String newName, User user) { - checkCreatorOrThrow(user); - - channelName = newName; - updateModified(); - } - - public void deleteChannel(User user) { - checkCreatorOrThrow(user); - - updateUnregistered(); - } - - public boolean isRegisteredAndNameEqual(String channelName) { - return isRegistered() && this.channelName.equals(channelName); - } - - public String getChannelName() { - return channelName; - } - - private void checkCreatorOrThrow(User user) { - var isCreator = isCreator(user); - - if (!isCreator) { - throw ChannelException.ofNotCreatorName( - ErrorCode.CHANNEL_NOT_EQUAL_CREATOR, - user.getName() - ); - } - } - - private boolean isCreator(User user) { - Preconditions.checkNotNull(user); - return creator.equals(user); - } - - public String getCreatorName() { - return creator.getName(); - } - - @Override - public String toString() { - var format = - String.format( - "channel info = [channel name = %s creator = %s, createAt = %d, updateAt = %d, status = %s]", - channelName, - creator.getName(), - getCreateAt(), - getUpdateAt().orElse(0L), - getStatus().toString() - ); - return format; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/dto/ChangeChannelNameRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/dto/ChangeChannelNameRequest.java deleted file mode 100644 index 353426161..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/dto/ChangeChannelNameRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.sprint.mission.discodeit.entity.channel.dto; - -import java.util.UUID; - -public record ChangeChannelNameRequest(UUID userId, UUID channelId, String newChannelName) { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/dto/ChannelResponse.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/dto/ChannelResponse.java deleted file mode 100644 index 5a115af80..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/dto/ChannelResponse.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.sprint.mission.discodeit.entity.channel.dto; - -import java.util.UUID; - -public record ChannelResponse(UUID channelId, String channelName, String creator, String status) { - -// public static ChannelResponse ofChannelIdNameCreatorStatus(UUID channelId, String channelName, String creator, String status) { -// // 이게 맞나... 모든 파라미터를 null check -// Preconditions.checkNotNull(channelId); -// Preconditions.checkNotNull(channelName); -// Preconditions.checkNotNull(creator); -// Preconditions.checkNotNull(status); -// return new ChannelResponse(channelId, channelName, creator, status); -// } - - public static final class Builder { - private UUID channelId; - private String channelName; - private String creator; - private String status; - - public Builder() {} - - public Builder channelId(UUID channelId) { - this.channelId = channelId; - return this; - } - - public Builder channelName(String channelName) { - this.channelName = channelName; - return this; - } - - public Builder creator(String creator) { - this.creator = creator; - return this; - } - - public Builder status(String status) { - this.status = status; - return this; - } - - public ChannelResponse build() { - return new ChannelResponse(channelId, channelName, creator, status); - } - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/dto/CreateNewChannelRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/dto/CreateNewChannelRequest.java deleted file mode 100644 index ba483eacf..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/dto/CreateNewChannelRequest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.sprint.mission.discodeit.entity.channel.dto; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.util.UUID; - -public record CreateNewChannelRequest( - @NotNull - UUID userId, - @NotBlank - String channelName -) { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/dto/DeleteChannelRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/dto/DeleteChannelRequest.java deleted file mode 100644 index 59ad9711d..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/channel/dto/DeleteChannelRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.sprint.mission.discodeit.entity.channel.dto; - -import java.util.UUID; - -public record DeleteChannelRequest(UUID userId, UUID channelId) { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/common/AbstractUUIDEntity.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/common/AbstractUUIDEntity.java deleted file mode 100644 index 6210c8dd6..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/common/AbstractUUIDEntity.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.sprint.mission.discodeit.entity.common; - -import static com.sprint.mission.discodeit.entity.common.Status.MODIFIED; -import static com.sprint.mission.discodeit.entity.common.Status.REGISTERED; -import static com.sprint.mission.discodeit.entity.common.Status.UNREGISTERED; - -import com.google.common.base.Preconditions; -import java.io.Serial; -import java.io.Serializable; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.util.Optional; -import java.util.UUID; - -public abstract class AbstractUUIDEntity implements Serializable { - - @Serial - private static final long serialVersionUID = -2898060967687082469L; - private final UUID id; - - private final Long createAt; - - private Long updateAt = null; - - private Status status; - - protected AbstractUUIDEntity() { - this.id = UUID.randomUUID(); - this.createAt = createUnixTimestamp(); - this.status = REGISTERED; - } - - public Optional getUpdateAt() { - return Optional.ofNullable(updateAt); - } - - public UUID getId() { - return id; - } - - public Long getCreateAt() { - return createAt; - } - - public Status getStatus() { - return status; - } - - private void updateStatus(Status status) { - Preconditions.checkNotNull(status); - this.status = status; - this.updateAt = createUnixTimestamp(); - } - - public void updateModified() { - updateStatus(MODIFIED); - } - - public void updateUnregistered() { - updateStatus(UNREGISTERED); - } - - public boolean isRegistered() { - return status != UNREGISTERED; - } - - private long createUnixTimestamp() { - return LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - AbstractUUIDEntity that = (AbstractUUIDEntity) o; - return id.equals(that.id); - } - - @Override - public int hashCode() { - return id.hashCode(); - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/common/Status.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/common/Status.java deleted file mode 100644 index 7168304db..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/common/Status.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.sprint.mission.discodeit.entity.common; - -public enum Status { - - MODIFIED("수정"), - REGISTERED("등록"), - UNREGISTERED("해지") - ; - - private final String description; - - Status(String status) { - this.description = status; - } - - public String getDescription() { - return description; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/ChannelMessage.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/ChannelMessage.java deleted file mode 100644 index d8354c4d5..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/ChannelMessage.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.sprint.mission.discodeit.entity.message; - -import com.sprint.mission.discodeit.entity.channel.Channel; -import com.sprint.mission.discodeit.entity.common.AbstractUUIDEntity; -import com.sprint.mission.discodeit.entity.user.entity.User; - -public class ChannelMessage extends AbstractUUIDEntity { - - private final Sender sender; - - private final String message; - - private final User messageSender; - - private final Channel receiverChannel; - - private ChannelMessage(Sender sender, String message, User messageSender, Channel receiverChannel) { - this.sender = sender; - this.message = message; - this.messageSender = messageSender; - this.receiverChannel = receiverChannel; - } - - public static ChannelMessage ofMessageAndSenderAndReceiverChannel( - String message, - User messageSender, - Channel receiverChannel - ) { - - Sender channelSender = (sender, receiver, message1) -> { - var format = String.format( - "보낸 사람 : %s , 수신 채널 : %s , 메시지 : %s", - sender.getName(), - receiver.getChannelName(), - message1 - ); - - System.out.println(format); - }; - - return new ChannelMessage(channelSender, message, messageSender, receiverChannel); - } - - public String getMessage() { - return message; - } - - public User getMessageSender() { - return messageSender; - } - - public Channel getReceiverChannel() { - return receiverChannel; - } - - // 채널에 속한 모든 사람들에게 알림을 전송해야겠네 ? - public void sendMessage() { - sender.sendMessage(messageSender, receiverChannel, message); - } - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/DirectMessage.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/DirectMessage.java deleted file mode 100644 index d0489d76a..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/DirectMessage.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.sprint.mission.discodeit.entity.message; - -import com.sprint.mission.discodeit.entity.common.AbstractUUIDEntity; -import com.sprint.mission.discodeit.entity.user.entity.User; - -public class DirectMessage extends AbstractUUIDEntity { - // 보내는 방법을 추상화 - private final Sender sender; - - private final String message; - - private final User messageSender; - - private final User messageReceiver; - - private DirectMessage(Sender sender, String message, User messageSender, User messageReceiver) { - this.sender = sender; - this.message = message; - this.messageSender = messageSender; - this.messageReceiver = messageReceiver; - } - - public static DirectMessage ofMessageAndSenderReceiver(String message, User messageSender, User messageReceiver) { - Sender sender = (sender1, receiver1, message1) -> { - var format = String.format( - "보낸 사람 : %s , 보낸 사람 : %s, 메시지 : %s", - sender1.getName(), - receiver1.getName(), - message - ); - }; - - return new DirectMessage(sender, message, messageSender, messageReceiver); - } - - public void sendMessage() { - sender.sendMessage(messageSender, messageReceiver, message); - } - - public String getMessage() { - return message; - } - - public User getMessageSender() { - return messageSender; - } - - public User getMessageReceiver() { - return messageReceiver; - } -} -/** - * 메세지를 주고 받는 행위를 어떻게 처리해주어야 할까? - * 1. 유저가 메시지를 발송한다. - * 2. 애플리케이션에서 메시지를 저장한다. - * 3. 애플리케이션에서 메시지 알림을 전송한다. - * 4. 받은 유저가 알림을 확인하고, 메시지를 확인한다. 메시지를 확인할 때 기존의 주고받은 메시지도 모두 들고 와야함 => 서비스 레포에서 처리해야할 일 같음 - */ - -/** - * 메시지가 저장할 데이터는 ? - * 1. 메시지 원문 - * 2. 보낸 사람 - * 3. 받는 사람 - * etc. 메시지 원문 말고, 사진(url 포함), 다양한 것을 보낼 수 있는데 저장할지 확실하지 않은 데이터를 필드로 가지고 있어야하는가? - */ \ No newline at end of file diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/Sender.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/Sender.java deleted file mode 100644 index 0e045fe12..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/Sender.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.sprint.mission.discodeit.entity.message; - -public interface Sender { - - void sendMessage(T sender, V receiver, String message); -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/dto/ChannelMessageInfoResponse.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/dto/ChannelMessageInfoResponse.java deleted file mode 100644 index b4e45760b..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/dto/ChannelMessageInfoResponse.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.sprint.mission.discodeit.entity.message.dto; - -import java.util.UUID; - -public record ChannelMessageInfoResponse(UUID messageId, UUID sendUserId, UUID receiveChannelId, String message) { - - public static final class Builder { - private UUID messageId; - private UUID sendUserId; - private UUID receiveChannelId; - private String message; - - public Builder messageId(UUID messageId) { - this.messageId = messageId; - return this; - } - - public Builder sendUserId(UUID sendUserId) { - this.sendUserId = sendUserId; - return this; - } - - public Builder receiveChannelId(UUID receiveChannelId) { - this.receiveChannelId = receiveChannelId; - return this; - } - - public Builder message(String message) { - this.message = message; - return this; - } - - public ChannelMessageInfoResponse build() { - return new ChannelMessageInfoResponse(messageId, sendUserId, receiveChannelId, message); - } - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/dto/DirectMessageInfoResponse.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/dto/DirectMessageInfoResponse.java deleted file mode 100644 index 12b33ab8d..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/dto/DirectMessageInfoResponse.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.sprint.mission.discodeit.entity.message.dto; - -import java.util.UUID; - -public record DirectMessageInfoResponse(UUID messageId, UUID sender, UUID receiver, String message) { - - public static final class Builder { - private UUID messageId; - private UUID sender; - private UUID receiver; - private String message; - - public Builder messageId(UUID messageId) { - this.messageId = messageId; - return this; - } - - public Builder sender(UUID sender) { - this.sender = sender; - return this; - } - - public Builder receiver(UUID receiver) { - this.receiver = receiver; - return this; - } - - public Builder message(String message) { - this.message = message; - return this; - } - - public DirectMessageInfoResponse build() { - return new DirectMessageInfoResponse(messageId, sender, receiver, message); - } - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/dto/SendChannelMessageRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/dto/SendChannelMessageRequest.java deleted file mode 100644 index af623b217..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/dto/SendChannelMessageRequest.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.sprint.mission.discodeit.entity.message.dto; - -import java.util.UUID; - -public record SendChannelMessageRequest(UUID sendUserId, UUID receiveChannelId, String message) { - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/dto/SendDirectMessageRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/dto/SendDirectMessageRequest.java deleted file mode 100644 index 2d79975a4..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/message/dto/SendDirectMessageRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.sprint.mission.discodeit.entity.message.dto; - -import java.util.UUID; - -public record SendDirectMessageRequest(UUID sendUserId, UUID receiveUserId, String message) { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/ExitChannelRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/ExitChannelRequest.java deleted file mode 100644 index be7b46381..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/ExitChannelRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.sprint.mission.discodeit.entity.user.dto; - -import java.util.UUID; - -public record ExitChannelRequest(UUID userId, UUID channelId) { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/FindUserRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/FindUserRequest.java deleted file mode 100644 index 78dba1e3e..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/FindUserRequest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.sprint.mission.discodeit.entity.user.dto; - -public record FindUserRequest(String username) { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/ModifyUserInfoRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/ModifyUserInfoRequest.java deleted file mode 100644 index d414afc40..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/ModifyUserInfoRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.sprint.mission.discodeit.entity.user.dto; - -import java.util.UUID; - -public record ModifyUserInfoRequest(UUID id, String changeUsername) { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/RegisterUserRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/RegisterUserRequest.java deleted file mode 100644 index e910c87e4..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/RegisterUserRequest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.sprint.mission.discodeit.entity.user.dto; - -public record RegisterUserRequest(String name) { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/UnregisterUserRequest.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/UnregisterUserRequest.java deleted file mode 100644 index 502ea8ae6..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/UnregisterUserRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.sprint.mission.discodeit.entity.user.dto; - -import java.util.UUID; - -public record UnregisterUserRequest(UUID id, String username) { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/UserInfoResponse.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/UserInfoResponse.java deleted file mode 100644 index 37f6a46d2..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/dto/UserInfoResponse.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.sprint.mission.discodeit.entity.user.dto; - -import com.sprint.mission.discodeit.entity.common.Status; -import java.util.UUID; - -public record UserInfoResponse(UUID uuid, String username, Status status) { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/entity/ParticipatedChannel.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/entity/ParticipatedChannel.java deleted file mode 100644 index 3d67182e9..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/entity/ParticipatedChannel.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.sprint.mission.discodeit.entity.user.entity; - -import static com.sprint.mission.discodeit.common.error.ErrorCode.USER_NOT_PARTICIPATED_CHANNEL; - -import com.sprint.mission.discodeit.common.error.channel.ChannelException; -import com.sprint.mission.discodeit.common.error.user.UserException; -import com.sprint.mission.discodeit.entity.channel.Channel; -import com.sprint.mission.discodeit.entity.common.Status; -import java.io.Serial; -import java.io.Serializable; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; - -public class ParticipatedChannel implements Serializable { - - @Serial - private static final long serialVersionUID = -2880824194029612128L; - - private final Map participatedChannels; - - private ParticipatedChannel(Map channels) { - this.participatedChannels = channels; - } - - public static ParticipatedChannel newDefault() { - return new ParticipatedChannel(new HashMap<>()); - } - - public Channel createChannel(String channelName, User user) { - var createdChannel = Channel.createOfChannelNameAndUser(channelName, user); - participatedChannels.put(createdChannel.getId(), createdChannel); - - return createdChannel; - } - - public List findAllChannels() { - var participatedChannels = - this.participatedChannels.values() - .stream() - .filter(Channel::isRegistered) - .toList(); - - return Collections.unmodifiableList(participatedChannels); - } - - private Optional findByChannelId(UUID channelId) { - var foundParticipatedChannel = participatedChannels.get(channelId); - return Optional.ofNullable(foundParticipatedChannel); - } - - public Optional getUnregisteredChannelById(UUID channelId) { - var foundChannel = - findByChannelId(channelId) - .orElseThrow( - () -> ChannelException.ofNotFound(USER_NOT_PARTICIPATED_CHANNEL, channelId)); - - var unregisteredReturnNullOrFoundChannel = - foundChannel.isRegistered() ? foundChannel : null; - - - return Optional.ofNullable(unregisteredReturnNullOrFoundChannel); - } - - // TODO 같은 이름을 가진 채널이 여러 개 있을 수 있음. 리스트로 반환 고려해야하지 않을까? - public Optional findByName(String name) { - var foundChannelByName = participatedChannels.values() - .stream() - .filter(channel -> channel.isRegisteredAndNameEqual(name)) - .findFirst(); - - return foundChannelByName; - } - - public Channel changeChannelNameOrThrow(UUID channelId, String newName, User user) { - var foundChannel = - getUnregisteredChannelById(channelId) - .orElseThrow( - () -> UserException.ofNotJoinChannel(USER_NOT_PARTICIPATED_CHANNEL, - channelId.toString())); - - foundChannel.changeName(newName, user); - participatedChannels.put(foundChannel.getId(), foundChannel); - - return foundChannel; - } - - public void exitChannelById(UUID channelId) { - findByChannelId(channelId) - .ifPresent(foundChannel -> participatedChannels.remove(foundChannel.getId())); - } - - public int countParticipatedChannels() { - return participatedChannels.size(); - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/entity/User.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/entity/User.java deleted file mode 100644 index 43c0cfefc..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/entity/User.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.sprint.mission.discodeit.entity.user.entity; - - -import com.google.common.base.Preconditions; -import com.sprint.mission.discodeit.entity.channel.Channel; -import com.sprint.mission.discodeit.entity.common.AbstractUUIDEntity; -import java.util.List; -import java.util.UUID; - -public class User extends AbstractUUIDEntity { - - private UserName name; - - private final ParticipatedChannel participatedChannels; - - private User(UserName name, ParticipatedChannel channel) { - this.name = name; - this.participatedChannels = channel; - } - - public static User createFrom(String username) { - Preconditions.checkNotNull(username); - var userName = UserName.createFrom(username); - var participatedChannel = ParticipatedChannel.newDefault(); - return new User(userName, participatedChannel); - } - - public void changeUserName(String newName) { - Preconditions.checkNotNull(newName); - var changedName = this.name.changeName(newName); - this.name = changedName; - updateModified(); - } - - /** - * 유저에게 채널을 생성하는 책임이 있는 것이아니라, - * 다른 객체에 해당 작업을 위임, 그런데 메서드 명이 영... - * 이 부분 코드 리뷰 부탁드릴게요! - */ - - /** - * 유저의 참여 채널에 새로운 채널을 생성하는 메서드 - * @param channelName - * @return - */ - public Channel openNewChannel(String channelName) { - Preconditions.checkNotNull(channelName); - var createdChannel = participatedChannels.createChannel(channelName, this); - return createdChannel; - } - - public Channel changeChannelName(UUID channelId, String channelName) { - Preconditions.checkNotNull(channelId); - var targetChannel = - participatedChannels.changeChannelNameOrThrow(channelId, channelName, this); - - return targetChannel; - } - - /** - * 참여한 채널에서 나가는 메서드 - * @param channelId - */ - public void exitParticipatedChannel(UUID channelId) { - participatedChannels.exitChannelById(channelId); - } - - public int countParticipatedChannels() { - var participatedChannelCount = participatedChannels.countParticipatedChannels(); - return participatedChannelCount; - } - - public List getParticipatedChannels() { - return participatedChannels.findAllChannels(); - } - - public String getName() { - return name.getName(); - } - - public void unregister() { - updateUnregistered(); - } - - @Override - public String toString() { - var format = - String.format( - "user info = [id : %s, name: %s, status : %s, createAt = %d, updateAt = %d], participatedChannel = {%s}", - getId(), - getName(), - getStatus().toString(), - getCreateAt(), - getUpdateAt().orElse(0L), - getParticipatedChannels() - ); - - return format; - } -} - diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/entity/UserName.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/entity/UserName.java deleted file mode 100644 index a2838e354..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/entity/user/entity/UserName.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.sprint.mission.discodeit.entity.user.entity; - - -import com.google.common.base.Preconditions; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import java.io.Serial; -import java.io.Serializable; -import java.util.Objects; - -public class UserName implements Serializable { - - public static final int NAME_MIN_LENGTH = 3; - public static final int NAME_MAX_LENGTH = 20; - @Serial - private static final long serialVersionUID = 8759111145208252347L; - - @Size( - min = NAME_MIN_LENGTH, max = NAME_MAX_LENGTH, - message = "'${validatedValue}' must be between {min} and {max} characters long" - ) - @NotNull //TODO : => NotBlank , 테스트 코드 수정 후 변경 - private final String name; - - public UserName(String name) { - this.name = name; - } - - public static UserName createFrom(String username) { - Preconditions.checkNotNull(username); - return new UserName(username); - } - - public UserName changeName(String name) { - Preconditions.checkNotNull(name); - return new UserName(name); - } - - public String getName() { - return name; - } - - @Override - public String toString() { - return name; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - UserName userName = (UserName) o; - return Objects.equals(name, userName.name); - } - - - @Override - public int hashCode() { - return Objects.hashCode(name); - } - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/global/error/GlobalControllerAdvice.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/global/error/GlobalControllerAdvice.java new file mode 100644 index 000000000..883d03fec --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/global/error/GlobalControllerAdvice.java @@ -0,0 +1,15 @@ +package com.sprint.mission.discodeit.global.error; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalControllerAdvice { + + @ExceptionHandler(value = IllegalArgumentException.class) + public ResponseEntity illegalArgumentExceptionHandler(IllegalArgumentException exception) { + + return ResponseEntity.badRequest().body(exception.getMessage()); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/BinaryContentRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/BinaryContentRepository.java new file mode 100644 index 000000000..f7eb440f9 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/BinaryContentRepository.java @@ -0,0 +1,14 @@ +package com.sprint.mission.discodeit.repository; + +import com.sprint.mission.discodeit.entity.BinaryContent; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface BinaryContentRepository { + BinaryContent save(BinaryContent binaryContent); + Optional findById(UUID id); + List findAllByIdIn(List ids); + boolean existsById(UUID id); + void deleteById(UUID id); +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/ChannelRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/ChannelRepository.java new file mode 100644 index 000000000..359bb0c80 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/ChannelRepository.java @@ -0,0 +1,14 @@ +package com.sprint.mission.discodeit.repository; + +import com.sprint.mission.discodeit.entity.Channel; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface ChannelRepository { + Channel save(Channel channel); + Optional findById(UUID id); + List findAll(); + boolean existsById(UUID id); + void deleteById(UUID id); +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/MessageRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/MessageRepository.java new file mode 100644 index 000000000..7c2a2c14e --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/MessageRepository.java @@ -0,0 +1,15 @@ +package com.sprint.mission.discodeit.repository; + +import com.sprint.mission.discodeit.entity.Message; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface MessageRepository { + Message save(Message message); + Optional findById(UUID id); + List findAllByChannelId(UUID channelId); + boolean existsById(UUID id); + void deleteById(UUID id); + void deleteAllByChannelId(UUID channelId); +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/ReadStatusRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/ReadStatusRepository.java new file mode 100644 index 000000000..38f840218 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/ReadStatusRepository.java @@ -0,0 +1,16 @@ +package com.sprint.mission.discodeit.repository; + +import com.sprint.mission.discodeit.entity.ReadStatus; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface ReadStatusRepository { + ReadStatus save(ReadStatus readStatus); + Optional findById(UUID id); + List findAllByUserId(UUID userId); + List findAllByChannelId(UUID channelId); + boolean existsById(UUID id); + void deleteById(UUID id); + void deleteAllByChannelId(UUID channelId); +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/UserRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/UserRepository.java new file mode 100644 index 000000000..85d58cdd2 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/UserRepository.java @@ -0,0 +1,17 @@ +package com.sprint.mission.discodeit.repository; + +import com.sprint.mission.discodeit.entity.User; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface UserRepository { + User save(User user); + Optional findById(UUID id); + Optional findByUsername(String username); + List findAll(); + boolean existsById(UUID id); + void deleteById(UUID id); + boolean existsByEmail(String email); + boolean existsByUsername(String username); +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/UserStatusRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/UserStatusRepository.java new file mode 100644 index 000000000..8b8f90c82 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/UserStatusRepository.java @@ -0,0 +1,16 @@ +package com.sprint.mission.discodeit.repository; + +import com.sprint.mission.discodeit.entity.UserStatus; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface UserStatusRepository { + UserStatus save(UserStatus userStatus); + Optional findById(UUID id); + Optional findByUserId(UUID userId); + List findAll(); + boolean existsById(UUID id); + void deleteById(UUID id); + void deleteByUserId(UUID userId); +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/common/CrudRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/common/CrudRepository.java deleted file mode 100644 index 0ac8f04f9..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/common/CrudRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.sprint.mission.discodeit.repository.common; - -import java.io.FileNotFoundException; -import java.util.Optional; - -public interface CrudRepository extends Repository { - - T save(T entity); - - Optional findById(ID id); - - Iterable findAll(); - - int count(); - - void deleteById(ID id); - - boolean isExistsById(ID id); -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/common/InMemoryCrudRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/common/InMemoryCrudRepository.java deleted file mode 100644 index fd5277172..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/common/InMemoryCrudRepository.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.sprint.mission.discodeit.repository.common; - -import com.sprint.mission.discodeit.entity.common.AbstractUUIDEntity; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.UUID; - -public abstract class InMemoryCrudRepository - implements CrudRepository { - - protected final Map store = new HashMap<>(); - - @Override - public final T save(T entity) { - var id = Objects.requireNonNull(entity.getId()); - store.put(id, entity); - return entity; - } - - @Override - public Optional findById(ID id) { - var findEntity = store.get(id); - return Optional.ofNullable(findEntity); - } - - @Override - public List findAll() { - if (store.isEmpty()) { - return Collections.emptyList(); - } - - return List.copyOf(store.values()); - } - - @Override - public int count() { - return store.size(); - } - - @Override - public void deleteById(ID id) { - store.remove(id); - } - - @Override - public boolean isExistsById(ID id) { - var isExist = store.containsKey(id); - return isExist; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/common/Repository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/common/Repository.java deleted file mode 100644 index dc48a9ae8..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/common/Repository.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.sprint.mission.discodeit.repository.common; - -public interface Repository { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileAbstractRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileAbstractRepository.java deleted file mode 100644 index a90c6ad84..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileAbstractRepository.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.sprint.mission.discodeit.repository.file; - -import com.sprint.mission.discodeit.entity.common.AbstractUUIDEntity; -import com.sprint.mission.discodeit.repository.common.InMemoryCrudRepository; -import java.io.Closeable; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public abstract class FileAbstractRepository - extends InMemoryCrudRepository - implements Closeable { - - private File file; - - protected FileAbstractRepository(String filePath) { - file = new File(filePath); - } - - protected Map loadFile() { - if (!file.exists()) { - return Collections.emptyMap(); - } - - Map store = new HashMap<>(); - try ( - FileInputStream fis = new FileInputStream(file); - ObjectInputStream ois = new ObjectInputStream(fis); - ) { - while (true) { - try { - var readUser = (T) ois.readObject(); - store.put(readUser.getId(), readUser); - } catch (ClassNotFoundException e) { - System.out.println(e.getMessage()); - } - } - } catch (IOException e) { - System.out.println("User loading exit"); - } - return store; - } - - - public void saveToFile() { - try ( - FileOutputStream fos = new FileOutputStream(file); - ObjectOutputStream oos = new ObjectOutputStream(fos); - ) { - - for (T value : store.values()) { - oos.writeObject(value); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public void close() throws IOException { - saveToFile(); - } -} - diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileBinaryContentRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileBinaryContentRepository.java new file mode 100644 index 000000000..e6c841a08 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileBinaryContentRepository.java @@ -0,0 +1,114 @@ +package com.sprint.mission.discodeit.repository.file; + +import com.sprint.mission.discodeit.entity.BinaryContent; +import com.sprint.mission.discodeit.repository.BinaryContentRepository; +import com.sprint.mission.discodeit.repository.serialization.Serialization; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Stream; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "file") +@Repository +public class FileBinaryContentRepository implements BinaryContentRepository { + private static final Serialization SERIALIZATION = new Serialization<>(BinaryContent.class); + private final Path DIRECTORY; + private final String EXTENSION = ".ser"; + + public FileBinaryContentRepository( + @Value("${discodeit.repository.file-directory:data}") String fileDirectory + ) { + this.DIRECTORY = Paths.get(System.getProperty("user.dir"), fileDirectory, BinaryContent.class.getSimpleName()); + if (Files.notExists(DIRECTORY)) { + try { + Files.createDirectories(DIRECTORY); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private Path resolvePath(UUID id) { + return DIRECTORY.resolve(id + EXTENSION); + } + + @Override + public BinaryContent save(BinaryContent binaryContent) { + Path path = resolvePath(binaryContent.getId()); + try ( + FileOutputStream fos = new FileOutputStream(path.toFile()); + ObjectOutputStream oos = new ObjectOutputStream(fos) + ) { + oos.writeObject(binaryContent); + } catch (IOException ioException) { + throw new RuntimeException(ioException); + } + return binaryContent; + } + + @Override + public Optional findById(UUID id) { + BinaryContent binaryContentNullable = null; + Path path = resolvePath(id); + if (Files.exists(path)) { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + binaryContentNullable = (BinaryContent) ois.readObject(); + } catch (IOException | ClassNotFoundException exception) { + throw new RuntimeException(exception); + } + } + return Optional.ofNullable(binaryContentNullable); + } + + @Override + public List findAllByIdIn(List ids) { + try (Stream paths = Files.list(DIRECTORY)) { + return paths + .filter(path -> path.toString().endsWith(EXTENSION)) + .map(path -> { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + return (BinaryContent) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + }) + .filter(content -> ids.contains(content.getId())) + .toList(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean existsById(UUID id) { + Path path = resolvePath(id); + return Files.exists(path); + } + + @Override + public void deleteById(UUID id) { + Path path = resolvePath(id); + try { + Files.delete(path); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileChannelRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileChannelRepository.java new file mode 100644 index 000000000..37021b87a --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileChannelRepository.java @@ -0,0 +1,111 @@ +package com.sprint.mission.discodeit.repository.file; + +import com.sprint.mission.discodeit.entity.Channel; +import com.sprint.mission.discodeit.repository.ChannelRepository; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Stream; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "file") +@Repository +public class FileChannelRepository implements ChannelRepository { + private final Path DIRECTORY; + private final String EXTENSION = ".ser"; + + public FileChannelRepository( + @Value("${discodeit.repository.file-directory:data}") String fileDirectory + ) { + this.DIRECTORY = Paths.get(System.getProperty("user.dir"), fileDirectory, Channel.class.getSimpleName()); + if (Files.notExists(DIRECTORY)) { + try { + Files.createDirectories(DIRECTORY); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private Path resolvePath(UUID id) { + return DIRECTORY.resolve(id + EXTENSION); + } + + @Override + public Channel save(Channel channel) { + Path path = resolvePath(channel.getId()); + try ( + FileOutputStream fos = new FileOutputStream(path.toFile()); + ObjectOutputStream oos = new ObjectOutputStream(fos) + ) { + oos.writeObject(channel); + } catch (IOException e) { + throw new RuntimeException(e); + } + return channel; + } + + @Override + public Optional findById(UUID id) { + Channel channelNullable = null; + Path path = resolvePath(id); + if (Files.exists(path)) { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + channelNullable = (Channel) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + return Optional.ofNullable(channelNullable); + } + + @Override + public List findAll() { + try (Stream paths = Files.list(DIRECTORY)) { + return paths + .filter(path -> path.toString().endsWith(EXTENSION)) + .map(path -> { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + return (Channel) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + }) + .toList(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean existsById(UUID id) { + Path path = resolvePath(id); + return Files.exists(path); + } + + @Override + public void deleteById(UUID id) { + Path path = resolvePath(id); + try { + Files.delete(path); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileMessageRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileMessageRepository.java new file mode 100644 index 000000000..607b43c09 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileMessageRepository.java @@ -0,0 +1,118 @@ +package com.sprint.mission.discodeit.repository.file; + +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.repository.MessageRepository; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Stream; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "file") +@Repository +public class FileMessageRepository implements MessageRepository { + private final Path DIRECTORY; + private final String EXTENSION = ".ser"; + + public FileMessageRepository( + @Value("${discodeit.repository.file-directory:data}") String fileDirectory + ) { + this.DIRECTORY = Paths.get(System.getProperty("user.dir"), fileDirectory, Message.class.getSimpleName()); + if (Files.notExists(DIRECTORY)) { + try { + Files.createDirectories(DIRECTORY); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private Path resolvePath(UUID id) { + return DIRECTORY.resolve(id + EXTENSION); + } + + @Override + public Message save(Message message) { + Path path = resolvePath(message.getId()); + try ( + FileOutputStream fos = new FileOutputStream(path.toFile()); + ObjectOutputStream oos = new ObjectOutputStream(fos) + ) { + oos.writeObject(message); + } catch (IOException e) { + throw new RuntimeException(e); + } + return message; + } + + @Override + public Optional findById(UUID id) { + Message messageNullable = null; + Path path = resolvePath(id); + if (Files.exists(path)) { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + messageNullable = (Message) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + return Optional.ofNullable(messageNullable); + } + + @Override + public List findAllByChannelId(UUID channelId) { + try (Stream paths = Files.list(DIRECTORY)) { + return paths + .filter(path -> path.toString().endsWith(EXTENSION)) + .map(path -> { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + return (Message) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + }) + .filter(message -> message.getChannelId().equals(channelId)) + .toList(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean existsById(UUID id) { + Path path = resolvePath(id); + return Files.exists(path); + } + + @Override + public void deleteById(UUID id) { + Path path = resolvePath(id); + try { + Files.delete(path); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void deleteAllByChannelId(UUID channelId) { + this.findAllByChannelId(channelId) + .forEach(message -> this.deleteById(message.getId())); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileReadStatusRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileReadStatusRepository.java new file mode 100644 index 000000000..5eea98753 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileReadStatusRepository.java @@ -0,0 +1,140 @@ +package com.sprint.mission.discodeit.repository.file; + +import com.sprint.mission.discodeit.entity.ReadStatus; +import com.sprint.mission.discodeit.repository.ReadStatusRepository; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Stream; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "file") +@Repository +public class FileReadStatusRepository implements ReadStatusRepository { + private final Path DIRECTORY; + private final String EXTENSION = ".ser"; + + public FileReadStatusRepository( + @Value("${discodeit.repository.file-directory:data}") String fileDirectory + ) { + this.DIRECTORY = Paths.get(System.getProperty("user.dir"), fileDirectory, ReadStatus.class.getSimpleName()); + if (Files.notExists(DIRECTORY)) { + try { + Files.createDirectories(DIRECTORY); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private Path resolvePath(UUID id) { + return DIRECTORY.resolve(id + EXTENSION); + } + + @Override + public ReadStatus save(ReadStatus readStatus) { + Path path = resolvePath(readStatus.getId()); + try ( + FileOutputStream fos = new FileOutputStream(path.toFile()); + ObjectOutputStream oos = new ObjectOutputStream(fos) + ) { + oos.writeObject(readStatus); + } catch (IOException e) { + throw new RuntimeException(e); + } + return readStatus; + } + + @Override + public Optional findById(UUID id) { + ReadStatus readStatusNullable = null; + Path path = resolvePath(id); + if (Files.exists(path)) { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + readStatusNullable = (ReadStatus) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + return Optional.ofNullable(readStatusNullable); + } + + @Override + public List findAllByUserId(UUID userId) { + try (Stream paths = Files.list(DIRECTORY)) { + return paths + .filter(path -> path.toString().endsWith(EXTENSION)) + .map(path -> { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + return (ReadStatus) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + }) + .filter(readStatus -> readStatus.getUserId().equals(userId)) + .toList(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public List findAllByChannelId(UUID channelId) { + try (Stream paths = Files.list(DIRECTORY)) { + return paths + .filter(path -> path.toString().endsWith(EXTENSION)) + .map(path -> { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + return (ReadStatus) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + }) + .filter(readStatus -> readStatus.getChannelId().equals(channelId)) + .toList(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean existsById(UUID id) { + Path path = resolvePath(id); + return Files.exists(path); + } + + @Override + public void deleteById(UUID id) { + Path path = resolvePath(id); + try { + Files.delete(path); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void deleteAllByChannelId(UUID channelId) { + this.findAllByChannelId(channelId) + .forEach(readStatus -> this.deleteById(readStatus.getId())); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileUserRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileUserRepository.java new file mode 100644 index 000000000..4cb015a0e --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileUserRepository.java @@ -0,0 +1,130 @@ +package com.sprint.mission.discodeit.repository.file; + +import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.repository.UserRepository; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Stream; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "file") +@Repository +public class FileUserRepository implements UserRepository { + private final Path DIRECTORY; + private final String EXTENSION = ".ser"; + + public FileUserRepository( + @Value("${discodeit.repository.file-directory:data}") String fileDirectory + ) { + this.DIRECTORY = Paths.get(System.getProperty("user.dir"), fileDirectory, User.class.getSimpleName()); + if (Files.notExists(DIRECTORY)) { + try { + Files.createDirectories(DIRECTORY); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private Path resolvePath(UUID id) { + return DIRECTORY.resolve(id + EXTENSION); + } + + @Override + public User save(User user) { + Path path = resolvePath(user.getId()); + try ( + FileOutputStream fos = new FileOutputStream(path.toFile()); + ObjectOutputStream oos = new ObjectOutputStream(fos) + ) { + oos.writeObject(user); + } catch (IOException e) { + throw new RuntimeException(e); + } + return user; + } + + @Override + public Optional findById(UUID id) { + User userNullable = null; + Path path = resolvePath(id); + if (Files.exists(path)) { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + userNullable = (User) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + return Optional.ofNullable(userNullable); + } + + @Override + public Optional findByUsername(String username) { + return this.findAll().stream() + .filter(user -> user.getUsername().equals(username)) + .findFirst(); + } + + @Override + public List findAll() { + try (Stream paths = Files.list(DIRECTORY)) { + return paths + .filter(path -> path.toString().endsWith(EXTENSION)) + .map(path -> { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + return (User) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + }) + .toList(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean existsById(UUID id) { + Path path = resolvePath(id); + return Files.exists(path); + } + + @Override + public void deleteById(UUID id) { + Path path = resolvePath(id); + try { + Files.delete(path); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean existsByEmail(String email) { + return this.findAll().stream() + .anyMatch(user -> user.getEmail().equals(email)); + } + + @Override + public boolean existsByUsername(String username) { + return this.findAll().stream() + .anyMatch(user -> user.getUsername().equals(username)); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileUserStatusRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileUserStatusRepository.java new file mode 100644 index 000000000..7cb308ba4 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/FileUserStatusRepository.java @@ -0,0 +1,124 @@ +package com.sprint.mission.discodeit.repository.file; + +import com.sprint.mission.discodeit.entity.UserStatus; +import com.sprint.mission.discodeit.repository.UserStatusRepository; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Stream; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "file") +@Repository +public class FileUserStatusRepository implements UserStatusRepository { + private final Path DIRECTORY; + private final String EXTENSION = ".ser"; + + public FileUserStatusRepository( + @Value("${discodeit.repository.file-directory:data}") String fileDirectory + ) { + this.DIRECTORY = Paths.get(System.getProperty("user.dir"), fileDirectory, UserStatus.class.getSimpleName()); + if (Files.notExists(DIRECTORY)) { + try { + Files.createDirectories(DIRECTORY); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private Path resolvePath(UUID id) { + return DIRECTORY.resolve(id + EXTENSION); + } + + @Override + public UserStatus save(UserStatus userStatus) { + Path path = resolvePath(userStatus.getId()); + try ( + FileOutputStream fos = new FileOutputStream(path.toFile()); + ObjectOutputStream oos = new ObjectOutputStream(fos) + ) { + oos.writeObject(userStatus); + } catch (IOException e) { + throw new RuntimeException(e); + } + return userStatus; + } + + @Override + public Optional findById(UUID id) { + UserStatus userStatusNullable = null; + Path path = resolvePath(id); + if (Files.exists(path)) { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + userStatusNullable = (UserStatus) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + return Optional.ofNullable(userStatusNullable); + } + + @Override + public Optional findByUserId(UUID userId) { + return findAll().stream() + .filter(userStatus -> userStatus.getUserId().equals(userId)) + .findFirst(); + } + + @Override + public List findAll() { + try (Stream paths = Files.list(DIRECTORY)) { + return paths + .filter(path -> path.toString().endsWith(EXTENSION)) + .map(path -> { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + return (UserStatus) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + }) + .toList(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean existsById(UUID id) { + Path path = resolvePath(id); + return Files.exists(path); + } + + @Override + public void deleteById(UUID id) { + Path path = resolvePath(id); + try { + Files.delete(path); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void deleteByUserId(UUID userId) { + this.findByUserId(userId) + .ifPresent(userStatus -> this.deleteById(userStatus.getId())); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/channel/FileChannelRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/channel/FileChannelRepository.java deleted file mode 100644 index 49b2e2033..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/channel/FileChannelRepository.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.sprint.mission.discodeit.repository.file.channel; - -import com.sprint.mission.discodeit.entity.channel.Channel; -import com.sprint.mission.discodeit.repository.jcf.channel.ChannelRepository; -import com.sprint.mission.discodeit.repository.file.FileAbstractRepository; -import java.util.UUID; - -public class FileChannelRepository extends FileAbstractRepository implements ChannelRepository { - private static final String CHANNEL_FILE_PATH_NAME = "temp/file/user/channel.ser"; - private static ChannelRepository FILE_USER_REPOSITORY_INSTANCE; - - protected FileChannelRepository() { - super(CHANNEL_FILE_PATH_NAME); - store.putAll(loadFile()); - } - - public static ChannelRepository getInstance() { - if (FILE_USER_REPOSITORY_INSTANCE == null) { - FILE_USER_REPOSITORY_INSTANCE = new FileChannelRepository(); - } - return FILE_USER_REPOSITORY_INSTANCE; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/message/FileChannelMessageRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/message/FileChannelMessageRepository.java deleted file mode 100644 index 1ba6fd4a1..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/message/FileChannelMessageRepository.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.sprint.mission.discodeit.repository.file.message; - -import com.sprint.mission.discodeit.entity.message.ChannelMessage; -import com.sprint.mission.discodeit.repository.file.FileAbstractRepository; -import com.sprint.mission.discodeit.repository.jcf.message.ChannelMessage.ChannelMessageRepository; -import java.util.UUID; - -public class FileChannelMessageRepository extends FileAbstractRepository - implements ChannelMessageRepository { - - private static final String CHANNEL_MESSAGE_FILE_PATH_NAME = "temp/file/user/channelMessage.ser"; - private static ChannelMessageRepository INSTANCE; - - - protected FileChannelMessageRepository(String filePath) { - super(filePath); - store.putAll(loadFile()); - } - - public static ChannelMessageRepository getInstance() { - if (INSTANCE == null) { - INSTANCE = new FileChannelMessageRepository(CHANNEL_MESSAGE_FILE_PATH_NAME); - } - return INSTANCE; - } - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/message/FileDirectMessageRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/message/FileDirectMessageRepository.java deleted file mode 100644 index ab2e79264..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/message/FileDirectMessageRepository.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.sprint.mission.discodeit.repository.file.message; - -import com.sprint.mission.discodeit.entity.message.DirectMessage; -import com.sprint.mission.discodeit.repository.file.FileAbstractRepository; -import com.sprint.mission.discodeit.repository.jcf.message.directMessage.DirectMessageRepository; -import java.util.UUID; - -public class FileDirectMessageRepository extends FileAbstractRepository implements - DirectMessageRepository { - private static final String DIRECT_MESSAGE_FILE_PATH_NAME = "temp/file/user/channel.ser"; - private static FileDirectMessageRepository FILE_DIRECT_REPOSITORY_INSTANCE; - - protected FileDirectMessageRepository() { - super(DIRECT_MESSAGE_FILE_PATH_NAME); - store.putAll(loadFile()); - } - - public static DirectMessageRepository getInstance() { - if (FILE_DIRECT_REPOSITORY_INSTANCE == null) { - FILE_DIRECT_REPOSITORY_INSTANCE = new FileDirectMessageRepository(); - } - return FILE_DIRECT_REPOSITORY_INSTANCE; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/user/FileUserRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/user/FileUserRepository.java deleted file mode 100644 index bef1ebc48..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/file/user/FileUserRepository.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.sprint.mission.discodeit.repository.file.user; - -import com.sprint.mission.discodeit.entity.user.entity.User; -import com.sprint.mission.discodeit.repository.file.FileAbstractRepository; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import java.util.Optional; -import java.util.UUID; - -public class FileUserRepository extends FileAbstractRepository implements UserRepository { - private static final String FILE_PATH_USER_NAME = "temp/file/user/user.ser"; - private static UserRepository FILE_USER_REPOSITORY_INSTANCE; - - private FileUserRepository() { - super(FILE_PATH_USER_NAME); - store.putAll(loadFile()); - } - - public static UserRepository getInstance() { - if (FILE_USER_REPOSITORY_INSTANCE == null) { - FILE_USER_REPOSITORY_INSTANCE = new FileUserRepository(); - } - return FILE_USER_REPOSITORY_INSTANCE; - } - - @Override - public Optional findByUsername(String username) { - var findUser = findAll().stream() - .filter(user -> username.equals(user.getName())) - .findFirst(); - - return findUser; - } - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFBinaryContentRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFBinaryContentRepository.java new file mode 100644 index 000000000..6b17d5b19 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFBinaryContentRepository.java @@ -0,0 +1,49 @@ +package com.sprint.mission.discodeit.repository.jcf; + +import com.sprint.mission.discodeit.entity.BinaryContent; +import com.sprint.mission.discodeit.repository.BinaryContentRepository; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "jcf", matchIfMissing = true) +@Repository +public class JCFBinaryContentRepository implements BinaryContentRepository { + private final Map data; + + public JCFBinaryContentRepository() { + this.data = new HashMap<>(); + } + + @Override + public BinaryContent save(BinaryContent binaryContent) { + this.data.put(binaryContent.getId(), binaryContent); + return binaryContent; + } + + @Override + public Optional findById(UUID id) { + return Optional.ofNullable(this.data.get(id)); + } + + @Override + public List findAllByIdIn(List ids) { + return this.data.values().stream() + .filter(content -> ids.contains(content.getId())) + .toList(); + } + + @Override + public boolean existsById(UUID id) { + return this.data.containsKey(id); + } + + @Override + public void deleteById(UUID id) { + this.data.remove(id); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFChannelRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFChannelRepository.java new file mode 100644 index 000000000..269c68d8b --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFChannelRepository.java @@ -0,0 +1,47 @@ +package com.sprint.mission.discodeit.repository.jcf; + +import com.sprint.mission.discodeit.entity.Channel; +import com.sprint.mission.discodeit.repository.ChannelRepository; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "jcf", matchIfMissing = true) +@Repository +public class JCFChannelRepository implements ChannelRepository { + private final Map data; + + public JCFChannelRepository() { + this.data = new HashMap<>(); + } + + @Override + public Channel save(Channel channel) { + this.data.put(channel.getId(), channel); + return channel; + } + + @Override + public Optional findById(UUID id) { + return Optional.ofNullable(this.data.get(id)); + } + + @Override + public List findAll() { + return this.data.values().stream().toList(); + } + + @Override + public boolean existsById(UUID id) { + return this.data.containsKey(id); + } + + @Override + public void deleteById(UUID id) { + this.data.remove(id); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFMessageRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFMessageRepository.java new file mode 100644 index 000000000..ee41b0831 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFMessageRepository.java @@ -0,0 +1,53 @@ +package com.sprint.mission.discodeit.repository.jcf; + +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.repository.MessageRepository; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "jcf", matchIfMissing = true) +@Repository +public class JCFMessageRepository implements MessageRepository { + private final Map data; + + public JCFMessageRepository() { + this.data = new HashMap<>(); + } + + @Override + public Message save(Message message) { + this.data.put(message.getId(), message); + return message; + } + + @Override + public Optional findById(UUID id) { + return Optional.ofNullable(this.data.get(id)); + } + + @Override + public List findAllByChannelId(UUID channelId) { + return this.data.values().stream().filter(message -> message.getChannelId().equals(channelId)).toList(); + } + + @Override + public boolean existsById(UUID id) { + return this.data.containsKey(id); + } + + @Override + public void deleteById(UUID id) { + this.data.remove(id); + } + + @Override + public void deleteAllByChannelId(UUID channelId) { + this.findAllByChannelId(channelId) + .forEach(message -> this.deleteById(message.getId())); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFReadStatusRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFReadStatusRepository.java new file mode 100644 index 000000000..c3e332672 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFReadStatusRepository.java @@ -0,0 +1,62 @@ +package com.sprint.mission.discodeit.repository.jcf; + +import com.sprint.mission.discodeit.entity.ReadStatus; +import com.sprint.mission.discodeit.repository.ReadStatusRepository; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "jcf", matchIfMissing = true) +@Repository +public class JCFReadStatusRepository implements ReadStatusRepository { + private final Map data; + + public JCFReadStatusRepository() { + this.data = new HashMap<>(); + } + + @Override + public ReadStatus save(ReadStatus readStatus) { + this.data.put(readStatus.getId(), readStatus); + return readStatus; + } + + @Override + public Optional findById(UUID id) { + return Optional.ofNullable(this.data.get(id)); + } + + @Override + public List findAllByUserId(UUID userId) { + return this.data.values().stream() + .filter(readStatus -> readStatus.getUserId().equals(userId)) + .toList(); + } + + @Override + public List findAllByChannelId(UUID channelId) { + return this.data.values().stream() + .filter(readStatus -> readStatus.getChannelId().equals(channelId)) + .toList(); + } + + @Override + public boolean existsById(UUID id) { + return this.data.containsKey(id); + } + + @Override + public void deleteById(UUID id) { + this.data.remove(id); + } + + @Override + public void deleteAllByChannelId(UUID channelId) { + this.findAllByChannelId(channelId) + .forEach(readStatus -> this.deleteById(readStatus.getId())); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFUserRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFUserRepository.java new file mode 100644 index 000000000..2080176f6 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFUserRepository.java @@ -0,0 +1,64 @@ +package com.sprint.mission.discodeit.repository.jcf; + +import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.repository.UserRepository; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "jcf", matchIfMissing = true) +@Repository +public class JCFUserRepository implements UserRepository { + private final Map data; + + public JCFUserRepository() { + this.data = new HashMap<>(); + } + + @Override + public User save(User user) { + this.data.put(user.getId(), user); + return user; + } + + @Override + public Optional findById(UUID id) { + return Optional.ofNullable(this.data.get(id)); + } + + @Override + public Optional findByUsername(String username) { + return this.findAll().stream() + .filter(user -> user.getUsername().equals(username)) + .findFirst(); + } + + @Override + public List findAll() { + return this.data.values().stream().toList(); + } + + @Override + public boolean existsById(UUID id) { + return this.data.containsKey(id); + } + + @Override + public void deleteById(UUID id) { + this.data.remove(id); + } + + @Override + public boolean existsByEmail(String email) { + return this.findAll().stream().anyMatch(user -> user.getEmail().equals(email)); + } + + @Override + public boolean existsByUsername(String username) { + return this.findAll().stream().anyMatch(user -> user.getUsername().equals(username)); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFUserStatusRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFUserStatusRepository.java new file mode 100644 index 000000000..c76b3a8ef --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFUserStatusRepository.java @@ -0,0 +1,60 @@ +package com.sprint.mission.discodeit.repository.jcf; + +import com.sprint.mission.discodeit.entity.UserStatus; +import com.sprint.mission.discodeit.repository.UserStatusRepository; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "jcf", matchIfMissing = true) +@Repository +public class JCFUserStatusRepository implements UserStatusRepository { + private final Map data; + + public JCFUserStatusRepository() { + this.data = new HashMap<>(); + } + + @Override + public UserStatus save(UserStatus userStatus) { + this.data.put(userStatus.getId(), userStatus); + return userStatus; + } + + @Override + public Optional findById(UUID id) { + return Optional.ofNullable(this.data.get(id)); + } + + @Override + public Optional findByUserId(UUID userId) { + return this.findAll().stream() + .filter(userStatus -> userStatus.getUserId().equals(userId)) + .findFirst(); + } + + @Override + public List findAll() { + return this.data.values().stream().toList(); + } + + @Override + public boolean existsById(UUID id) { + return this.data.containsKey(id); + } + + @Override + public void deleteById(UUID id) { + this.data.remove(id); + } + + @Override + public void deleteByUserId(UUID userId) { + this.findByUserId(userId) + .ifPresent(userStatus -> this.deleteByUserId(userStatus.getId())); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/channel/ChannelRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/channel/ChannelRepository.java deleted file mode 100644 index 1a5bbc5fc..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/channel/ChannelRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.sprint.mission.discodeit.repository.jcf.channel; - -import com.sprint.mission.discodeit.repository.common.CrudRepository; -import com.sprint.mission.discodeit.entity.channel.Channel; -import java.util.UUID; - -public interface ChannelRepository extends CrudRepository { - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/channel/JCFChannelRepositoryInMemory.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/channel/JCFChannelRepositoryInMemory.java deleted file mode 100644 index 68faf6f8e..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/channel/JCFChannelRepositoryInMemory.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.sprint.mission.discodeit.repository.jcf.channel; - -import com.sprint.mission.discodeit.repository.common.InMemoryCrudRepository; -import com.sprint.mission.discodeit.entity.channel.Channel; -import java.util.UUID; - -public class JCFChannelRepositoryInMemory extends InMemoryCrudRepository implements ChannelRepository { - private JCFChannelRepositoryInMemory() {} - - public static ChannelRepository getChannelRepositoryInMemory() { - return new JCFChannelRepositoryInMemory(); - } - - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/message/ChannelMessage/ChannelMessageRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/message/ChannelMessage/ChannelMessageRepository.java deleted file mode 100644 index b78ce6471..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/message/ChannelMessage/ChannelMessageRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.sprint.mission.discodeit.repository.jcf.message.ChannelMessage; - -import com.sprint.mission.discodeit.repository.common.CrudRepository; -import com.sprint.mission.discodeit.entity.message.ChannelMessage; -import java.util.UUID; - -public interface ChannelMessageRepository extends CrudRepository { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/message/ChannelMessage/JCFChannelMessageRepositoryInMemory.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/message/ChannelMessage/JCFChannelMessageRepositoryInMemory.java deleted file mode 100644 index e6559940a..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/message/ChannelMessage/JCFChannelMessageRepositoryInMemory.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.sprint.mission.discodeit.repository.jcf.message.ChannelMessage; - -import com.sprint.mission.discodeit.repository.common.InMemoryCrudRepository; -import com.sprint.mission.discodeit.entity.message.ChannelMessage; -import java.util.UUID; - -public class JCFChannelMessageRepositoryInMemory extends InMemoryCrudRepository implements ChannelMessageRepository { - - private JCFChannelMessageRepositoryInMemory() {} - - public static JCFChannelMessageRepositoryInMemory getInstance() { - return new JCFChannelMessageRepositoryInMemory(); - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/message/directMessage/DirectMessageRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/message/directMessage/DirectMessageRepository.java deleted file mode 100644 index 9cbd28670..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/message/directMessage/DirectMessageRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.sprint.mission.discodeit.repository.jcf.message.directMessage; - -import com.sprint.mission.discodeit.repository.common.CrudRepository; -import com.sprint.mission.discodeit.entity.message.DirectMessage; -import java.util.UUID; - -public interface DirectMessageRepository extends CrudRepository { - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/message/directMessage/JCFDirectMessageRepositoryInMemory.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/message/directMessage/JCFDirectMessageRepositoryInMemory.java deleted file mode 100644 index 6144a3735..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/message/directMessage/JCFDirectMessageRepositoryInMemory.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.sprint.mission.discodeit.repository.jcf.message.directMessage; - -import com.sprint.mission.discodeit.repository.common.InMemoryCrudRepository; -import com.sprint.mission.discodeit.entity.message.DirectMessage; -import java.util.UUID; - -public class JCFDirectMessageRepositoryInMemory extends InMemoryCrudRepository - implements DirectMessageRepository { - - private JCFDirectMessageRepositoryInMemory() {} - - public static JCFDirectMessageRepositoryInMemory getInstance() { - return new JCFDirectMessageRepositoryInMemory(); - } - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/user/JCFUserRepositoryInMemory.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/user/JCFUserRepositoryInMemory.java deleted file mode 100644 index dd48cb4b8..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/user/JCFUserRepositoryInMemory.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.sprint.mission.discodeit.repository.jcf.user; - -import com.sprint.mission.discodeit.repository.common.InMemoryCrudRepository; -import com.sprint.mission.discodeit.entity.user.entity.User; -import java.util.Optional; -import java.util.UUID; - -public class JCFUserRepositoryInMemory extends InMemoryCrudRepository implements UserRepository { - - private static UserRepository INSTANCE; - - private JCFUserRepositoryInMemory() {} - - @Override - public Optional findByUsername(String username) { - var findUser = findAll().stream() - .filter(user -> username.equals(user.getName())) - .findFirst(); - - return findUser; - } - - - public static UserRepository getInstance() { - if (INSTANCE == null) { - INSTANCE = new JCFUserRepositoryInMemory(); - } - - return INSTANCE; - } - - public static UserRepository getUserRepositoryInMemory() { - return new JCFUserRepositoryInMemory(); - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/user/UserRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/user/UserRepository.java deleted file mode 100644 index 4f22cf196..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/jcf/user/UserRepository.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.sprint.mission.discodeit.repository.jcf.user; - -import com.sprint.mission.discodeit.repository.common.CrudRepository; -import com.sprint.mission.discodeit.entity.user.entity.User; -import java.util.Optional; -import java.util.UUID; - -public interface UserRepository extends CrudRepository { - - Optional findByUsername(String username); - - public static UserRepository getInMemoryUserRepositoryImpl() { - return JCFUserRepositoryInMemory.getInstance(); - } - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/serialization/Serialization.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/serialization/Serialization.java new file mode 100644 index 000000000..27ef2346f --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/repository/serialization/Serialization.java @@ -0,0 +1,39 @@ +package com.sprint.mission.discodeit.repository.serialization; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.nio.file.Path; + +public class Serialization { + + private final Class type; + + public Serialization(Class type) { + this.type = type; + } + + public void serialize(Path path, T t) { + try ( + FileOutputStream fos = new FileOutputStream(path.toFile()); + ObjectOutputStream oos = new ObjectOutputStream(fos) + ) { + oos.writeObject(t); + } catch (IOException ioException) { + throw new RuntimeException(ioException); + } + } + + public T deserialize(Path path) { + try ( + FileInputStream fis = new FileInputStream(path.toFile()); + ObjectInputStream ois = new ObjectInputStream(fis) + ) { + return type.cast(ois.readObject()); + } catch (IOException | ClassNotFoundException exception) { + throw new RuntimeException(exception); + } + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/AuthService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/AuthService.java new file mode 100644 index 000000000..fcc2b1af0 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/AuthService.java @@ -0,0 +1,8 @@ +package com.sprint.mission.discodeit.service; + +import com.sprint.mission.discodeit.dto.request.LoginRequest; +import com.sprint.mission.discodeit.entity.User; + +public interface AuthService { + User login(LoginRequest loginRequest); +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/BinaryContentService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/BinaryContentService.java new file mode 100644 index 000000000..140fea9e5 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/BinaryContentService.java @@ -0,0 +1,13 @@ +package com.sprint.mission.discodeit.service; + +import com.sprint.mission.discodeit.dto.request.BinaryContentCreateRequest; +import com.sprint.mission.discodeit.entity.BinaryContent; +import java.util.List; +import java.util.UUID; + +public interface BinaryContentService { + BinaryContent create(BinaryContentCreateRequest request); + BinaryContent find(UUID binaryContentId); + List findAllByIdIn(List binaryContentIds); + void delete(UUID binaryContentId); +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/ChannelService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/ChannelService.java new file mode 100644 index 000000000..28052b331 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/ChannelService.java @@ -0,0 +1,18 @@ +package com.sprint.mission.discodeit.service; + +import com.sprint.mission.discodeit.dto.data.ChannelDto; +import com.sprint.mission.discodeit.dto.request.PrivateChannelCreateRequest; +import com.sprint.mission.discodeit.dto.request.PublicChannelCreateRequest; +import com.sprint.mission.discodeit.dto.request.PublicChannelUpdateRequest; +import com.sprint.mission.discodeit.entity.Channel; +import java.util.List; +import java.util.UUID; + +public interface ChannelService { + Channel create(PublicChannelCreateRequest request); + Channel create(PrivateChannelCreateRequest request); + ChannelDto find(UUID channelId); + List findAllByUserId(UUID userId); + Channel update(UUID channelId, PublicChannelUpdateRequest request); + void delete(UUID channelId); +} \ No newline at end of file diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/MessageService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/MessageService.java new file mode 100644 index 000000000..8fcc62d34 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/MessageService.java @@ -0,0 +1,16 @@ +package com.sprint.mission.discodeit.service; + +import com.sprint.mission.discodeit.dto.request.BinaryContentCreateRequest; +import com.sprint.mission.discodeit.dto.request.MessageCreateRequest; +import com.sprint.mission.discodeit.dto.request.MessageUpdateRequest; +import com.sprint.mission.discodeit.entity.Message; +import java.util.List; +import java.util.UUID; + +public interface MessageService { + Message create(MessageCreateRequest messageCreateRequest, List binaryContentCreateRequests); + Message find(UUID messageId); + List findAllByChannelId(UUID channelId); + Message update(UUID messageId, MessageUpdateRequest request); + void delete(UUID messageId); +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/ReadStatusService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/ReadStatusService.java new file mode 100644 index 000000000..2d7775c68 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/ReadStatusService.java @@ -0,0 +1,15 @@ +package com.sprint.mission.discodeit.service; + +import com.sprint.mission.discodeit.dto.request.ReadStatusCreateRequest; +import com.sprint.mission.discodeit.dto.request.ReadStatusUpdateRequest; +import com.sprint.mission.discodeit.entity.ReadStatus; +import java.util.List; +import java.util.UUID; + +public interface ReadStatusService { + ReadStatus create(ReadStatusCreateRequest request); + ReadStatus find(UUID readStatusId); + List findAllByUserId(UUID userId); + ReadStatus update(UUID readStatusId, ReadStatusUpdateRequest request); + void delete(UUID readStatusId); +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/UserService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/UserService.java new file mode 100644 index 000000000..228cacdf9 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/UserService.java @@ -0,0 +1,18 @@ +package com.sprint.mission.discodeit.service; + +import com.sprint.mission.discodeit.dto.data.UserDto; +import com.sprint.mission.discodeit.dto.request.BinaryContentCreateRequest; +import com.sprint.mission.discodeit.dto.request.UserCreateRequest; +import com.sprint.mission.discodeit.dto.request.UserUpdateRequest; +import com.sprint.mission.discodeit.entity.User; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface UserService { + User create(UserCreateRequest userCreateRequest, Optional profileCreateRequest); + UserDto find(UUID userId); + List findAll(); + User update(UUID userId, UserUpdateRequest userUpdateRequest, Optional profileCreateRequest); + void delete(UUID userId); +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/UserStatusService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/UserStatusService.java new file mode 100644 index 000000000..99d54e32f --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/UserStatusService.java @@ -0,0 +1,16 @@ +package com.sprint.mission.discodeit.service; + +import com.sprint.mission.discodeit.dto.request.UserStatusCreateRequest; +import com.sprint.mission.discodeit.dto.request.UserStatusUpdateRequest; +import com.sprint.mission.discodeit.entity.UserStatus; +import java.util.List; +import java.util.UUID; + +public interface UserStatusService { + UserStatus create(UserStatusCreateRequest request); + UserStatus find(UUID userStatusId); + List findAll(); + UserStatus update(UUID userStatusId, UserStatusUpdateRequest request); + UserStatus updateByUserId(UUID userId, UserStatusUpdateRequest request); + void delete(UUID userStatusId); +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicAuthService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicAuthService.java new file mode 100644 index 000000000..8c5a2645c --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicAuthService.java @@ -0,0 +1,30 @@ +package com.sprint.mission.discodeit.service.basic; + +import com.sprint.mission.discodeit.dto.request.LoginRequest; +import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.repository.UserRepository; +import com.sprint.mission.discodeit.service.AuthService; +import java.util.NoSuchElementException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class BasicAuthService implements AuthService { + private final UserRepository userRepository; + + @Override + public User login(LoginRequest loginRequest) { + String username = loginRequest.username(); + String password = loginRequest.password(); + + User user = userRepository.findByUsername(username) + .orElseThrow(() -> new NoSuchElementException("User with username " + username + " not found")); + + if (!user.getPassword().equals(password)) { + throw new IllegalArgumentException("Wrong password"); + } + + return user; + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicBinaryContentService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicBinaryContentService.java new file mode 100644 index 000000000..885b17147 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicBinaryContentService.java @@ -0,0 +1,51 @@ +package com.sprint.mission.discodeit.service.basic; + +import com.sprint.mission.discodeit.dto.request.BinaryContentCreateRequest; +import com.sprint.mission.discodeit.entity.BinaryContent; +import com.sprint.mission.discodeit.repository.BinaryContentRepository; +import com.sprint.mission.discodeit.service.BinaryContentService; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class BasicBinaryContentService implements BinaryContentService { + private final BinaryContentRepository binaryContentRepository; + + @Override + public BinaryContent create(BinaryContentCreateRequest request) { + String fileName = request.fileName(); + byte[] bytes = request.bytes(); + String contentType = request.contentType(); + BinaryContent binaryContent = new BinaryContent( + fileName, + (long) bytes.length, + contentType, + bytes + ); + return binaryContentRepository.save(binaryContent); + } + + @Override + public BinaryContent find(UUID binaryContentId) { + return binaryContentRepository.findById(binaryContentId) + .orElseThrow(() -> new NoSuchElementException("BinaryContent with id " + binaryContentId + " not found")); + } + + @Override + public List findAllByIdIn(List binaryContentIds) { + return binaryContentRepository.findAllByIdIn(binaryContentIds).stream() + .toList(); + } + + @Override + public void delete(UUID binaryContentId) { + if (!binaryContentRepository.existsById(binaryContentId)) { + throw new NoSuchElementException("BinaryContent with id " + binaryContentId + " not found"); + } + binaryContentRepository.deleteById(binaryContentId); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicChannelMessageService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicChannelMessageService.java deleted file mode 100644 index 8c875ba3a..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicChannelMessageService.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.sprint.mission.discodeit.service.basic; - -import com.sprint.mission.discodeit.common.error.ErrorCode; -import com.sprint.mission.discodeit.common.error.channel.ChannelException; -import com.sprint.mission.discodeit.common.error.user.UserException; -import com.sprint.mission.discodeit.entity.channel.Channel; -import com.sprint.mission.discodeit.entity.message.ChannelMessage; -import com.sprint.mission.discodeit.entity.message.dto.ChannelMessageInfoResponse; -import com.sprint.mission.discodeit.entity.message.dto.SendChannelMessageRequest; -import com.sprint.mission.discodeit.entity.user.entity.User; -import com.sprint.mission.discodeit.repository.jcf.channel.ChannelRepository; -import com.sprint.mission.discodeit.repository.jcf.message.ChannelMessage.ChannelMessageRepository; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.service.message.channelMessage.ChannelMessageService; -import com.sprint.mission.discodeit.service.message.converter.ChannelMessageConverter; -import java.util.UUID; - -public class BasicChannelMessageService implements ChannelMessageService { - - private final UserRepository userRepository; - private final ChannelRepository channelRepository; - private final ChannelMessageRepository channelMessageRepository; - private final ChannelMessageConverter converter; - - private BasicChannelMessageService( - UserRepository userRepository, - ChannelRepository channelRepository, - ChannelMessageRepository channelMessageRepository, - ChannelMessageConverter converter - ) { - this.userRepository = userRepository; - this.channelRepository = channelRepository; - this.channelMessageRepository = channelMessageRepository; - this.converter = converter; - } - - public static ChannelMessageService getInstance( - UserRepository userRepository, - ChannelRepository channelRepository, - ChannelMessageRepository channelMessageRepository - ) { - var converter = new ChannelMessageConverter(); - return new BasicChannelMessageService(userRepository, channelRepository, channelMessageRepository, converter); - } - - @Override - public ChannelMessageInfoResponse sendMessage(SendChannelMessageRequest sendChannelMessageRequest) { - // 유저 찾기 - var foundUser = findUserByIdOrThrow(sendChannelMessageRequest.sendUserId()); - // 채널 찾기 - var foundChannel = findChannelByIdOrThrow(sendChannelMessageRequest.receiveChannelId()); - // 메시지 생성 - var channelMessage = ChannelMessage.ofMessageAndSenderAndReceiverChannel( - sendChannelMessageRequest.message(), - foundUser, - foundChannel - ); - // 메시지 저장 - var savedMessage = channelMessageRepository.save(channelMessage); - // 메시지 전송 - savedMessage.sendMessage(); - // 생성된 메시지 반환 - return converter.toDto(savedMessage); - } - - /** - * ==> 코드리뷰 부탁드립니다. 유저 서비스에 다른 서비스에서 이용하기 위한 메서드를 넣는게 바람직한가요? - * ==> 제 생각은, 유저 서비스에 같은 기능으로 호출하는 기능이 필요하다면 추가하지만, 없다면 안넣는게 낫다고 생각함. 넣는다면 userRepository - * 그런데, 유저 서비스에서 id로만 찾는 유저를 찾는 기능이 있는가? 구현한 내용은 유저 서비스 레이어 안에서만 private 구현 - * 코드 중복이 너무 많이 발생함, 이를 해결하기 위해 userService, userRepository 둘 중 하나에 메서드를 만드는 방법 중 어디가 좋을까요? - * - * ==> 다른 서비스 레이어를 의존하도록 해서 호출해도 괜찮을까요 ? - */ - private User findUserByIdOrThrow(UUID userId) { - var foundUser = userRepository.findById(userId) - .filter(User::isRegistered) - .orElseThrow(() -> UserException.ofNotJoinChannel( - ErrorCode.USER_NOT_FOUND, userId.toString() - )); - - return foundUser; - } - - - private Channel findChannelByIdOrThrow(UUID channelId) { - var foundChannel = channelRepository.findById(channelId) - .orElseThrow(() -> ChannelException.ofNotFound( - ErrorCode.CHANNEL_NOT_FOUND, - channelId - )); - return foundChannel; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicChannelService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicChannelService.java index dacd11089..3faf4ce0c 100644 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicChannelService.java +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicChannelService.java @@ -1,87 +1,125 @@ package com.sprint.mission.discodeit.service.basic; -import static com.sprint.mission.discodeit.common.error.ErrorCode.CHANNEL_NOT_FOUND; -import static com.sprint.mission.discodeit.common.error.ErrorCode.USER_NOT_FOUND; - -import com.sprint.mission.discodeit.common.error.channel.ChannelException; -import com.sprint.mission.discodeit.common.error.user.UserException; -import com.sprint.mission.discodeit.entity.channel.dto.ChangeChannelNameRequest; -import com.sprint.mission.discodeit.entity.channel.dto.ChannelResponse; -import com.sprint.mission.discodeit.entity.channel.dto.CreateNewChannelRequest; -import com.sprint.mission.discodeit.entity.channel.dto.DeleteChannelRequest; -import com.sprint.mission.discodeit.entity.user.entity.User; -import com.sprint.mission.discodeit.repository.jcf.channel.ChannelRepository; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.service.channel.ChannelConverter; -import com.sprint.mission.discodeit.service.channel.ChannelService; +import com.sprint.mission.discodeit.dto.data.ChannelDto; +import com.sprint.mission.discodeit.dto.request.PrivateChannelCreateRequest; +import com.sprint.mission.discodeit.dto.request.PublicChannelCreateRequest; +import com.sprint.mission.discodeit.dto.request.PublicChannelUpdateRequest; +import com.sprint.mission.discodeit.entity.Channel; +import com.sprint.mission.discodeit.entity.ChannelType; +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.entity.ReadStatus; +import com.sprint.mission.discodeit.repository.ChannelRepository; +import com.sprint.mission.discodeit.repository.MessageRepository; +import com.sprint.mission.discodeit.repository.ReadStatusRepository; +import com.sprint.mission.discodeit.service.ChannelService; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.NoSuchElementException; import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +@RequiredArgsConstructor +@Service public class BasicChannelService implements ChannelService { - private final ChannelRepository channelRepository; - private final UserRepository userRepository; - private final ChannelConverter channelConverter; - - private BasicChannelService( - ChannelRepository channelRepository, - UserRepository userRepository, - ChannelConverter channelConverter - ) { - this.channelRepository = channelRepository; - this.userRepository = userRepository; - this.channelConverter = channelConverter; - } + // + private final ReadStatusRepository readStatusRepository; + private final MessageRepository messageRepository; + + @Override + public Channel create(PublicChannelCreateRequest request) { + String name = request.name(); + String description = request.description(); + Channel channel = new Channel(ChannelType.PUBLIC, name, description); - public static ChannelService getInstance(UserRepository userRepository, ChannelRepository channelRepository) { - return new BasicChannelService(channelRepository, userRepository, new ChannelConverter()); + return channelRepository.save(channel); } @Override - public ChannelResponse createChannelOrThrow(CreateNewChannelRequest request) { - /** - * ==> 코드리뷰 : 메서드 내부에 다른 메서드를 호출하면서 throw가 발생가능하다는 것을 코드 블록의 메서드의 이름에 추가해야할까요? - * createChannel VS createChannelOrThrow - */ - var findUser = findUserByIdOrThrow(request.userId()); - - var createdChannel = findUser.openNewChannel(request.channelName()); + public Channel create(PrivateChannelCreateRequest request) { + Channel channel = new Channel(ChannelType.PRIVATE, null, null); + Channel createdChannel = channelRepository.save(channel); - channelRepository.save(createdChannel); - userRepository.save(findUser); + request.participantIds().stream() + .map(userId -> new ReadStatus(userId, createdChannel.getId(), Instant.MIN)) + .forEach(readStatusRepository::save); - return channelConverter.toDto(createdChannel); + return createdChannel; } @Override - public void changeChannelNameOrThrow(ChangeChannelNameRequest request) { - var foundUser = findUserByIdOrThrow(request.userId()); - - var changedChannel = foundUser.changeChannelName(request.channelId(), request.newChannelName()); + public ChannelDto find(UUID channelId) { + return channelRepository.findById(channelId) + .map(this::toDto) + .orElseThrow(() -> new NoSuchElementException("Channel with id " + channelId + " not found")); + } - channelRepository.save(changedChannel); - userRepository.save(foundUser); + @Override + public List findAllByUserId(UUID userId) { + List mySubscribedChannelIds = readStatusRepository.findAllByUserId(userId).stream() + .map(ReadStatus::getChannelId) + .toList(); + + return channelRepository.findAll().stream() + .filter(channel -> + channel.getType().equals(ChannelType.PUBLIC) + || mySubscribedChannelIds.contains(channel.getId()) + ) + .map(this::toDto) + .toList(); } @Override - public void deleteChannelByChannelIdOrThrow(DeleteChannelRequest request) { - var foundChannel = channelRepository.findById(request.channelId()) - .orElseThrow( - () -> ChannelException.ofNotFound( - CHANNEL_NOT_FOUND, - request.channelId()) - ); - - var foundUser = findUserByIdOrThrow(request.userId()); - foundChannel.deleteChannel(foundUser); - - channelRepository.save(foundChannel); + public Channel update(UUID channelId, PublicChannelUpdateRequest request) { + String newName = request.newName(); + String newDescription = request.newDescription(); + Channel channel = channelRepository.findById(channelId) + .orElseThrow(() -> new NoSuchElementException("Channel with id " + channelId + " not found")); + if (channel.getType().equals(ChannelType.PRIVATE)) { + throw new IllegalArgumentException("Private channel cannot be updated"); + } + channel.update(newName, newDescription); + return channelRepository.save(channel); } - private User findUserByIdOrThrow(UUID id) { - var foundUser = userRepository.findById(id) - .filter(User::isRegistered) - .orElseThrow(() -> UserException.of(USER_NOT_FOUND)); + @Override + public void delete(UUID channelId) { + Channel channel = channelRepository.findById(channelId) + .orElseThrow(() -> new NoSuchElementException("Channel with id " + channelId + " not found")); + + messageRepository.deleteAllByChannelId(channel.getId()); + readStatusRepository.deleteAllByChannelId(channel.getId()); + + channelRepository.deleteById(channelId); + } - return foundUser; + private ChannelDto toDto(Channel channel) { + Instant lastMessageAt = messageRepository.findAllByChannelId(channel.getId()) + .stream() + .sorted(Comparator.comparing(Message::getCreatedAt).reversed()) + .map(Message::getCreatedAt) + .limit(1) + .findFirst() + .orElse(Instant.MIN); + + List participantIds = new ArrayList<>(); + if (channel.getType().equals(ChannelType.PRIVATE)) { + readStatusRepository.findAllByChannelId(channel.getId()) + .stream() + .map(ReadStatus::getUserId) + .forEach(participantIds::add); + } + + return new ChannelDto( + channel.getId(), + channel.getType(), + channel.getName(), + channel.getDescription(), + participantIds, + lastMessageAt + ); } } diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicDirectMessageService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicDirectMessageService.java deleted file mode 100644 index 526e495f8..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicDirectMessageService.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.sprint.mission.discodeit.service.basic; - -import com.sprint.mission.discodeit.common.error.ErrorCode; -import com.sprint.mission.discodeit.common.error.user.UserException; -import com.sprint.mission.discodeit.entity.message.DirectMessage; -import com.sprint.mission.discodeit.entity.message.dto.DirectMessageInfoResponse; -import com.sprint.mission.discodeit.entity.message.dto.SendDirectMessageRequest; -import com.sprint.mission.discodeit.entity.user.entity.User; -import com.sprint.mission.discodeit.repository.jcf.message.directMessage.DirectMessageRepository; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.service.message.converter.DirectMessageConverter; -import com.sprint.mission.discodeit.service.message.directMessage.DirectMessageService; -import java.util.UUID; - -public class BasicDirectMessageService implements DirectMessageService { - - private final DirectMessageRepository directMessageRepository; - private final UserRepository userRepository; - private final DirectMessageConverter directMessageConverter; - - private BasicDirectMessageService( - DirectMessageRepository directMessageRepository, - UserRepository userRepository, - DirectMessageConverter directMessageConverter - ) { - this.directMessageRepository = directMessageRepository; - this.userRepository = userRepository; - this.directMessageConverter = directMessageConverter; - } - - public static DirectMessageService getInstance( - DirectMessageRepository directMessageRepository, - UserRepository userRepository - ) { - var converter = new DirectMessageConverter(); - return new BasicDirectMessageService(directMessageRepository, userRepository, converter); - } - - @Override - public DirectMessageInfoResponse sendMessage(SendDirectMessageRequest sendDirectMessageRequest) { - - var foundSendUser = findUserByIdOrThrow(sendDirectMessageRequest.sendUserId()); - var foundReceiverUser = findUserByIdOrThrow(sendDirectMessageRequest.receiveUserId()); - - var createdDirectMessage = DirectMessage.ofMessageAndSenderReceiver( - sendDirectMessageRequest.message(), - foundSendUser, - foundReceiverUser - ); - - var savedDirectMessage = directMessageRepository.save(createdDirectMessage); - - createdDirectMessage.sendMessage(); - - return directMessageConverter.toDto(savedDirectMessage); - } - - private User findUserByIdOrThrow(UUID userId) { - var foundUser = userRepository.findById(userId) - .filter(User::isRegistered) - .orElseThrow(() -> UserException.ofNotJoinChannel( - ErrorCode.USER_NOT_FOUND, userId.toString() - )); - - return foundUser; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicMessageService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicMessageService.java new file mode 100644 index 000000000..fe16c8f04 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicMessageService.java @@ -0,0 +1,93 @@ +package com.sprint.mission.discodeit.service.basic; + +import com.sprint.mission.discodeit.dto.request.BinaryContentCreateRequest; +import com.sprint.mission.discodeit.dto.request.MessageCreateRequest; +import com.sprint.mission.discodeit.dto.request.MessageUpdateRequest; +import com.sprint.mission.discodeit.entity.BinaryContent; +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.repository.BinaryContentRepository; +import com.sprint.mission.discodeit.repository.ChannelRepository; +import com.sprint.mission.discodeit.repository.MessageRepository; +import com.sprint.mission.discodeit.repository.UserRepository; +import com.sprint.mission.discodeit.service.MessageService; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class BasicMessageService implements MessageService { + private final MessageRepository messageRepository; + // + private final ChannelRepository channelRepository; + private final UserRepository userRepository; + private final BinaryContentRepository binaryContentRepository; + + @Override + public Message create(MessageCreateRequest messageCreateRequest, List binaryContentCreateRequests) { + UUID channelId = messageCreateRequest.channelId(); + UUID authorId = messageCreateRequest.authorId(); + + if (!channelRepository.existsById(channelId)) { + throw new NoSuchElementException("Channel with id " + channelId + " does not exist"); + } + if (!userRepository.existsById(authorId)) { + throw new NoSuchElementException("Author with id " + authorId + " does not exist"); + } + + List attachmentIds = binaryContentCreateRequests.stream() + .map(attachmentRequest -> { + String fileName = attachmentRequest.fileName(); + String contentType = attachmentRequest.contentType(); + byte[] bytes = attachmentRequest.bytes(); + + BinaryContent binaryContent = new BinaryContent(fileName, (long) bytes.length, contentType, bytes); + BinaryContent createdBinaryContent = binaryContentRepository.save(binaryContent); + return createdBinaryContent.getId(); + }) + .toList(); + + String content = messageCreateRequest.content(); + Message message = new Message( + content, + channelId, + authorId, + attachmentIds + ); + return messageRepository.save(message); + } + + @Override + public Message find(UUID messageId) { + return messageRepository.findById(messageId) + .orElseThrow(() -> new NoSuchElementException("Message with id " + messageId + " not found")); + } + + @Override + public List findAllByChannelId(UUID channelId) { + return messageRepository.findAllByChannelId(channelId).stream() + .toList(); + } + + @Override + public Message update(UUID messageId, MessageUpdateRequest request) { + String newContent = request.newContent(); + Message message = messageRepository.findById(messageId) + .orElseThrow(() -> new NoSuchElementException("Message with id " + messageId + " not found")); + message.update(newContent); + return messageRepository.save(message); + } + + @Override + public void delete(UUID messageId) { + Message message = messageRepository.findById(messageId) + .orElseThrow(() -> new NoSuchElementException("Message with id " + messageId + " not found")); + + message.getAttachmentIds() + .forEach(binaryContentRepository::deleteById); + + messageRepository.deleteById(messageId); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicReadStatusService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicReadStatusService.java new file mode 100644 index 000000000..880c22628 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicReadStatusService.java @@ -0,0 +1,73 @@ +package com.sprint.mission.discodeit.service.basic; + +import com.sprint.mission.discodeit.dto.request.ReadStatusCreateRequest; +import com.sprint.mission.discodeit.dto.request.ReadStatusUpdateRequest; +import com.sprint.mission.discodeit.entity.ReadStatus; +import com.sprint.mission.discodeit.repository.ChannelRepository; +import com.sprint.mission.discodeit.repository.ReadStatusRepository; +import com.sprint.mission.discodeit.repository.UserRepository; +import com.sprint.mission.discodeit.service.ReadStatusService; +import java.time.Instant; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class BasicReadStatusService implements ReadStatusService { + private final ReadStatusRepository readStatusRepository; + private final UserRepository userRepository; + private final ChannelRepository channelRepository; + + @Override + public ReadStatus create(ReadStatusCreateRequest request) { + UUID userId = request.userId(); + UUID channelId = request.channelId(); + + if (!userRepository.existsById(userId)) { + throw new NoSuchElementException("User with id " + userId + " does not exist"); + } + if (!channelRepository.existsById(channelId)) { + throw new NoSuchElementException("Channel with id " + channelId + " does not exist"); + } + if (readStatusRepository.findAllByUserId(userId).stream() + .anyMatch(readStatus -> readStatus.getChannelId().equals(channelId))) { + throw new IllegalArgumentException("ReadStatus with userId " + userId + " and channelId " + channelId + " already exists"); + } + + Instant lastReadAt = request.lastReadAt(); + ReadStatus readStatus = new ReadStatus(userId, channelId, lastReadAt); + return readStatusRepository.save(readStatus); + } + + @Override + public ReadStatus find(UUID readStatusId) { + return readStatusRepository.findById(readStatusId) + .orElseThrow(() -> new NoSuchElementException("ReadStatus with id " + readStatusId + " not found")); + } + + @Override + public List findAllByUserId(UUID userId) { + return readStatusRepository.findAllByUserId(userId).stream() + .toList(); + } + + @Override + public ReadStatus update(UUID readStatusId, ReadStatusUpdateRequest request) { + Instant newLastReadAt = request.newLastReadAt(); + ReadStatus readStatus = readStatusRepository.findById(readStatusId) + .orElseThrow(() -> new NoSuchElementException("ReadStatus with id " + readStatusId + " not found")); + readStatus.update(newLastReadAt); + return readStatusRepository.save(readStatus); + } + + @Override + public void delete(UUID readStatusId) { + if (!readStatusRepository.existsById(readStatusId)) { + throw new NoSuchElementException("ReadStatus with id " + readStatusId + " not found"); + } + readStatusRepository.deleteById(readStatusId); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicUserService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicUserService.java index dccde4d90..06f03b29d 100644 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicUserService.java +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicUserService.java @@ -1,86 +1,138 @@ package com.sprint.mission.discodeit.service.basic; -import static com.sprint.mission.discodeit.common.error.ErrorCode.USER_NOT_FOUND; - -import com.sprint.mission.discodeit.common.error.user.UserException; -import com.sprint.mission.discodeit.entity.user.dto.ExitChannelRequest; -import com.sprint.mission.discodeit.entity.user.dto.FindUserRequest; -import com.sprint.mission.discodeit.entity.user.dto.ModifyUserInfoRequest; -import com.sprint.mission.discodeit.entity.user.dto.RegisterUserRequest; -import com.sprint.mission.discodeit.entity.user.dto.UnregisterUserRequest; -import com.sprint.mission.discodeit.entity.user.dto.UserInfoResponse; -import com.sprint.mission.discodeit.entity.user.entity.User; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.service.user.UserConverter; -import com.sprint.mission.discodeit.service.user.UserService; +import com.sprint.mission.discodeit.dto.data.UserDto; +import com.sprint.mission.discodeit.dto.request.BinaryContentCreateRequest; +import com.sprint.mission.discodeit.dto.request.UserCreateRequest; +import com.sprint.mission.discodeit.dto.request.UserUpdateRequest; +import com.sprint.mission.discodeit.entity.BinaryContent; +import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.entity.UserStatus; +import com.sprint.mission.discodeit.repository.BinaryContentRepository; +import com.sprint.mission.discodeit.repository.UserRepository; +import com.sprint.mission.discodeit.repository.UserStatusRepository; +import com.sprint.mission.discodeit.service.UserService; +import java.time.Instant; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +@RequiredArgsConstructor +@Service public class BasicUserService implements UserService { - private final UserRepository userRepository; - private final UserConverter converter; - - public BasicUserService( - UserRepository userRepository, - UserConverter converter - ) { - this.userRepository = userRepository; - this.converter = converter; - } + // + private final BinaryContentRepository binaryContentRepository; + private final UserStatusRepository userStatusRepository; @Override - public UserInfoResponse register(RegisterUserRequest registerUserRequest) { - var entity = converter.toEntity(registerUserRequest); - var savedEntity = userRepository.save(entity); - - return converter.toDto(savedEntity); + public User create(UserCreateRequest userCreateRequest, Optional optionalProfileCreateRequest) { + String username = userCreateRequest.username(); + String email = userCreateRequest.email(); + + if (userRepository.existsByEmail(email)) { + throw new IllegalArgumentException("User with email " + email + " already exists"); + } + if (userRepository.existsByUsername(username)) { + throw new IllegalArgumentException("User with username " + username + " already exists"); + } + + UUID nullableProfileId = optionalProfileCreateRequest + .map(profileRequest -> { + String fileName = profileRequest.fileName(); + String contentType = profileRequest.contentType(); + byte[] bytes = profileRequest.bytes(); + BinaryContent binaryContent = new BinaryContent(fileName, (long)bytes.length, contentType, bytes); + return binaryContentRepository.save(binaryContent).getId(); + }) + .orElse(null); + String password = userCreateRequest.password(); + + User user = new User(username, email, password, nullableProfileId); + User createdUser = userRepository.save(user); + + Instant now = Instant.now(); + UserStatus userStatus = new UserStatus(createdUser.getId(), now); + userStatusRepository.save(userStatus); + + return createdUser; } @Override - public UserInfoResponse findUserByUsernameOrThrow(FindUserRequest findUserRequest) { - var foundUser = userRepository.findByUsername(findUserRequest.username()) - .filter(User::isRegistered) - .map(converter::toDto) - .orElseThrow(() -> UserException.of(USER_NOT_FOUND)); - - return foundUser; + public UserDto find(UUID userId) { + return userRepository.findById(userId) + .map(this::toDto) + .orElseThrow(() -> new NoSuchElementException("User with id " + userId + " not found")); } @Override - public UserInfoResponse modifyUserInfo(ModifyUserInfoRequest request) { - var foundUser = findByUserIdOrThrow(request.id()); - - foundUser.changeUserName(request.changeUsername()); - userRepository.save(foundUser); - - var response = converter.toDto(foundUser); - return response; + public List findAll() { + return userRepository.findAll() + .stream() + .map(this::toDto) + .toList(); } @Override - public void UnRegisterUser(UnregisterUserRequest request) { - var foundUser = findByUserIdOrThrow(request.id()); - - foundUser.unregister(); - - userRepository.save(foundUser); + public User update(UUID userId, UserUpdateRequest userUpdateRequest, Optional optionalProfileCreateRequest) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new NoSuchElementException("User with id " + userId + " not found")); + + String newUsername = userUpdateRequest.newUsername(); + String newEmail = userUpdateRequest.newEmail(); + if (userRepository.existsByEmail(newEmail)) { + throw new IllegalArgumentException("User with email " + newEmail + " already exists"); + } + if (userRepository.existsByUsername(newUsername)) { + throw new IllegalArgumentException("User with username " + newUsername + " already exists"); + } + + UUID nullableProfileId = optionalProfileCreateRequest + .map(profileRequest -> { + Optional.ofNullable(user.getProfileId()) + .ifPresent(binaryContentRepository::deleteById); + + String fileName = profileRequest.fileName(); + String contentType = profileRequest.contentType(); + byte[] bytes = profileRequest.bytes(); + BinaryContent binaryContent = new BinaryContent(fileName, (long) bytes.length, contentType, bytes); + return binaryContentRepository.save(binaryContent).getId(); + }) + .orElse(null); + + String newPassword = userUpdateRequest.newPassword(); + user.update(newUsername, newEmail, newPassword, nullableProfileId); + + return userRepository.save(user); } @Override - public void exitChannel(ExitChannelRequest request) { - var foundUser = findByUserIdOrThrow(request.userId()); - foundUser.exitParticipatedChannel(request.channelId()); - userRepository.save(foundUser); - } + public void delete(UUID userId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new NoSuchElementException("User with id " + userId + " not found")); + + Optional.ofNullable(user.getProfileId()) + .ifPresent(binaryContentRepository::deleteById); + userStatusRepository.deleteByUserId(userId); - private User findByUserIdOrThrow(UUID id) { - var entity = userRepository.findById(id) - .filter(User::isRegistered) - .orElseThrow(() -> UserException.of(USER_NOT_FOUND)); - return entity; + userRepository.deleteById(userId); } - public static BasicUserService getInstance(UserRepository userRepository) { - return new BasicUserService(userRepository, new UserConverter()); + private UserDto toDto(User user) { + Boolean online = userStatusRepository.findByUserId(user.getId()) + .map(UserStatus::isOnline) + .orElse(null); + + return new UserDto( + user.getId(), + user.getCreatedAt(), + user.getUpdatedAt(), + user.getUsername(), + user.getEmail(), + user.getProfileId(), + online + ); } } diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicUserStatusService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicUserStatusService.java new file mode 100644 index 000000000..ef577423f --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/basic/BasicUserStatusService.java @@ -0,0 +1,79 @@ +package com.sprint.mission.discodeit.service.basic; + +import com.sprint.mission.discodeit.dto.request.UserStatusCreateRequest; +import com.sprint.mission.discodeit.dto.request.UserStatusUpdateRequest; +import com.sprint.mission.discodeit.entity.UserStatus; +import com.sprint.mission.discodeit.repository.UserRepository; +import com.sprint.mission.discodeit.repository.UserStatusRepository; +import com.sprint.mission.discodeit.service.UserStatusService; +import java.time.Instant; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class BasicUserStatusService implements UserStatusService { + private final UserStatusRepository userStatusRepository; + private final UserRepository userRepository; + + @Override + public UserStatus create(UserStatusCreateRequest request) { + UUID userId = request.userId(); + + if (!userRepository.existsById(userId)) { + throw new NoSuchElementException("User with id " + userId + " does not exist"); + } + if (userStatusRepository.findByUserId(userId).isPresent()) { + throw new IllegalArgumentException("UserStatus with id " + userId + " already exists"); + } + + Instant lastActiveAt = request.lastActiveAt(); + UserStatus userStatus = new UserStatus(userId, lastActiveAt); + return userStatusRepository.save(userStatus); + } + + @Override + public UserStatus find(UUID userStatusId) { + return userStatusRepository.findById(userStatusId) + .orElseThrow(() -> new NoSuchElementException("UserStatus with id " + userStatusId + " not found")); + } + + @Override + public List findAll() { + return userStatusRepository.findAll().stream() + .toList(); + } + + @Override + public UserStatus update(UUID userStatusId, UserStatusUpdateRequest request) { + Instant newLastActiveAt = request.newLastActiveAt(); + + UserStatus userStatus = userStatusRepository.findById(userStatusId) + .orElseThrow(() -> new NoSuchElementException("UserStatus with id " + userStatusId + " not found")); + userStatus.update(newLastActiveAt); + + return userStatusRepository.save(userStatus); + } + + @Override + public UserStatus updateByUserId(UUID userId, UserStatusUpdateRequest request) { + Instant newLastActiveAt = request.newLastActiveAt(); + + UserStatus userStatus = userStatusRepository.findByUserId(userId) + .orElseThrow(() -> new NoSuchElementException("UserStatus with userId " + userId + " not found")); + userStatus.update(newLastActiveAt); + + return userStatusRepository.save(userStatus); + } + + @Override + public void delete(UUID userStatusId) { + if (!userStatusRepository.existsById(userStatusId)) { + throw new NoSuchElementException("UserStatus with id " + userStatusId + " not found"); + } + userStatusRepository.deleteById(userStatusId); + } +} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/channel/ChannelConverter.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/channel/ChannelConverter.java deleted file mode 100644 index e068eab5d..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/channel/ChannelConverter.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.sprint.mission.discodeit.service.channel; - -import com.sprint.mission.discodeit.entity.channel.Channel; -import com.sprint.mission.discodeit.entity.channel.dto.ChannelResponse; -import com.sprint.mission.discodeit.entity.channel.dto.ChannelResponse.Builder; - -public class ChannelConverter { - - public ChannelResponse toDto(Channel channel) { - var channelResponse = new Builder() - .channelId(channel.getId()) - .channelName(channel.getChannelName()) - .creator(channel.getCreatorName()) - .status(channel.getStatus().getDescription()) - .build(); - - return channelResponse; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/channel/ChannelService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/channel/ChannelService.java deleted file mode 100644 index 5a79aa1c6..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/channel/ChannelService.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.sprint.mission.discodeit.service.channel; - -import com.sprint.mission.discodeit.entity.channel.dto.ChangeChannelNameRequest; -import com.sprint.mission.discodeit.entity.channel.dto.ChannelResponse; -import com.sprint.mission.discodeit.entity.channel.dto.CreateNewChannelRequest; -import com.sprint.mission.discodeit.entity.channel.dto.DeleteChannelRequest; - -public interface ChannelService { - ChannelResponse createChannelOrThrow(CreateNewChannelRequest request); - - void changeChannelNameOrThrow(ChangeChannelNameRequest request); - - void deleteChannelByChannelIdOrThrow(DeleteChannelRequest request); -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFChannelMessageService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFChannelMessageService.java deleted file mode 100644 index 8aa20804d..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFChannelMessageService.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.sprint.mission.discodeit.service.jcf; - -import com.sprint.mission.discodeit.common.error.ErrorCode; -import com.sprint.mission.discodeit.common.error.channel.ChannelException; -import com.sprint.mission.discodeit.common.error.user.UserException; -import com.sprint.mission.discodeit.repository.jcf.channel.ChannelRepository; -import com.sprint.mission.discodeit.repository.jcf.message.ChannelMessage.ChannelMessageRepository; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.entity.channel.Channel; -import com.sprint.mission.discodeit.entity.message.ChannelMessage; -import com.sprint.mission.discodeit.entity.message.dto.ChannelMessageInfoResponse; -import com.sprint.mission.discodeit.entity.message.dto.SendChannelMessageRequest; -import com.sprint.mission.discodeit.entity.user.entity.User; -import com.sprint.mission.discodeit.service.message.channelMessage.ChannelMessageService; -import com.sprint.mission.discodeit.service.message.converter.ChannelMessageConverter; -import java.util.UUID; - -public class JCFChannelMessageService implements ChannelMessageService { - - private final UserRepository userRepository; - private final ChannelRepository channelRepository; - private final ChannelMessageRepository channelMessageRepository; - private final ChannelMessageConverter converter; - - private JCFChannelMessageService( - UserRepository userRepository, - ChannelRepository channelRepository, - ChannelMessageRepository channelMessageRepository, - ChannelMessageConverter converter - ) { - this.userRepository = userRepository; - this.channelRepository = channelRepository; - this.channelMessageRepository = channelMessageRepository; - this.converter = converter; - } - - public static ChannelMessageService getInstance( - UserRepository userRepository, - ChannelRepository channelRepository, - ChannelMessageRepository channelMessageRepository - ) { - var converter = new ChannelMessageConverter(); - return new JCFChannelMessageService(userRepository, channelRepository, channelMessageRepository, converter); - } - - @Override - public ChannelMessageInfoResponse sendMessage(SendChannelMessageRequest sendChannelMessageRequest) { - // 유저 찾기 - var foundUser = findUserByIdOrThrow(sendChannelMessageRequest.sendUserId()); - // 채널 찾기 - var foundChannel = findChannelByIdOrThrow(sendChannelMessageRequest.receiveChannelId()); - // 메시지 생성 - var channelMessage = ChannelMessage.ofMessageAndSenderAndReceiverChannel( - sendChannelMessageRequest.message(), - foundUser, - foundChannel - ); - // 메시지 저장 - var savedMessage = channelMessageRepository.save(channelMessage); - // 메시지 전송 - savedMessage.sendMessage(); - // 생성된 메시지 반환 - return converter.toDto(savedMessage); - } - - /** - * ==> 코드리뷰 부탁드립니다. 유저 서비스에 다른 서비스에서 이용하기 위한 메서드를 넣는게 바람직한가요? - * ==> 제 생각은, 유저 서비스에 같은 기능으로 호출하는 기능이 필요하다면 추가하지만, 없다면 안넣는게 낫다고 생각함. 넣는다면 userRepository - * 그런데, 유저 서비스에서 id로만 찾는 유저를 찾는 기능이 있는가? 구현한 내용은 유저 서비스 레이어 안에서만 private 구현 - * 코드 중복이 너무 많이 발생함, 이를 해결하기 위해 userService, userRepository 둘 중 하나에 메서드를 만드는 방법 중 어디가 좋을까요? - * - * ==> 다른 서비스 레이어를 의존하도록 해서 호출해도 괜찮을까요 ? - */ - private User findUserByIdOrThrow(UUID userId) { - var foundUser = userRepository.findById(userId) - .filter(User::isRegistered) - .orElseThrow(() -> UserException.ofNotJoinChannel( - ErrorCode.USER_NOT_FOUND, userId.toString() - )); - - return foundUser; - } - - - private Channel findChannelByIdOrThrow(UUID channelId) { - var foundChannel = channelRepository.findById(channelId) - .orElseThrow(() -> ChannelException.ofNotFound( - ErrorCode.CHANNEL_NOT_FOUND, - channelId - )); - return foundChannel; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFChannelService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFChannelService.java deleted file mode 100644 index f73f7a03f..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFChannelService.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.sprint.mission.discodeit.service.jcf; - -import static com.sprint.mission.discodeit.common.error.ErrorCode.CHANNEL_NOT_FOUND; -import static com.sprint.mission.discodeit.common.error.ErrorCode.USER_NOT_FOUND; - -import com.sprint.mission.discodeit.common.error.channel.ChannelException; -import com.sprint.mission.discodeit.common.error.user.UserException; -import com.sprint.mission.discodeit.repository.jcf.channel.ChannelRepository; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.entity.channel.dto.ChangeChannelNameRequest; -import com.sprint.mission.discodeit.entity.channel.dto.ChannelResponse; -import com.sprint.mission.discodeit.entity.channel.dto.CreateNewChannelRequest; -import com.sprint.mission.discodeit.entity.channel.dto.DeleteChannelRequest; -import com.sprint.mission.discodeit.entity.user.entity.User; -import com.sprint.mission.discodeit.service.channel.ChannelConverter; -import com.sprint.mission.discodeit.service.channel.ChannelService; -import java.util.UUID; - -public class JCFChannelService implements ChannelService { - - private final ChannelRepository channelRepository; - private final UserRepository userRepository; - private final ChannelConverter channelConverter; - - private JCFChannelService( - ChannelRepository channelRepository, - UserRepository userRepository, - ChannelConverter channelConverter - ) { - this.channelRepository = channelRepository; - this.userRepository = userRepository; - this.channelConverter = channelConverter; - } - - public static ChannelService getInstance(UserRepository userRepository, ChannelRepository channelRepository) { - return new JCFChannelService(channelRepository, userRepository, new ChannelConverter()); - } - - @Override - public ChannelResponse createChannelOrThrow(CreateNewChannelRequest request) { - /** - * ==> 코드리뷰 : 메서드 내부에 다른 메서드를 호출하면서 throw가 발생가능하다는 것을 코드 블록의 메서드의 이름에 추가해야할까요? - * createChannel VS createChannelOrThrow - */ - var findUser = findUserByIdOrThrow(request.userId()); - - var createdChannel = findUser.openNewChannel(request.channelName()); - - channelRepository.save(createdChannel); - userRepository.save(findUser); - - return channelConverter.toDto(createdChannel); - } - - @Override - public void changeChannelNameOrThrow(ChangeChannelNameRequest request) { - var foundUser = findUserByIdOrThrow(request.userId()); - - var changedChannel = foundUser.changeChannelName(request.channelId(), request.newChannelName()); - - channelRepository.save(changedChannel); - userRepository.save(foundUser); - } - - @Override - public void deleteChannelByChannelIdOrThrow(DeleteChannelRequest request) { - var foundChannel = channelRepository.findById(request.channelId()) - .orElseThrow( - () -> ChannelException.ofNotFound( - CHANNEL_NOT_FOUND, - request.channelId()) - ); - - var foundUser = findUserByIdOrThrow(request.userId()); - foundChannel.deleteChannel(foundUser); - - channelRepository.save(foundChannel); - } - - private User findUserByIdOrThrow(UUID id) { - var foundUser = userRepository.findById(id) - .filter(User::isRegistered) - .orElseThrow(() -> UserException.of(USER_NOT_FOUND)); - - return foundUser; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFDirectMessageService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFDirectMessageService.java deleted file mode 100644 index 8ba337947..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFDirectMessageService.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.sprint.mission.discodeit.service.jcf; - -import com.sprint.mission.discodeit.common.error.ErrorCode; -import com.sprint.mission.discodeit.common.error.user.UserException; -import com.sprint.mission.discodeit.repository.jcf.message.directMessage.DirectMessageRepository; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.entity.message.DirectMessage; -import com.sprint.mission.discodeit.entity.message.dto.DirectMessageInfoResponse; -import com.sprint.mission.discodeit.entity.message.dto.SendDirectMessageRequest; -import com.sprint.mission.discodeit.entity.user.entity.User; -import com.sprint.mission.discodeit.service.message.converter.DirectMessageConverter; -import com.sprint.mission.discodeit.service.message.directMessage.DirectMessageService; -import java.util.UUID; - -public class JCFDirectMessageService implements DirectMessageService { - - private final DirectMessageRepository directMessageRepository; - private final UserRepository userRepository; - private final DirectMessageConverter directMessageConverter; - - private JCFDirectMessageService( - DirectMessageRepository directMessageRepository, - UserRepository userRepository, - DirectMessageConverter directMessageConverter - ) { - this.directMessageRepository = directMessageRepository; - this.userRepository = userRepository; - this.directMessageConverter = directMessageConverter; - } - - public static DirectMessageService getInstance( - DirectMessageRepository directMessageRepository, - UserRepository userRepository - ) { - var converter = new DirectMessageConverter(); - return new JCFDirectMessageService(directMessageRepository, userRepository, converter); - } - - @Override - public DirectMessageInfoResponse sendMessage(SendDirectMessageRequest sendDirectMessageRequest) { - - var foundSendUser = findUserByIdOrThrow(sendDirectMessageRequest.sendUserId()); - var foundReceiverUser = findUserByIdOrThrow(sendDirectMessageRequest.receiveUserId()); - - var createdDirectMessage = DirectMessage.ofMessageAndSenderReceiver( - sendDirectMessageRequest.message(), - foundSendUser, - foundReceiverUser - ); - - var savedDirectMessage = directMessageRepository.save(createdDirectMessage); - - createdDirectMessage.sendMessage(); - - return directMessageConverter.toDto(savedDirectMessage); - } - - private User findUserByIdOrThrow(UUID userId) { - var foundUser = userRepository.findById(userId) - .filter(User::isRegistered) - .orElseThrow(() -> UserException.ofNotJoinChannel( - ErrorCode.USER_NOT_FOUND, userId.toString() - )); - - return foundUser; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFUserService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFUserService.java deleted file mode 100644 index 79c2973d4..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFUserService.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.sprint.mission.discodeit.service.jcf; - -import static com.sprint.mission.discodeit.common.error.ErrorCode.USER_NOT_FOUND; - -import com.sprint.mission.discodeit.common.error.user.UserException; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.entity.user.dto.ExitChannelRequest; -import com.sprint.mission.discodeit.entity.user.entity.User; -import com.sprint.mission.discodeit.entity.user.dto.FindUserRequest; -import com.sprint.mission.discodeit.entity.user.dto.ModifyUserInfoRequest; -import com.sprint.mission.discodeit.entity.user.dto.RegisterUserRequest; -import com.sprint.mission.discodeit.entity.user.dto.UnregisterUserRequest; -import com.sprint.mission.discodeit.entity.user.dto.UserInfoResponse; -import com.sprint.mission.discodeit.service.user.UserConverter; -import com.sprint.mission.discodeit.service.user.UserService; -import java.util.UUID; - -public class JCFUserService implements UserService { - - private final UserRepository userRepository; - private final UserConverter converter; - - public JCFUserService( - UserRepository userRepository, - UserConverter converter - ) { - this.userRepository = userRepository; - this.converter = converter; - } - - @Override - public UserInfoResponse register(RegisterUserRequest registerUserRequest) { - var entity = converter.toEntity(registerUserRequest); - var savedEntity = userRepository.save(entity); - - return converter.toDto(savedEntity); - } - - @Override - public UserInfoResponse findUserByUsernameOrThrow(FindUserRequest findUserRequest) { - var foundUser = userRepository.findByUsername(findUserRequest.username()) - .filter(User::isRegistered) - .map(converter::toDto) - .orElseThrow(() -> UserException.of(USER_NOT_FOUND)); - - return foundUser; - } - - @Override - public UserInfoResponse modifyUserInfo(ModifyUserInfoRequest request) { - var foundUser = findByUserIdOrThrow(request.id()); - - foundUser.changeUserName(request.changeUsername()); - userRepository.save(foundUser); - - var response = converter.toDto(foundUser); - return response; - } - - @Override - public void UnRegisterUser(UnregisterUserRequest request) { - var foundUser = findByUserIdOrThrow(request.id()); - - foundUser.unregister(); - - userRepository.save(foundUser); - } - - @Override - public void exitChannel(ExitChannelRequest request) { - var foundUser = findByUserIdOrThrow(request.userId()); - foundUser.exitParticipatedChannel(request.channelId()); - userRepository.save(foundUser); - } - - private User findByUserIdOrThrow(UUID id) { - var entity = userRepository.findById(id) - .filter(User::isRegistered) - .orElseThrow(() -> UserException.of(USER_NOT_FOUND)); - return entity; - } - - public static JCFUserService getInstance(UserRepository userRepository) { - return new JCFUserService(userRepository, new UserConverter()); - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/message/channelMessage/ChannelMessageService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/message/channelMessage/ChannelMessageService.java deleted file mode 100644 index 4578cc6ba..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/message/channelMessage/ChannelMessageService.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.sprint.mission.discodeit.service.message.channelMessage; - -import com.sprint.mission.discodeit.entity.message.dto.ChannelMessageInfoResponse; -import com.sprint.mission.discodeit.entity.message.dto.SendChannelMessageRequest; - -public interface ChannelMessageService { - - ChannelMessageInfoResponse sendMessage(SendChannelMessageRequest sendChannelMessageRequest); -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/message/converter/ChannelMessageConverter.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/message/converter/ChannelMessageConverter.java deleted file mode 100644 index 2deed9290..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/message/converter/ChannelMessageConverter.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.sprint.mission.discodeit.service.message.converter; - -import com.sprint.mission.discodeit.entity.message.ChannelMessage; -import com.sprint.mission.discodeit.entity.message.dto.ChannelMessageInfoResponse; -import com.sprint.mission.discodeit.entity.message.dto.ChannelMessageInfoResponse.Builder; - -public class ChannelMessageConverter { - - public ChannelMessageInfoResponse toDto(ChannelMessage message) { - var response = new ChannelMessageInfoResponse.Builder() - .messageId(message.getId()) - .sendUserId(message.getMessageSender().getId()) - .receiveChannelId(message.getReceiverChannel().getId()) - .message(message.getMessage()) - .build(); - - return response; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/message/converter/DirectMessageConverter.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/message/converter/DirectMessageConverter.java deleted file mode 100644 index dda0676a5..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/message/converter/DirectMessageConverter.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.sprint.mission.discodeit.service.message.converter; - -import com.sprint.mission.discodeit.entity.message.DirectMessage; -import com.sprint.mission.discodeit.entity.message.dto.DirectMessageInfoResponse; -import com.sprint.mission.discodeit.entity.message.dto.DirectMessageInfoResponse.Builder; - -public class DirectMessageConverter { - - public DirectMessageInfoResponse toDto(DirectMessage directMessage) { - var response = new Builder() - .messageId(directMessage.getId()) - .sender(directMessage.getMessageSender().getId()) - .receiver(directMessage.getMessageReceiver().getId()) - .message(directMessage.getMessage()) - .build(); - - return response; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/message/directMessage/DirectMessageService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/message/directMessage/DirectMessageService.java deleted file mode 100644 index 1eee17b5a..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/message/directMessage/DirectMessageService.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.sprint.mission.discodeit.service.message.directMessage; - -import com.sprint.mission.discodeit.entity.message.dto.DirectMessageInfoResponse; -import com.sprint.mission.discodeit.entity.message.dto.SendDirectMessageRequest; - -public interface DirectMessageService { - - DirectMessageInfoResponse sendMessage(SendDirectMessageRequest sendDirectMessageRequest); -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/user/UserConverter.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/user/UserConverter.java deleted file mode 100644 index 47977d732..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/user/UserConverter.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.sprint.mission.discodeit.service.user; - -import com.sprint.mission.discodeit.entity.user.dto.RegisterUserRequest; -import com.sprint.mission.discodeit.entity.user.dto.UserInfoResponse; -import com.sprint.mission.discodeit.entity.user.entity.User; -import java.util.Objects; - -public class UserConverter { - private static UserConverter INSTANCE; - - public UserConverter() {} - - public static UserConverter getInstance() { - if (INSTANCE == null) { - INSTANCE = new UserConverter(); - } - return Objects.requireNonNull(INSTANCE); - } - - public User toEntity(RegisterUserRequest request) { - var createdUser = User.createFrom(request.name()); - return createdUser; - } - - public UserInfoResponse toDto(User user) { - var responseDto = new UserInfoResponse( - user.getId(), - user.getName(), - user.getStatus() - ); - return responseDto; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/user/UserService.java b/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/user/UserService.java deleted file mode 100644 index cea20b893..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/main/java/com/sprint/mission/discodeit/service/user/UserService.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.sprint.mission.discodeit.service.user; - -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.entity.user.dto.ExitChannelRequest; -import com.sprint.mission.discodeit.entity.user.dto.FindUserRequest; -import com.sprint.mission.discodeit.entity.user.dto.ModifyUserInfoRequest; -import com.sprint.mission.discodeit.entity.user.dto.RegisterUserRequest; -import com.sprint.mission.discodeit.entity.user.dto.UnregisterUserRequest; -import com.sprint.mission.discodeit.entity.user.dto.UserInfoResponse; -import com.sprint.mission.discodeit.service.jcf.JCFUserService; - -public interface UserService { - - UserInfoResponse register(RegisterUserRequest registerUserRequest); - - UserInfoResponse findUserByUsernameOrThrow(FindUserRequest findUserRequest); - - UserInfoResponse modifyUserInfo(ModifyUserInfoRequest request); - - void UnRegisterUser(UnregisterUserRequest request); - - void exitChannel(ExitChannelRequest request); - - public static UserService getJCFUserService(UserRepository userRepository) { - return JCFUserService.getInstance(userRepository); - } - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/application.yaml b/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/application.yaml new file mode 100644 index 000000000..d7204418d --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/application.yaml @@ -0,0 +1,14 @@ +spring: + application: + name: discodeit + mvc: + view: + suffix: .html + +discodeit: + repository: + type: file # jcf | file + file-directory: .discodeit + + + diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/static/default-avatar.png b/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/static/default-avatar.png new file mode 100644 index 000000000..a9b3c6d37 Binary files /dev/null and b/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/static/default-avatar.png differ diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/static/script.js b/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/static/script.js new file mode 100644 index 000000000..d8d6e7449 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/static/script.js @@ -0,0 +1,67 @@ +// API endpoints +const API_BASE_URL = '/api'; +const ENDPOINTS = { + USERS: `${API_BASE_URL}/user/findAll`, + BINARY_CONTENT: `${API_BASE_URL}/binary-content` +}; + +// Initialize the application +document.addEventListener('DOMContentLoaded', () => { + fetchAndRenderUsers(); +}); + +// Fetch users from the API +async function fetchAndRenderUsers() { + try { + const response = await fetch(ENDPOINTS.USERS); + if (!response.ok) throw new Error('Failed to fetch users'); + const users = await response.json(); + renderUserList(users); + } catch (error) { + console.error('Error fetching users:', error); + } +} + +// Fetch user profile image +async function fetchUserProfile(profileId) { + try { + const response = await fetch(`${ENDPOINTS.BINARY_CONTENT}/${profileId}`); + if (!response.ok) throw new Error('Failed to fetch profile'); + const profile = await response.json(); + + // Convert base64 encoded bytes to data URL + return `data:${profile.contentType};base64,${profile.bytes}`; + } catch (error) { + console.error('Error fetching profile:', error); + return '/default-avatar.png'; // Fallback to default avatar + } +} + +// Render user list +async function renderUserList(users) { + const userListElement = document.getElementById('userList'); + userListElement.innerHTML = ''; // Clear existing content + + for (const user of users) { + const userElement = document.createElement('div'); + userElement.className = 'user-item'; + + // Get profile image URL + const profileUrl = user.profileId ? + await fetchUserProfile(user.profileId) : + '/default-avatar.png'; + + userElement.innerHTML = ` + ${user.username} + +
+ ${user.online ? '온라인' : '오프라인'} +
+ `; + + userListElement.appendChild(userElement); + } +} \ No newline at end of file diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/static/styles.css b/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/static/styles.css new file mode 100644 index 000000000..b45f4e704 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/static/styles.css @@ -0,0 +1,80 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: Arial, sans-serif; + background-color: #f5f5f5; +} + +.container { + max-width: 800px; + margin: 0 auto; + padding: 20px; +} + +h1 { + text-align: center; + margin-bottom: 30px; + color: #333; +} + +.user-list { + background-color: white; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.user-item { + display: flex; + align-items: center; + padding: 20px; + border-bottom: 1px solid #eee; +} + +.user-item:last-child { + border-bottom: none; +} + +.user-avatar { + width: 60px; + height: 60px; + border-radius: 50%; + margin-right: 20px; + object-fit: cover; +} + +.user-info { + flex-grow: 1; +} + +.user-name { + font-size: 18px; + font-weight: bold; + color: #333; + margin-bottom: 5px; +} + +.user-email { + font-size: 14px; + color: #666; +} + +.status-badge { + padding: 6px 12px; + border-radius: 20px; + font-size: 14px; + font-weight: bold; +} + +.online { + background-color: #4CAF50; + color: white; +} + +.offline { + background-color: #9e9e9e; + color: white; +} \ No newline at end of file diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/static/user-list.html b/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/static/user-list.html new file mode 100644 index 000000000..f3acfdb59 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/src/main/resources/static/user-list.html @@ -0,0 +1,18 @@ + + + + + + 사용자 목록 + + + +
+

사용자 목록

+
+ +
+
+ + + \ No newline at end of file diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/UUIDTest.java b/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/UUIDTest.java deleted file mode 100644 index 4bd085631..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/UUIDTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.sprint.mission.discodeit; - -import static org.assertj.core.api.Assertions.*; - -import java.util.UUID; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.Test; - -public class UUIDTest { - - @Test - void uuidTest() { - var uuid = UUID.randomUUID(); - var targetUUID = UUID.fromString(uuid.toString()); - - var retsult = uuid.equals(targetUUID); - - assertThat(retsult).isTrue(); - } - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/channel/ChannelTest.java b/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/channel/ChannelTest.java deleted file mode 100644 index a04ef15a8..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/channel/ChannelTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.sprint.mission.discodeit.entity.channel; - -import static com.sprint.mission.discodeit.entity.common.Status.MODIFIED; -import static com.sprint.mission.discodeit.entity.common.Status.UNREGISTERED; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertAll; - -import com.sprint.mission.discodeit.entity.user.entity.User; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -@DisplayName("채널 도메인") -class ChannelTest { - private static final String CHANNEL_NAME = "스프린트_백엔드_1기"; - private static final String USER_NAME = "SB_1기_백재우"; - private static final User USER = User.createFrom(USER_NAME); - private Channel channel; - - @Test - @DisplayName("새로운 채널 생성") - void createChannelThenSuccess() { - assertThat(Channel.createOfChannelNameAndUser(CHANNEL_NAME, USER)) - .isNotNull(); - } - - @Nested - @DisplayName("메서드 검사") - class whenUseMethodTest { - - @BeforeEach - void setUp() { - channel = Channel.createOfChannelNameAndUser(CHANNEL_NAME, USER); - } - - @Test - @DisplayName("변경하려는 새로운 이름으로 채널이름 변경하면 채널의 이름과 상태가 변경") - void givenChangeChannelNameWhenChangeNameThenUpdateStatusAndChannelName() { - // given - var newChannelName = "SB_999기_백재우"; - // then - channel.changeName(newChannelName, USER); - // when - assertAll( - () -> { - assertThat(channel.getChannelName()).isNotEqualTo(CHANNEL_NAME); - assertThat(channel.getStatus()).isEqualTo(MODIFIED); - } - ); - } - - @Test - @DisplayName("채널을 삭제 시 상태가 변경") - void givenChannelWhenDeleteChannelThenStatusUpdate() { - // given - // when - channel.deleteChannel(USER); - // then - assertThat(channel.getStatus()).isEqualTo(UNREGISTERED); - } - - @Test - @DisplayName("매개변수로 들어온 이름과 채널 객체의 이름이 같을 경우, 상태가 해지 상태가 아닐 시 True 반환") - void givenSameChannelNameWhenIsEqualFromNameAndNotUnregisteredThenTrue() { - // given - - // when - var validResult = channel.isRegisteredAndNameEqual(CHANNEL_NAME); - // then - assertThat(validResult).isTrue(); - } - - @Test - @DisplayName("매개변수로 들어온 이름과 채널 객체의 이름이 다를 경우, 상태가 해지 상태가 아닐 시 False 반환") - void givenDifferentChannelNameWhenIsEqualFromNameAndNotUnregisteredThenFalse() { - // given - var differentChannelName = "스프린트_백엔드_100기"; - // when - var validResult = channel.isRegisteredAndNameEqual(differentChannelName); - // then - assertThat(validResult).isFalse(); - } - - @Test - @DisplayName("찾으려는 채널이름과 비교하려는 채널 객체의 이름이 같고 해지상태가 아닐 경우 true 반환") - void givenSameNameWhenIsStatusNotUnregisteredAndEqualsToThenTrue() { - // given - var findChannelNameRequest = CHANNEL_NAME; - // when - var isEquals = channel.isRegisteredAndNameEqual(findChannelNameRequest); - // then - assertThat(isEquals).isTrue(); - } - - @Test - @DisplayName("찾으려는 채널이름과 비교하려는 채널 객체 이름이 같고 해지상태일 경우 false 반환") - void givenSameNameAndUnregisteredWhenIsStatusNotUnregisteredThenFalse() { - // given - var findChannelNameRequest = CHANNEL_NAME; - channel.updateUnregistered(); - // when - var isEquals = channel.isRegisteredAndNameEqual(findChannelNameRequest); - // then - assertThat(isEquals).isFalse(); - } - } -} \ No newline at end of file diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/common/AbstractUUIDTest.java b/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/common/AbstractUUIDTest.java deleted file mode 100644 index 70746b7c3..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/common/AbstractUUIDTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.sprint.mission.discodeit.entity.common; - -import static com.sprint.mission.discodeit.entity.common.Status.MODIFIED; -import static com.sprint.mission.discodeit.entity.common.Status.REGISTERED; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; - -import com.sprint.mission.discodeit.testdummy.TestUUIDEntity; -import java.lang.reflect.Field; -import java.util.UUID; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -public class AbstractUUIDTest { - - private AbstractUUIDEntity entity; - - - @BeforeEach - void init() { - entity = new TestUUIDEntity(); - } - - @Test - @DisplayName("공통 엔티티 추상 클래스 생성 시 id, createdAt, status 필드 초기화 시 Not Null test") - void createAbstractUUIDThenInitializeFieldIdAndCreatedAtAndStatusIsNotNullTest() { - assertAll( - () -> assertThat(entity.getId()).as("Id should not be null").isNotNull(), - () -> assertThat(entity.getCreateAt()).as("createAt should not be null").isNotNull(), - () -> assertThat(entity.getStatus()).isEqualTo(REGISTERED), - () -> assertThat(entity.getUpdateAt()).as("At Initialized updateAt time is must be Empty").isEmpty() - ); - } - - @Test - @DisplayName("엔티티 내 데이터가 수정 시 updateAt and status 필드 수정 여부 테스트") - void givenWhenSomeDateModifyThenFieldUpdateAtAndStatusIsChangedTest() { - // given - assertThat(entity.getUpdateAt()).isEmpty(); - // when - entity.updateModified(); - //then - assertAll( - () -> assertThat(entity.getUpdateAt()).as("invoke update() then updateAt must be present").isPresent(), - () -> assertThat(entity.getStatus()).isEqualTo(MODIFIED) - ); - } - - @Test - @DisplayName("동일한 UUID를 가진 객체간의 동등성 비교를 할 경우 True를 반환하는지 테스트") - void givenCreateAbstractEntityAndEqualEntityWhenIsEqualsThenReturnTrueTest() throws Exception { - // given - AbstractUUIDEntity entity1 = new TestUUIDEntity(); - AbstractUUIDEntity entity2 = new TestUUIDEntity(); - - UUID sameUUID = UUID.randomUUID(); - - setFinalField(entity1, "id", sameUUID); - setFinalField(entity2, "id", sameUUID); - - // then - assertEquals(entity1, entity2, "Entities with the same UUID should be equal"); - - AbstractUUIDEntity entity3 = new TestUUIDEntity(); - assertNotEquals(entity1, entity3, "Entities with different UUIDs should not be equal"); - } - - // 리플렉션. 이 부분 코드 리뷰 XXX - private void setFinalField(Object object, String fieldName, Object value) throws Exception { - Field field = object.getClass().getSuperclass().getDeclaredField(fieldName); - field.setAccessible(true); - field.set(object, value); - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/user/UserNameTest.java b/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/user/UserNameTest.java deleted file mode 100644 index 3880736b3..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/user/UserNameTest.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.sprint.mission.discodeit.entity.user; - -import static com.sprint.mission.discodeit.entity.user.entity.UserName.NAME_MAX_LENGTH; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchNullPointerException; -import static org.assertj.core.api.BDDAssertions.then; - -import com.sprint.mission.discodeit.entity.user.entity.UserName; -import jakarta.validation.ConstraintViolation; -import jakarta.validation.Validation; -import jakarta.validation.Validator; -import java.util.Set; -import java.util.stream.Stream; -import net.bytebuddy.asm.Advice.Thrown; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.NullAndEmptySource; -import org.junit.jupiter.params.provider.NullSource; - -class UserNameTest { - - private UserName userName; - - private Validator validator; - - @BeforeEach - void setUp() { - validator = Validation.buildDefaultValidatorFactory().getValidator(); - } - - static Stream stringProvider() { - return Stream.of( - ".".repeat(NAME_MAX_LENGTH + 1), - "T", - "TT" - ); - } - - @ParameterizedTest(name = "[test {index}] ==> given name : {arguments}") - @NullSource - @DisplayName("요구되는 유저의 이름이 비어있는 value 제공 시 에러 발생 테스트") - void givenUserNameLengthLessThanRequiredLengthWhenCreateUserThenThrowException(String name) { - // given - -// Set> violations = validator.validate(userName); - - // when - Throwable thrown = catchNullPointerException(() -> userName = UserName.createFrom(name)); - // then - assertThat(thrown).isInstanceOf(NullPointerException.class); -// assertThat(violations.size()).isEqualTo(1); - } - - @ParameterizedTest(name = "given name : {arguments}") - @MethodSource("stringProvider") - @DisplayName("유저의 이름의 제한을 넘어가는 문자열로 생성 시 에러 발생 테스트") - void givenMoreThanInvalidLengthNameWhenCreateUserNameThenThrowException(String overLengthName) { - // given - userName = UserName.createFrom(overLengthName); - Set> violations = validator.validate(userName); - // then - assertThat(violations.size()).isEqualTo(1); - } - - - @Nested - @DisplayName("초기화 후 기능 테스트") - class whenSetup { - - private static final String USER_NAME = "SB_1기_백재우"; - - @BeforeEach - void setup() { - userName = UserName.createFrom(USER_NAME); - } - - @Test - @DisplayName("특정 문자열을 통해 UserName 객체 생성 후 동일한 문자열을 리턴 테스트") - void givenNameWhenCreateUserNameThenReturnUserName() { - then(userName.getName()).isEqualTo(USER_NAME); - } - - @Test - @DisplayName("새로운 이름으로 사용자 이름을 변경 시 새로운 UserName 객체 반환") - void givenNewUserNameWhenChangeUserNameThenReturnNewUserName() { - // given - String newName = "SB_2기_백재우"; - // when - var newUserName = userName.changeName(newName); - // then - then(newUserName).isNotEqualTo(userName); - } - } -} \ No newline at end of file diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/user/UserTest.java b/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/user/UserTest.java deleted file mode 100644 index 53f017c7f..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/user/UserTest.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.sprint.mission.discodeit.entity.user; - -import static com.sprint.mission.discodeit.entity.common.Status.UNREGISTERED; -import static org.assertj.core.api.Assertions.assertThat; - -import com.sprint.mission.discodeit.entity.channel.Channel; -import com.sprint.mission.discodeit.entity.user.entity.User; -import java.util.UUID; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -@DisplayName("User Test") -class UserTest { - private static final String USER_NAME = "test"; - private static final String CHANNEL_NAME = "코드잇-스프린트_1기"; - private User user; - - @Test - void createUserTest() { - // given - String userName = "test1"; - - assertThat(User.createFrom(userName)).isNotNull(); - } - - @Nested - @DisplayName("유저 생성 수정 삭제") - class InitializeNew { - @BeforeEach - void setUp() { - user = User.createFrom(USER_NAME); - } - - @Test - @DisplayName("유저 객체를 생성한 후 객체의 name value 와 초기화 시 입력 값과 동일 테스트") - void givenUserWhenGetUserNameThenReturnUserName() { - // given - - // when - var userName = user.getName(); - // then - assertThat(userName).isEqualTo(USER_NAME); - } - - // TODO : 유저 이름 수정 성공 테스트 - - // TODO : 유저 이름 수정 실패 테스트 - - @Test - @DisplayName("유저 해지 요청 후 유저의 상태 변경") - void givenUnregisterRequestWhenUnregisterThenStatusChange() { - // given - // when - user.unregister(); - // then - assertThat(user.getStatus()).isEqualTo(UNREGISTERED); - } - } - - @Nested - @DisplayName("유저 채널") - class aboutChannel { - private Channel participatedChannel; - - @BeforeEach - void setup() { - user = User.createFrom(USER_NAME); - participatedChannel = user.openNewChannel("new Channel1"); - } - - @Test - @DisplayName("채널 이름을 유저가 제공하여 새로운 채널을 만들면 생성된 채널 반환") - void givenChannelNameWhenUserCreateChannelThenReturnChannel() { - // given - var createdUser = User.createFrom(USER_NAME); - // when - var channel = createdUser.openNewChannel(CHANNEL_NAME); - // then - Assertions.assertAll( - () -> { - assertThat(channel).isNotNull(); - assertThat(channel.getChannelName()).isEqualTo(CHANNEL_NAME); - } - ); - } - - @Test - @DisplayName("새로운 채널 이름으로 유저가 채널의 이름을 변경 시 변경된 채널 반환") - void givenChangeChannelNameWhenUserChangeChannelNameThenReturnChangedChannel() { - // given - var newChangeChannelName = "NEW CHANNEL NAME"; - var targetChannelId = participatedChannel.getId(); - // when - var changeChannel = user.changeChannelName(targetChannelId, newChangeChannelName); - // then - assertThat(changeChannel.getChannelName()).isEqualTo(newChangeChannelName); - } - - @Test - @DisplayName("유저의 참가 채널 id로 참가한 채널에서 나가면 참가채널 수 감소") - void givenExitChannelIdWhenExitParticipatedChannelThenReturnParticipatedChannelCountDecrease() { - // given - var participatedChannelId = participatedChannel.getId(); - var oldCount = user.countParticipatedChannels(); - // when - user.exitParticipatedChannel(participatedChannelId); - // then - assertThat(user.countParticipatedChannels()).isEqualTo(oldCount - 1); - } - } - -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/user/entity/ParticipatedChannelTest.java b/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/user/entity/ParticipatedChannelTest.java deleted file mode 100644 index d77b46112..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/entity/user/entity/ParticipatedChannelTest.java +++ /dev/null @@ -1,220 +0,0 @@ -package com.sprint.mission.discodeit.entity.user.entity; - -import static com.sprint.mission.discodeit.common.error.ErrorCode.USER_NOT_PARTICIPATED_CHANNEL; -import static com.sprint.mission.discodeit.entity.common.Status.MODIFIED; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.catchThrowable; -import static org.junit.jupiter.api.Assertions.assertAll; - -import com.sprint.mission.discodeit.common.error.channel.ChannelException; -import com.sprint.mission.discodeit.entity.channel.Channel; -import java.util.UUID; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -class ParticipatedChannelTest { - private static final String CHANNEL_NAME = "코드잇-1기-백엔드"; - private ParticipatedChannel channels; - private static final User USER = User.createFrom("SB_1기_백재우"); - - @Test - void givenNewParticipatedChannelWhenCreateThenReturnNewParticipatedChannel() { - // given when - var createdParticipatedChannel = ParticipatedChannel.newDefault(); - // then - assertThat(createdParticipatedChannel).isNotNull(); - } - - @BeforeEach - void setUp() { - channels = ParticipatedChannel.newDefault(); - } - - @Test - void givenChannelNameWhenCreateChannelThenReturnNewChannel() { - // given when - var channel = channels.createChannel(CHANNEL_NAME, USER); - // then - assertAll( - () -> { - assertThat(channel).isNotNull(); - - assertAll( - () -> assertThat(channel.getChannelName()).isEqualTo(CHANNEL_NAME) - ); - } - ); - } - - @Nested - @DisplayName("유저의 참여 채널") - class givenSomeElements { - private static final String addChannelName1 = "스프린트_2기_백엔드"; - private static final String addChannelName2 = "스프린트_3기_백엔드"; - private Channel createdChannel1; - private Channel createdChannel2; - - @BeforeEach - void add() { - createdChannel1 = channels.createChannel(addChannelName1, USER); - createdChannel2 = channels.createChannel(addChannelName2, USER); - } - - @Test - @DisplayName("유저가 참여한 채널에서 Id를 통해 채널 조회") - void givenSomeElementsAddedChannelsWhenFindByIdThenReturnSomeElements() { - // given - var channelId = createdChannel1.getId(); - - // when - var findByIdParticipatedChannel = channels.getUnregisteredChannelById(channelId); - - // then - assertAll( - () -> { - assertThat(findByIdParticipatedChannel).isNotNull(); - - assertAll( - () -> assertThat(findByIdParticipatedChannel.orElseThrow().getId()) - .isEqualTo(channelId) - ); - } - ); - } - - @Test - @DisplayName("유저가 참여한 채널에서 channelName 을 통해 채널 조회") - void givenSomeElementsAddedChannelsWhenFindByNameThenReturnSomeElements() { - // given - var channelName = createdChannel1.getChannelName(); - - // when - var findByIdParticipatedChannel = channels.findByName(channelName); - - // then - assertAll( - () -> { - assertThat(findByIdParticipatedChannel).isNotNull(); - - assertAll( - () -> assertThat(findByIdParticipatedChannel.orElseThrow().getChannelName()) - .isEqualTo(addChannelName1) - ); - } - ); - } - - @Test - @DisplayName("유저가 참여한 채널에 존재하지 않는 channel Id로 채널 조회 시 에러 발생") - void givenNotExistChannelIdWhenFindByIdThenThrowException() { - // given - var notExistedChannelId = UUID.randomUUID(); - - // when - var throwable = catchThrowable(() -> - channels.getUnregisteredChannelById(notExistedChannelId) - ); - - // then - assertThat(throwable).isInstanceOf(ChannelException.class) - .hasMessageContaining(USER_NOT_PARTICIPATED_CHANNEL.getErrorMessage()); - } - - @Test - @DisplayName("유저가 참여한 채널에 존재하는 ChannelName 으로 채널 조회 시 해당 채널 반환") - void givenExistedChannelNameWhenFindByNameThenReturnChannel() { - // given - - // when - var foundChannel = channels.findByName(addChannelName1); - // then - assertThat(foundChannel) - .isNotNull(); - } - - @Test - @DisplayName("유저가 참여한 채널에 존재하지 않는 ChannelName 으로 채널 조회시 에러") - void givenNotExistedChannelNameWhenFindByNameThenThrowException() { - // given - var notExistedChannelName = "SB_999기_백재우"; - - // when - var foundChannel = channels.findByName(notExistedChannelName); - - // then - assertThat(foundChannel.orElse(null)).isNull(); - } - - @Test - @DisplayName("유저가 참여한 채널의 id로 채널이름을 변경 성공") - void givenParticipatedChannelIdAndNewChannelNameWhenChangeChannelNameThenSuccess() { - // given - var channelId = createdChannel1.getId(); - var changeChannelName = createdChannel1.getChannelName(); - - // when - channels.changeChannelNameOrThrow(channelId, "new ChannelName", USER); - - // then - assertAll( - () -> { - assertThat(createdChannel1.getChannelName()).isNotEqualTo(changeChannelName); - assertThat(createdChannel1.getStatus()).isEqualTo(MODIFIED); - } - ); - } - - @Test - @DisplayName("존재하지 않는 채널 id로 유저가 참여한 채널의 id로 채널이름 변경 시 에러") - void givenNotExistedChannelIdWhenChangeChannelNameThenThrowUserException() { - // given - var notExistedChannelId = UUID.randomUUID(); - var changeChannelName = "new ChannelName"; - - // when - var throwable = catchThrowable(() -> channels.changeChannelNameOrThrow(notExistedChannelId, changeChannelName, USER)); - - // then - assertThat(throwable).isInstanceOf(ChannelException.class) - .hasMessageContaining(notExistedChannelId.toString()); - - } - - @Test - @DisplayName("채널을 생성한 사람이 아닌 다른 누군가 채널이름을 변경하려고 할 경우 에러") - void givenNotChannelCreatorWhenChangeChannelNameThenThrowChannelException() { - // given - var notCreatorUser = User.createFrom("is not Creator"); - var changeChannelName = "SB_백엔드_1000기"; - var channelId = createdChannel1.getId(); - - // when - var throwable = catchThrowable(() -> - channels.changeChannelNameOrThrow(channelId, changeChannelName, notCreatorUser) - ); - - // then - assertThat(throwable).isInstanceOf(ChannelException.class) - .hasMessageContaining(notCreatorUser.getName()); - } - - @Test - @DisplayName("채널 id 값으로 유저가 참여한 채널을 삭제하면 유저가 참여한 채널 목록의 개수 감소") - void givenDeleteTargetIdWhenDeleteChannelThenParticipatedChannelIsRemove() { - // given - var oldParticipatedChannelCount = channels.countParticipatedChannels(); - var deleteTargetChannelId = createdChannel2.getId(); - - // when - channels.exitChannelById(deleteTargetChannelId); - - // then - assertThat(channels.countParticipatedChannels()).isNotEqualTo(oldParticipatedChannelCount); - } - } -} - - - diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/repository/common/InMemoryCrudRepositoryTest.java b/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/repository/common/InMemoryCrudRepositoryTest.java deleted file mode 100644 index 533989b2c..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/repository/common/InMemoryCrudRepositoryTest.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.sprint.mission.discodeit.repository.common; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertAll; - -import com.sprint.mission.discodeit.testdummy.TestDummyInMemoryCurdRepository; -import com.sprint.mission.discodeit.testdummy.TestUUIDEntity; -import java.util.UUID; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -@DisplayName("레포지토리 추상 클래스 테스트") -class InMemoryCrudRepositoryTest { - - private static TestDummyInMemoryCurdRepository repository; - - @Test - void initializeRepositoryTest() { - assertThat(new TestDummyInMemoryCurdRepository()).isNotNull(); - } - - @Nested - @DisplayName("데이터를 저장했을 때") - class whenAddEntity { - - @BeforeEach - void setUp() { - repository = new TestDummyInMemoryCurdRepository(); - } - - @Test - @DisplayName("새로운 객체를 생성하여 저장했을 때 동일한 객체가 리턴") - void givenNewEntityWhenSaveEntityThenReturnNewEntity() { - // given - TestUUIDEntity newEntity = new TestUUIDEntity(); - // when - var savedEntity = repository.save(newEntity); - // then - assertThat(savedEntity).isEqualTo(newEntity); - } - - @Test - @DisplayName("레포지토리에 저장 시 총 저장되어 있는 개수 증가") - void givenSaveNewEntityWhenCountRepositoryThenSizeIncrease() { - // given - var oldCount = repository.count(); - repository.save(new TestUUIDEntity()); - // when - var newCount = repository.count(); - // then - assertThat(newCount).isEqualTo(oldCount + 1); - } - - @Test - @DisplayName("저장한 객체와 동일한 객체의 id로 가져온 객체 비교") - void givenSavedEntityWhenFindByIdThenReturnEqualIsTrue() { - // given - var createdEntity = new TestUUIDEntity(); - repository.save(createdEntity); - // when - var findEntity = repository.findById(createdEntity.getId()).orElse(null); - //then - assertThat(findEntity).isEqualTo(createdEntity); - } - - @Test - @DisplayName("새로운 객체를 저장 후 삭제 시 정상 작동") - void givenNewEntitySaveWhenDeleteEntityThenStoreSizeNoChange() { - // given - int storeSize = repository.count(); - var newEntity = new TestUUIDEntity(); - repository.save(newEntity); - // when - repository.deleteById(newEntity.getId()); - // then - assertThat(repository.count()).isEqualTo(storeSize); - } - } - - @Nested - @DisplayName("저장된 객체") - class whenFindEntity { - private static final int REPOSITORY_SIZE = 10; - private static TestUUIDEntity entity; - - @BeforeAll - static void setUp() { - repository = new TestDummyInMemoryCurdRepository(); - entity = new TestUUIDEntity(); - repository.save(entity); - for (int i = 0; i < REPOSITORY_SIZE; i++) { - repository.save(new TestUUIDEntity()); - } - } - - @Test - @DisplayName("확실히 저장되어 있는 객체를 id로 레포지터리에서 찾을 때 true 리턴") - void givenEnsureEntityIdWhenFindByIdThenReturnTrue() { - // given - var existId = entity.getId(); - // when - var result = repository.isExistsById(existId); - // then - assertThat(result).isTrue(); - } - - @Test - @DisplayName("존재하지 않는 id로 레포지터리에서 찾을 때 false 리턴") - void givenGenerateUUIDWhenFindByIdThenReturnFalse() { - // given - var id = UUID.randomUUID(); - // when - var result = repository.isExistsById(id); - //then - assertThat(result).isFalse(); - } - - // 모든 저장된 객체를 가져오기 - @Test - @DisplayName("저장된 모든 객체를 리스트로 조회시 레포지터리 count 메서드의 결과 비교") - void whenFindAllThenReturnAll() { - // given - int repositorySize = repository.count(); - // when - var allEntity = repository.findAll(); - // then - assertAll( - () -> assertThat(allEntity).isNotEmpty(), - () -> assertThat(allEntity.size()).isEqualTo(repositorySize) - ); - } - } -} \ No newline at end of file diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/repository/user/UserRepositoryImplTest.java b/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/repository/user/UserRepositoryImplTest.java deleted file mode 100644 index 0e677848c..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/repository/user/UserRepositoryImplTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.sprint.mission.discodeit.repository.user; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertAll; - -import com.sprint.mission.discodeit.entity.user.entity.User; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.testdummy.TestDummyFactory; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -class UserRepositoryImplTest { - private static final String TEST_NAME = "Test"; - private User user; - private UserRepository userRepository; - - @BeforeEach - void setUp() { - userRepository = TestDummyFactory.getUserRepository(); - user = User.createFrom(TEST_NAME); - userRepository.save(user); - } - - - @Test - @DisplayName("사용자 이름으로 찾을 때 유저정보 객체를 리턴") - void givenUsernameWhenFindByNameThenReturnUser() { - // given - // when - var findUser = userRepository.findByUsername(TEST_NAME).orElse(null); - // then - assertAll( - () -> assertThat(findUser).isEqualTo(user), - () -> assertThat(findUser).isNotNull() - ); - } - -} \ No newline at end of file diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/service/jcf/JCFChannelServiceTest.java b/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/service/jcf/JCFChannelServiceTest.java deleted file mode 100644 index 296300e59..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/service/jcf/JCFChannelServiceTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.sprint.mission.discodeit.service.jcf; - -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.sprint.mission.discodeit.repository.jcf.channel.ChannelRepository; -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.entity.channel.Channel; -import com.sprint.mission.discodeit.entity.channel.dto.CreateNewChannelRequest; -import com.sprint.mission.discodeit.entity.user.entity.User; -import com.sprint.mission.discodeit.service.channel.ChannelConverter; -import com.sprint.mission.discodeit.service.channel.ChannelService; -import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -class JCFChannelServiceTest { - private ChannelService channelService; - @Mock - private ChannelRepository channelRepository; - @Mock - private UserRepository userRepository; - - private ChannelConverter channelConverter = new ChannelConverter(); - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - - channelService = JCFChannelService.getInstance(userRepository, channelRepository); - } - - - // createChannelOrThrow 테스트 => uuid 값이 수정할 수 없어서 테스트하는데 너무 어려움을 느낌.. - @Test - void test() { - // given - var user = User.createFrom("SB_1기_백재우"); - var channelName = "스프링백엔드_1기"; - var channel = Channel.createOfChannelNameAndUser(channelName, user); - // when - var request = new CreateNewChannelRequest(user.getId(), channelName); - when(userRepository.findById(user.getId())).thenReturn(Optional.of(user)); - // then - channelService.createChannelOrThrow(request); - - verify(userRepository, times(1)).findById(user.getId()); - } -} \ No newline at end of file diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/service/jcf/JCFUserServiceTest.java b/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/service/jcf/JCFUserServiceTest.java deleted file mode 100644 index 0300965b4..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/service/jcf/JCFUserServiceTest.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.sprint.mission.discodeit.service.jcf; - -import static com.sprint.mission.discodeit.entity.common.Status.MODIFIED; -import static com.sprint.mission.discodeit.entity.common.Status.REGISTERED; -import static com.sprint.mission.discodeit.entity.common.Status.UNREGISTERED; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.entity.user.dto.FindUserRequest; -import com.sprint.mission.discodeit.entity.user.dto.ModifyUserInfoRequest; -import com.sprint.mission.discodeit.entity.user.dto.RegisterUserRequest; -import com.sprint.mission.discodeit.entity.user.dto.UnregisterUserRequest; -import com.sprint.mission.discodeit.entity.user.entity.User; -import com.sprint.mission.discodeit.service.user.UserConverter; -import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -@DisplayName("UserInterface smoke testing") -class JCFUserServiceTest { - private static final String NAME = "SB_1기_백재우"; - - private UserRepository userRepository; - private UserConverter userConverter; - private JCFUserService userService; - private User user; - - @BeforeEach - void setUp() { - userRepository = mock(UserRepository.class); - userConverter = UserConverter.getInstance(); - userService = new JCFUserService(userRepository, userConverter); - user = User.createFrom(NAME); - } - - @Test - @DisplayName("유저 등록 userService register 호출 시 userInfoResponse 반환") - void givenNewUserRequestWhenRegisterThenReturnUserInfoResponse() { - // given - RegisterUserRequest registerUserRequest = new RegisterUserRequest(NAME); - var registerUser = userConverter.toEntity(registerUserRequest); - when(userRepository.save(any(User.class))).thenReturn(registerUser); - - // when - var infoResponse = userService.register(registerUserRequest); - - // then - assertAll( - () -> { - assertThat(infoResponse).isNotNull(); - - assertAll( - () -> assertThat(infoResponse.username()).isEqualTo(NAME), - () -> assertThat(infoResponse.status()).isEqualTo(REGISTERED) - ); - } - ); - verify(userRepository).save(any(User.class)); - } - - @Test - @DisplayName("유저 이름으로 findUserByUsername 호출 시 UserResponse 반환") - void givenUsernameWhenFindUserByUsernameThenReturnUserInfoResponse() { - // given - Optional mockUser = Optional.of(user); - var findUserRequest = new FindUserRequest(NAME); - when(userRepository.findByUsername(NAME)).thenReturn(mockUser); - - // when - var user = userService.findUserByUsernameOrThrow(findUserRequest); - - // then - assertThat(user).isNotNull(); - assertThat(user.username()).isEqualTo(NAME); - - verify(userRepository).findByUsername(NAME); - } - // TODO : 해지된 유지이름으로 조회 시 실패 테스트 - - @Test - @DisplayName("유저 정보 수정 modifyUserInfo 호출 시 UserResponse 반환") - void givenModifyUserInfoRequestWhenModifyUserInfoThenReturnUserInfoResponse() { - // given - var modifyUserInfoRequest = new ModifyUserInfoRequest(user.getId(), "CHANGE NAME"); - when(userRepository.findById(user.getId())).thenReturn(Optional.of(user)); - when(userRepository.save(any(User.class))).thenReturn(user); - - // when - var userInfoResponse = userService.modifyUserInfo(modifyUserInfoRequest); - - // then - assertAll( - () -> { - assertThat(userInfoResponse).isNotNull(); - - assertAll( - () -> assertThat(userInfoResponse.status()).isEqualTo(MODIFIED), - () -> assertThat(userInfoResponse.username()).isEqualTo("CHANGE NAME") - ); - } - ); - - verify(userRepository).save(any(User.class)); - verify(userRepository).findById(user.getId()); - } - - // 탈퇴 - @Test - @DisplayName("유저 회원 탈퇴 unregister 호출 시 유저 상태 변경") - void givenUnregisterUserRequestWhenUnregisterThenUserStatusIsChanged() { - // given - var unregisterUserRequest = new UnregisterUserRequest(user.getId(), NAME); - when(userRepository.findById(user.getId())).thenReturn(Optional.of(user)); - when(userRepository.save(any(User.class))).thenReturn(user); - - // when - userService.UnRegisterUser(unregisterUserRequest); - - // then - assertThat(user.getStatus()).isEqualTo(UNREGISTERED); - verify(userRepository).findById(user.getId()); - verify(userRepository).save(any(User.class)); - } - -} \ No newline at end of file diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/testdummy/TestDummyFactory.java b/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/testdummy/TestDummyFactory.java deleted file mode 100644 index 1900c89da..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/testdummy/TestDummyFactory.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.sprint.mission.discodeit.testdummy; - -import com.sprint.mission.discodeit.repository.jcf.user.UserRepository; -import com.sprint.mission.discodeit.repository.jcf.user.JCFUserRepositoryInMemory; -import com.sprint.mission.discodeit.entity.user.entity.User; -import java.util.ArrayList; -import java.util.List; - -public class TestDummyFactory { - - private static final List users = new ArrayList<>(List.of( - User.createFrom("홍길동"), - User.createFrom("김길동"), - User.createFrom("이길동"), - User.createFrom("박깅동") - )); - - - public static UserRepository getUserRepository() { - var userRepository = JCFUserRepositoryInMemory.getInstance(); - users.forEach(userRepository::save); - return userRepository; - } -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/testdummy/TestDummyInMemoryCurdRepository.java b/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/testdummy/TestDummyInMemoryCurdRepository.java deleted file mode 100644 index 4cf3aa25e..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/testdummy/TestDummyInMemoryCurdRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.sprint.mission.discodeit.testdummy; - -import com.sprint.mission.discodeit.repository.common.InMemoryCrudRepository; -import java.util.UUID; - -public class TestDummyInMemoryCurdRepository extends InMemoryCrudRepository { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/testdummy/TestUUIDEntity.java b/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/testdummy/TestUUIDEntity.java deleted file mode 100644 index 114ac72bf..000000000 --- a/codeit-bootcamp-spring/1-sprint-mission/src/test/java/com/sprint/mission/discodeit/testdummy/TestUUIDEntity.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.sprint.mission.discodeit.testdummy; - -import com.sprint.mission.discodeit.entity.common.AbstractUUIDEntity; - -public class TestUUIDEntity extends AbstractUUIDEntity { -} diff --git a/codeit-bootcamp-spring/1-sprint-mission/study/Valid.md b/codeit-bootcamp-spring/1-sprint-mission/study/Valid.md new file mode 100644 index 000000000..f7528155b --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/study/Valid.md @@ -0,0 +1,59 @@ +# 도메인 유효성 검증 + +도메인의 유효성 검증은 비즈니스 로직으로 적절히 처리되고 에러를 반환해주어야 한다. +그렇다면, 어떻게 검증하는 것이 좋을까 ? + +우선, 도메인 객체와 DTO 객체의 분리를 먼저 하자. 도메인 객체에서 던지는 에러와 DTO 에서 던지는 +에러를 분리해서 생각해본다는 말이다. 밀접하게 연관되어 있는 두 객체 사이의 비슷한 검증으로 인해 +어떻게 만들어야 할지 헷갈리기 때문이다. + +도메인 객체의 유효성 검사를 위해서 외부에 validator 담당 객체를 만들어 준다. 그리고 도메인 +객체의 생성자에서 정적 메서드를 호출하여 적절한 처리를 통해 도메인의 무결성을 보장한다. + +분리를 통해서 만들어지는 `검증 객체`가 많아질 수 도 있겠다고 생각한다. 공통되는 부분이 있다면 +최대한 고려해서 리팩터링을 진행하는 것이 중요하다. + +또한 검증객체에서 던지는 `커스텀 에러 객체` 또한 만들어주어야 한다. 이를 통해서 공통되는 +에러 객체를 던지고 그 내용은 `검증 객체`에 따라서 다른 내용이 들어가게 만들어준다. 이후 던져진 +에러를 잡고 적절히 반환해주기 위해 컨트롤러에서 응답객체에 적절히 담아서 사용자에게 응답한다. + +## Hibernate Validator(@Valid) 사용 시 커스텀 Validator 가 필요 없는가? +hibernate 에서 제공해주는 valid 기능을 사용하게 된다면 내 도메인 객체에서 값을 검증해주는 +검증 객체 또는 검증 메서드를 만들 필요가 없지 않을까라고 생각이 들었습니다. + +결론은 커스텀 검증 객체가 필요합니다. 그 이유에 대해서 살펴보겠습니다. + +우선 다음 코드가 테스트 실패합니다. + +
+ 도메인 + 테스트 +
+ +### Hibernate Validator(@Valid) 는 언제 동작하는가? +Hibernate validator 가 동작하는 경우는 다음과 같습니다. +1. Spring MVC에서 요청 바인딩 시 (@Valid 사용) +2. JPA 엔티티로 저장할 때 유효성 검사를 실행할 때 +3. 명시적으로 Hibernate Validator를 호출할 때 + +즉, 엔티티 도메인 객체 생성자에서 `new Test("123")` 처럼 직접 객체를 만드는 과정에서는 +검증이 되지 않습니다. 왜냐하면 `@Email` 검증이 동작하지 않기 때문입니다. + +
+ +| 상황 | Hibernate Validator(@Valid) 자동 실행 여부 | +|------|--------------------------------| +| **Spring 컨트롤러에서 `@Valid` 사용** | ✅ 자동 실행됨 | +| **JPA에서 `persist()` 또는 `update()` 호출 시** | ✅ 자동 실행됨 (단, `@PrePersist`, `@PreUpdate` 필요) | +| **`new Test("123")`로 직접 객체 생성** | ❌ 자동 실행되지 않음 | + +### 엔티티 도메인 객체에 필요할까? +또 한가지 생각해볼것이 있습니다. Validator 기능을 통해서 검증을 실행하면 되는 것이 아닌가요. +왜 도메인 커스텀 검증 객체를 만들어야 하는지 이유는 무엇일까요? + +JPA의 기능으로 데이터베이스에 저장할 때 검증을 하게 된다면 영속성 컨텍스트에서 검증 후 +DB 요청을 하기 때문에 별다른 검증을 진행하지 않아도 되지 않을까 생각이 듭니다. 만약 JPA를 +지원하지 않는 데이터베이스로 변경하게 된다면 정상적으로 검증이 실행되지 않을 것입니다. 그렇다면 +수동으로 Hibernate Validator 를 실행시켜야 하는데, 코드가 매우 지저분해질 것입니다. + +이러한 이유 때문에 값을 검증하는 로직을 관리하는 객체를 만들고 검증을 실행해야 한다고 생각합니다. diff --git a/codeit-bootcamp-spring/1-sprint-mission/study/channelDomain.png b/codeit-bootcamp-spring/1-sprint-mission/study/channelDomain.png new file mode 100644 index 000000000..c3787c682 Binary files /dev/null and b/codeit-bootcamp-spring/1-sprint-mission/study/channelDomain.png differ diff --git a/codeit-bootcamp-spring/1-sprint-mission/study/domain.png b/codeit-bootcamp-spring/1-sprint-mission/study/domain.png new file mode 100644 index 000000000..6d515bbba Binary files /dev/null and b/codeit-bootcamp-spring/1-sprint-mission/study/domain.png differ diff --git a/codeit-bootcamp-spring/1-sprint-mission/study/domaintest.png b/codeit-bootcamp-spring/1-sprint-mission/study/domaintest.png new file mode 100644 index 000000000..1ec9ee956 Binary files /dev/null and b/codeit-bootcamp-spring/1-sprint-mission/study/domaintest.png differ diff --git a/codeit-bootcamp-spring/1-sprint-mission/study/refactoring.md b/codeit-bootcamp-spring/1-sprint-mission/study/refactoring.md new file mode 100644 index 000000000..fb3f2cbb2 --- /dev/null +++ b/codeit-bootcamp-spring/1-sprint-mission/study/refactoring.md @@ -0,0 +1,12 @@ +## 🛠️ 도메인 리팩토링하기 + +## User +- 회원 가입 + - user 는 유저 닉네임, 이메일, 비밀번호를 입력받는다. (컨트롤러) + - user를 생성한다. (서비스) + - user 정보 검증 (비즈니스) + - user 닉네임의 길이 : 1~15 글자 제한 + - 이메일 형식 + - 비밀번호 형식 + - 비밀번호 암호화 + - 데이터베이스에 user를 저장한다. (데이터베이스) diff --git "a/codeit-bootcamp-spring/1-sprint-mission/study/\353\217\204\353\251\224\354\235\270 \353\252\250\353\215\270\353\247\201.md" "b/codeit-bootcamp-spring/1-sprint-mission/study/\353\217\204\353\251\224\354\235\270 \353\252\250\353\215\270\353\247\201.md" new file mode 100644 index 000000000..397dfebe4 --- /dev/null +++ "b/codeit-bootcamp-spring/1-sprint-mission/study/\353\217\204\353\251\224\354\235\270 \353\252\250\353\215\270\353\247\201.md" @@ -0,0 +1,90 @@ +# Domain Modeling +디스코드 서비스를 활용하면서 각 도메인 모델에 필요한 정보를 도출한다. + + +- User +- Channel +- Message + +## 유저 + +- 회원 가입 + - `이메일`, `별명`, `사용자명`, `비밀번호`, `생년월일`, `수신여부` 를 입력받는다. + - 별명 : 다른 회원에게 보여지는 이름입니다. 이모지 사용가능합니다. + - 서버마다 다르게 설정가능 + - 최소 1~ 최대 32자 + - 사용자명: 숫자,밑줄 _, 마침표, 문자 + - 길이제한: 최소 2 ~ 최대 32자 + - 사용가능문자 : 영문(a-z, A-z), 숫자(0-9), 밑줄(_), 마침표(.) + - 금지된 문자: 공백, 특수문자, 이모지, 연속된마침표, 마침표로 시작하거나 끝나는것 + - 대소문자 구분없음 -> 중복 방지를 위해 모두 소문자로 변환하여 저장함 + - 유저이름은 고유 + - 특정 문자 단어제한 : discord, admin, moderator, 욕설 + - 비밀번호: 필수, 개수 제한 8미만 x , 영문 대문자, 소문자, 숫자, 특수문자가 들어가야합니다. 공백 x + - 생년월일: 필수, 13세 이상만 사용가능 + - 사용하고 있는 이메일인지 검증한다. + - 사용하고 있는 유저이름인지 검증한다. + - 비밀번호를 저장할 때 암호화를 진행한다. + - [jBCrypt](https://www.mindrot.org/projects/jBCrypt/) + - 회원 프로필 사진을 저장한다. + - 파일을 입력받아 저장한다. + +- 로그인 + - `이메일`과 `비밀번호`를 입력받는다. + - 유저의 비밀번호가 틀리다면 에러를 반환한다. + +- 비밀번호 변경 + - flow + - 본인이 맞는지 기존 비밀번호를 확인한다. + - 변경 비밀번호를 입력받는다. + - 디비에서 유저조회 + - 조횐된 유저의 비밀번호를 암호화 후 변경 + - 디비에 저장 + - 리팩터링할 부분 : 토큰으로 일회용 토큰으로 기존 비밀번호 확인 후 토큰이 없다면 불가하게 하는방법 구현하기 +- 수신 여부 변경 + +## 채널 +- 새로운 채널 생성 + - `채널이름`, `채널 유형`, `채널 생성 유저`를 입력받는다. + - 텍스트 채널 유형 + - 음성, 영상, 화면 유형 + - 채널 주제 (생성 시에는 입력받지 않음, 1024 글자 제한) +- 채널 삭제 + - 채널 매니저가 아닐 경우 에러 +- 채널 정보 수정 + - 채널 매니저가 아닐 경우 에러 + - 이름 수정 + - 채널 주제 수정 1024 글자제한 + +## 메세지 + +- 새로운 메시지 생성 + - `메시지 id`, `메시지 생성, 수정시간`, `메시지 내용`, `보낸사람`, `목적지 채널` + - 메시지 내용은 비어있을 수 없다. +- 메시지 내용 수정 + - 발신자가 아니라면 에러 +- 메시지 삭제 + - 발진자가 아니라면 에러 + + +## ReadStatus + - 사용자가 채널 별 마지막으로 메시지를 읽은 시간을 표현하는 도메인 모델입니다. 사용자별 각 채널에 읽지 않은 메시지를 확인하기 위해 활용합니다. + - `id`, `createdAt`, `updatedAt` + + - 유저가 채널별 읽은 시간을 기록한다. + - 유저가 채널에 접속한 시간을 업데이트한다. + - 접속한 적이 없는 경우에는 새로운 객체를 생성하여 저장한다. + - 접속한 적이 있는 경우에는 기존 객체의 접속 시간을 업데이트한다. + +## UserStatus +- 사용자 별 마지막으로 확인된 접속 시간을 표현하는 도메인 모델입니다. 사용자의 온라인 상태를 확인하기 위해 활용합니다. +- 마지막 접속 시간을 기준으로 현재 로그인한 유저로 판단할 수 있는 메소드를 정의하세요. + - 마지막 접속 시간이 현재 시간으로부터 5분 이내이면 현재 접속 중인 유저로 간주합니다. +- `id`, `createdAt`, `updatedAt` + +## BinaryContent +- 이미지, 파일 등 바이너리 데이터를 표현하는 도메인 모델입니다. 사용자의 프로필 이미지, 메시지에 첨부된 파일을 저장하기 위해 활용합니다. +- 수정 불가능한 도메인 모델로 간주합니다. 따라서 updatedAt 필드는 정의하지 않습니다. +- User, Message 도메인 모델과의 의존 관계 방향성을 잘 고려하여 id 참조 필드를 추가하세요. + +-- newLine for git