diff --git a/backend/kirikiri/build.gradle b/backend/kirikiri/build.gradle index cf8b5b92d..7bd653e1d 100644 --- a/backend/kirikiri/build.gradle +++ b/backend/kirikiri/build.gradle @@ -80,7 +80,8 @@ jacocoTestReport { "**/*Request*", "**/*Response*", "**/*Interceptor*", - "**/*Exception*" + "**/*Exception*", + "**/*Mapper*" ] + QDomains) }) ) @@ -122,7 +123,8 @@ jacocoTestCoverageVerification { "**.*Request*", "**.*Response*", "**.*Interceptor*", - "**.*Exception*" + "**.*Exception*", + "**.*Mapper*" ] + QDomains } } @@ -168,6 +170,9 @@ dependencies { // flyway implementation 'org.flywaydb:flyway-mysql' + // redis + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + // test testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' testImplementation 'org.springframework.boot:spring-boot-starter-test' diff --git a/backend/kirikiri/src/docs/asciidoc/auth.adoc b/backend/kirikiri/src/docs/asciidoc/auth.adoc index 65f3ce4ad..c003e342c 100644 --- a/backend/kirikiri/src/docs/asciidoc/auth.adoc +++ b/backend/kirikiri/src/docs/asciidoc/auth.adoc @@ -58,3 +58,14 @@ operation::auth-create-api-test/토큰_재발행_시_토큰이_만료_됐을_때 === *2-4* 실패 - 토큰 재발행 시 토큰이 유효하지 않을 때 operation::auth-create-api-test/토큰_재발행_시_토큰이_유효하지_않을_때_예외를_던진다[snippets='http-request,http-response'] + +[[네이버OAuth로그인-API]] +== *3. 네이버 OAuth 로그인* + +=== *3-1* 성공 - 네이버 로그인 페이지 리다이렉트를 성공한다 + +operation::auth-create-api-test/네이버_로그인_페이지를_정상적으로_반환한다[snippets='http-request,http-response,response-fields'] + +=== *3-2* 성공 - 네이버 사용자 정보 요청을 성공한다 + +operation::auth-create-api-test/네이버에서_콜백요청을_받아_사용자_정보를_반환한다[snippets='http-request,http-response'] diff --git a/backend/kirikiri/src/docs/asciidoc/goalroom.adoc b/backend/kirikiri/src/docs/asciidoc/goalroom.adoc index 5859c216b..8b46d2ffa 100644 --- a/backend/kirikiri/src/docs/asciidoc/goalroom.adoc +++ b/backend/kirikiri/src/docs/asciidoc/goalroom.adoc @@ -45,27 +45,19 @@ operation::goal-room-create-api-test/골룸_생성_시_삭제된_로드맵_경 operation::goal-room-create-api-test/골룸_생성_시_존재하지_않는_회원일_경우[snippets='http-request,http-response'] -=== *1-8* 실패 - 골룸 생성 시 골룸 투두의 시작 날짜가 오늘보다 전일 경우 - -operation::goal-room-create-api-test/골룸_생성_시_골룸_투두의_시작_날짜가_오늘보다_전일_경우[snippets='http-request,http-response'] - -=== *1-9* 실패 - 골룸 생성 시 골룸 투두의 시작 날짜보다 종료 날짜가 빠른 경우 - -operation::goal-room-create-api-test/골룸_생성_시_골룸_투두의_시작_날짜보다_종료_날짜가_빠른_경우[snippets='http-request,http-response'] - -=== *1-10* 실패 - 골룸 생성 시 골룸 노드의 시작 날짜가 오늘보다 전일 경우 +=== *1-9* 실패 - 골룸 생성 시 골룸 노드의 시작 날짜가 오늘보다 전일 경우 operation::goal-room-create-api-test/골룸_생성_시_골룸_노드의_시작_날짜가_오늘보다_전일_경우[snippets='http-request,http-response'] -=== *1-11* 실패 - 골룸 생성 시 골룸 노드의 시작 날짜보다 종료 날짜가 빠른 경우 +=== *1-10* 실패 - 골룸 생성 시 골룸 노드의 시작 날짜보다 종료 날짜가 빠른 경우 operation::goal-room-create-api-test/골룸_생성_시_골룸_노드의_시작_날짜보다_종료_날짜가_빠른_경우[snippets='http-request,http-response'] -=== *1-12* 실패 - 골룸 생성 시 골룸 노드의 인증 횟수가 0보다 작을 경우 +=== *1-11* 실패 - 골룸 생성 시 골룸 노드의 인증 횟수가 0보다 작을 경우 operation::goal-room-create-api-test/골룸_생성_시_골룸_노드의_인증_횟수가_0보다_작을_경우[snippets='http-request,http-response'] -=== *1-13* 실패 - 골룸 생성 시 골룸 노드의 인증 횟수가 기간보다 클 경우 +=== *1-12* 실패 - 골룸 생성 시 골룸 노드의 인증 횟수가 기간보다 클 경우 operation::goal-room-create-api-test/골룸_생성_시_골룸_노드의_인증_횟수가_기간보다_클_경우[snippets='http-request,http-response'] diff --git a/backend/kirikiri/src/docs/asciidoc/member.adoc b/backend/kirikiri/src/docs/asciidoc/member.adoc index ddb45009e..0b7e95670 100644 --- a/backend/kirikiri/src/docs/asciidoc/member.adoc +++ b/backend/kirikiri/src/docs/asciidoc/member.adoc @@ -32,37 +32,29 @@ operation::member-create-api-test/회원가입_시_비밀번호가_형식에_맞 operation::member-create-api-test/회원가입_시_닉네임이_형식에_맞지않을때[snippets='http-request,http-response'] -=== *1-5* 실패 - 전화번호 형식에 맞지 않을 때 - -operation::member-create-api-test/회원가입_시_전화번호_형식에_맞지않을때[snippets='http-request,http-response'] - -=== *1-6* 실패 - 중복된 아이디일 때 +=== *1-5* 실패 - 중복된 아이디일 때 operation::member-create-api-test/회원가입_시_중복된_닉네임일_때[snippets='http-request,http-response'] -=== *1-7* 실패 - 중복된 닉네임일 때 +=== *1-6* 실패 - 중복된 닉네임일 때 operation::member-create-api-test/회원가입_시_중복된_아이디일_때[snippets='http-request,http-response'] -=== *1-8* 실패 - 회원가입 시 아이디에 빈값이 들어올 때 +=== *1-7* 실패 - 회원가입 시 아이디에 빈값이 들어올 때 operation::member-create-api-test/회원가입_시_아이디에_빈값이_들어올_때[snippets='http-request,http-response'] -=== *1-9* 실패 - 회원가입 시 비밀번호에 빈값이 들어올 때 +=== *1-8* 실패 - 회원가입 시 비밀번호에 빈값이 들어올 때 operation::member-create-api-test/회원가입_시_비밀번호에_빈값이_들어올_때[snippets='http-request,http-response'] -=== *1-10* 실패 - 회원가입 할 때 닉네임에 빈값이 들어올 때 +=== *1-9* 실패 - 회원가입 할 때 닉네임에 빈값이 들어올 때 operation::member-create-api-test/회원가입_시_닉네임에_빈값이_들어올_때[snippets='http-request,http-response'] -=== *1-11* 실패 - 회원가입 시 전화번호에 빈값이 들어올 때 - -operation::member-create-api-test/회원가입_시_전화번호에_빈값이_들어올_때[snippets='http-request,http-response'] - -=== *1-12* 실패 - 회원가입 시 아이디 비밀번호 닉네임 전화번호 필드에 빈값이 들어올 때 +=== *1-10* 실패 - 회원가입_시_아이디_비밀번호_닉네임_이메일_필드에_빈값이_들어올_때 -operation::member-create-api-test/회원가입_시_아이디_비밀번호_닉네임_전화번호_필드에_빈값이_들어올_때[snippets='http-request,http-response'] +operation::member-create-api-test/회원가입_시_아이디_비밀번호_닉네임_이메일_필드에_빈값이_들어올_때[snippets='http-request,http-response'] [[사용자정보조회-API]] == *2. 사용자 정보 조회* diff --git a/backend/kirikiri/src/docs/asciidoc/overview.adoc b/backend/kirikiri/src/docs/asciidoc/overview.adoc index c78b3d840..b5d8d102f 100644 --- a/backend/kirikiri/src/docs/asciidoc/overview.adoc +++ b/backend/kirikiri/src/docs/asciidoc/overview.adoc @@ -25,26 +25,6 @@ |=== -[[overview-page-response]] -=== *Page Response Data* - -|=== -| Field Name | Type | Description - -| currentPage -| int -| 현재 페이지 값 - -| totalPage -| int -| 총 페이지 값 - -| data -| Object -| 데이터 리스트 - -|=== - [[overview-error-response]] === *Error Response Data* diff --git a/backend/kirikiri/src/docs/asciidoc/roadmap.adoc b/backend/kirikiri/src/docs/asciidoc/roadmap.adoc index 32b684800..f5d0fc6ef 100644 --- a/backend/kirikiri/src/docs/asciidoc/roadmap.adoc +++ b/backend/kirikiri/src/docs/asciidoc/roadmap.adoc @@ -219,3 +219,22 @@ operation::roadmap-create-api-test/로드맵_삭제시_존재하지_않는_로 === *10-3* 실패 - 자신이 생성한 로드맵이 아닌 경우 operation::roadmap-create-api-test/로드맵_삭제시_자신이_생성한_로드맵이_아닌_경우_예외가_발생한다[snippets='http-request,http-response,response-fields'] + +[[로드맵카테고리생성-API]] +== *11. 로드맵 카테고리 생성 API* + +=== *11-1* 성공 + +operation::roadmap-create-api-test/정상적으로_로드맵_카테고리를_생성한다[snippets='http-request,request-fields,http-response'] + +=== *11-2* 로드맵 카테고리 생성 시 카테고리 이름이 빈값일 경우 + +operation::roadmap-create-api-test/로드맵_카테고리_생성_시_카테고리_이름이_빈값일_경우[snippets='http-request,request-fields,http-response'] + +=== *11-3* 로드맵 카테고리 생성 시 카테고리 이름이 10자 초과일 경우 + +operation::roadmap-create-api-test/로드맵_카테고리_생성_시_카테고리_이름이_10자_초과일_경우[snippets='http-request,request-fields,http-response'] + +=== *11-4* 로드맵 카테고리 생성 시 카테고리 이름이 중복될 경우 + +operation::roadmap-create-api-test/로드맵_카테고리_생성_시_카테고리_이름이_중복될_경우[snippets='http-request,request-fields,http-response'] diff --git a/backend/kirikiri/src/main/java/co/kirikiri/common/config/AWSConfig.java b/backend/kirikiri/src/main/java/co/kirikiri/common/config/AWSConfig.java index b084ee0eb..21500a245 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/common/config/AWSConfig.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/common/config/AWSConfig.java @@ -1,5 +1,7 @@ package co.kirikiri.common.config; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.regions.Regions; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; @@ -11,15 +13,23 @@ public class AWSConfig { private final Regions region; + private final String accessKey; + private final String secretKey; - public AWSConfig(@Value("${cloud.aws.region.static}") final String region) { + public AWSConfig(@Value("${cloud.aws.region.static}") final String region, + @Value("${cloud.aws.credentials.access-key}") final String accessKey, + @Value("${cloud.aws.credentials.secret-key}") final String secretKey) { this.region = Regions.fromName(region); + this.accessKey = accessKey; + this.secretKey = secretKey; } @Bean public AmazonS3 amazonS3() { + final BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); return AmazonS3ClientBuilder.standard() .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) .build(); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/common/config/JpaConfig.java b/backend/kirikiri/src/main/java/co/kirikiri/common/config/JpaConfig.java deleted file mode 100644 index 18158e4fb..000000000 --- a/backend/kirikiri/src/main/java/co/kirikiri/common/config/JpaConfig.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.kirikiri.common.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; - -@Configuration -@EnableJpaAuditing -public class JpaConfig { - -} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/common/config/NetworkConfig.java b/backend/kirikiri/src/main/java/co/kirikiri/common/config/NetworkConfig.java new file mode 100644 index 000000000..5663d17e3 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/common/config/NetworkConfig.java @@ -0,0 +1,14 @@ +package co.kirikiri.common.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class NetworkConfig { + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/common/config/RedisConfig.java b/backend/kirikiri/src/main/java/co/kirikiri/common/config/RedisConfig.java new file mode 100644 index 000000000..e49a413d9 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/common/config/RedisConfig.java @@ -0,0 +1,52 @@ +package co.kirikiri.common.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.time.Duration; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +@EnableCaching +@Profile(value = {"prod", "dev", "local"}) +public class RedisConfig { + + @Bean + public RedisTemplate redisTemplate(final RedisConnectionFactory redisConnectionFactory) { + final RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + return redisTemplate; + } + + @Bean + public CacheManager redisCacheManager(final RedisConnectionFactory redisConnectionFactory) { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.EVERYTHING); + + final RedisSerializer serializer = new GenericJackson2JsonRedisSerializer(objectMapper); + + final RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofMinutes(30L)) + .disableCachingNullValues() + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer)); + + return RedisCacheManager.RedisCacheManagerBuilder + .fromConnectionFactory(redisConnectionFactory) + .cacheDefaults(redisCacheConfiguration) + .build(); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/common/config/WebConfig.java b/backend/kirikiri/src/main/java/co/kirikiri/common/config/WebConfig.java index 4b19bc9a9..73fca7c9f 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/common/config/WebConfig.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/common/config/WebConfig.java @@ -3,12 +3,12 @@ import co.kirikiri.common.interceptor.AuthInterceptor; import co.kirikiri.common.resolver.MemberIdentifierArgumentResolver; import co.kirikiri.common.resolver.RoadmapSaveArgumentResolver; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import java.util.List; @Configuration @RequiredArgsConstructor diff --git a/backend/kirikiri/src/main/java/co/kirikiri/common/interceptor/AuthInterceptor.java b/backend/kirikiri/src/main/java/co/kirikiri/common/interceptor/AuthInterceptor.java index a580a4897..d2298df5c 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/common/interceptor/AuthInterceptor.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/common/interceptor/AuthInterceptor.java @@ -1,7 +1,7 @@ package co.kirikiri.common.interceptor; -import co.kirikiri.exception.AuthenticationException; -import co.kirikiri.service.AuthService; +import co.kirikiri.service.auth.AuthService; +import co.kirikiri.service.exception.AuthenticationException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; diff --git a/backend/kirikiri/src/main/java/co/kirikiri/common/resolver/MemberIdentifierArgumentResolver.java b/backend/kirikiri/src/main/java/co/kirikiri/common/resolver/MemberIdentifierArgumentResolver.java index 26bb61ad4..caf9b0e30 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/common/resolver/MemberIdentifierArgumentResolver.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/common/resolver/MemberIdentifierArgumentResolver.java @@ -1,7 +1,9 @@ package co.kirikiri.common.resolver; -import co.kirikiri.exception.AuthenticationException; -import co.kirikiri.service.AuthService; +import co.kirikiri.common.interceptor.Authenticated; +import co.kirikiri.service.auth.AuthService; +import co.kirikiri.service.exception.AuthenticationException; +import co.kirikiri.service.exception.ServerException; import lombok.RequiredArgsConstructor; import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; @@ -21,6 +23,9 @@ public class MemberIdentifierArgumentResolver implements HandlerMethodArgumentRe @Override public boolean supportsParameter(final MethodParameter parameter) { + if (!parameter.hasMethodAnnotation(Authenticated.class)) { + throw new ServerException("MemberIdentifier는 인증된 사용자만 사용 가능합니다. (@Authenticated)"); + } return parameter.getParameterType().equals(String.class) && parameter.hasParameterAnnotation(MemberIdentifier.class); } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/common/resolver/RoadmapSaveArgumentResolver.java b/backend/kirikiri/src/main/java/co/kirikiri/common/resolver/RoadmapSaveArgumentResolver.java index 168abc2f9..fb080e831 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/common/resolver/RoadmapSaveArgumentResolver.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/common/resolver/RoadmapSaveArgumentResolver.java @@ -1,8 +1,8 @@ package co.kirikiri.common.resolver; -import co.kirikiri.exception.BadRequestException; import co.kirikiri.service.dto.roadmap.request.RoadmapNodeSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapSaveRequest; +import co.kirikiri.service.exception.BadRequestException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; diff --git a/backend/kirikiri/src/main/java/co/kirikiri/controller/AuthController.java b/backend/kirikiri/src/main/java/co/kirikiri/controller/AuthController.java index 38f8c8bc4..dfbdd8620 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/controller/AuthController.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/controller/AuthController.java @@ -1,16 +1,21 @@ package co.kirikiri.controller; -import co.kirikiri.service.AuthService; +import co.kirikiri.service.auth.AuthService; +import co.kirikiri.service.auth.NaverOauthService; +import co.kirikiri.service.dto.auth.OauthRedirectResponse; import co.kirikiri.service.dto.auth.request.LoginRequest; import co.kirikiri.service.dto.auth.request.ReissueTokenRequest; import co.kirikiri.service.dto.auth.response.AuthenticationResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import java.util.Map; @RestController @RequestMapping("/auth") @@ -18,6 +23,7 @@ public class AuthController { private final AuthService authService; + private final NaverOauthService naverOauthService; @PostMapping("/login") public ResponseEntity login(@RequestBody @Valid final LoginRequest request) { @@ -31,4 +37,22 @@ public ResponseEntity reissue(@RequestBody @Valid final return ResponseEntity.ok(response); } + @GetMapping("/oauth/naver") + public ResponseEntity loginOauth() { + final OauthRedirectResponse oauthRedirectResponse = naverOauthService.makeOauthUrl(); + return ResponseEntity.ok(oauthRedirectResponse); + } + + @GetMapping("/login/oauth") + public ResponseEntity loginOauth( + @RequestParam(value = "code") final String code, + @RequestParam("state") final String state) { + final Map queryParams = Map.of( + "code", code, + "state", state, + "grant_type", "authorization_code" + ); + final AuthenticationResponse response = naverOauthService.login(queryParams); + return ResponseEntity.ok(response); + } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/controller/GlobalExceptionHandler.java b/backend/kirikiri/src/main/java/co/kirikiri/controller/GlobalExceptionHandler.java index bfa90d07d..181ac9cb0 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/controller/GlobalExceptionHandler.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/controller/GlobalExceptionHandler.java @@ -1,12 +1,12 @@ package co.kirikiri.controller; -import co.kirikiri.exception.AuthenticationException; -import co.kirikiri.exception.BadRequestException; -import co.kirikiri.exception.ConflictException; -import co.kirikiri.exception.ForbiddenException; -import co.kirikiri.exception.NotFoundException; -import co.kirikiri.exception.ServerException; import co.kirikiri.service.dto.ErrorResponse; +import co.kirikiri.service.exception.AuthenticationException; +import co.kirikiri.service.exception.BadRequestException; +import co.kirikiri.service.exception.ConflictException; +import co.kirikiri.service.exception.ForbiddenException; +import co.kirikiri.service.exception.NotFoundException; +import co.kirikiri.service.exception.ServerException; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import java.util.List; import org.slf4j.Logger; diff --git a/backend/kirikiri/src/main/java/co/kirikiri/controller/GoalRoomController.java b/backend/kirikiri/src/main/java/co/kirikiri/controller/GoalRoomController.java index 6123024e3..671c65dd8 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/controller/GoalRoomController.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/controller/GoalRoomController.java @@ -2,8 +2,6 @@ import co.kirikiri.common.interceptor.Authenticated; import co.kirikiri.common.resolver.MemberIdentifier; -import co.kirikiri.service.GoalRoomCreateService; -import co.kirikiri.service.GoalRoomReadService; import co.kirikiri.service.dto.goalroom.GoalRoomMemberSortTypeDto; import co.kirikiri.service.dto.goalroom.request.CheckFeedRequest; import co.kirikiri.service.dto.goalroom.request.GoalRoomCreateRequest; @@ -13,11 +11,13 @@ import co.kirikiri.service.dto.goalroom.response.GoalRoomCheckFeedResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomMemberResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomResponse; -import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodeResponse; +import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodeDetailResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomToDoCheckResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomTodoResponse; import co.kirikiri.service.dto.member.response.MemberGoalRoomForListResponse; import co.kirikiri.service.dto.member.response.MemberGoalRoomResponse; +import co.kirikiri.service.goalroom.GoalRoomCreateService; +import co.kirikiri.service.goalroom.GoalRoomReadService; import jakarta.validation.Valid; import java.net.URI; import java.util.List; @@ -50,16 +50,16 @@ public ResponseEntity create(@RequestBody @Valid final GoalRoomCreateReque return ResponseEntity.created(URI.create("/api/goal-rooms/" + id)).build(); } - @Authenticated @PostMapping("/{goalRoomId}/join") + @Authenticated public ResponseEntity joinGoalRoom(@MemberIdentifier final String identifier, @PathVariable final Long goalRoomId) { goalRoomCreateService.join(identifier, goalRoomId); return ResponseEntity.status(HttpStatus.OK).build(); } - @Authenticated @PostMapping("/{goalRoomId}/todos") + @Authenticated public ResponseEntity addTodo(@RequestBody @Valid final GoalRoomTodoRequest goalRoomTodoRequest, @PathVariable final Long goalRoomId, @MemberIdentifier final String identifier) { @@ -67,8 +67,8 @@ public ResponseEntity addTodo(@RequestBody @Valid final GoalRoomTodoReques return ResponseEntity.created(URI.create("/api/goal-rooms/" + goalRoomId + "/todos/" + id)).build(); } - @Authenticated @PostMapping("/{goalRoomId}/todos/{todoId}") + @Authenticated public ResponseEntity checkTodo(@PathVariable final Long goalRoomId, @PathVariable final Long todoId, @MemberIdentifier final String identifier) { @@ -77,8 +77,8 @@ public ResponseEntity checkTodo(@PathVariable final L return ResponseEntity.ok(checkResponse); } - @Authenticated @PostMapping(value = "/{goalRoomId}/checkFeeds", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) + @Authenticated public ResponseEntity createCheckFeed(@MemberIdentifier final String identifier, @PathVariable("goalRoomId") final Long goalRoomId, @ModelAttribute final CheckFeedRequest checkFeedRequest) { @@ -116,8 +116,8 @@ public ResponseEntity findGoalRoom(@PathVariable("goalRoomId") return ResponseEntity.ok(goalRoomResponse); } - @Authenticated @GetMapping("/{goalRoomId}/members") + @Authenticated public ResponseEntity> findGoalRoomMembers( @PathVariable final Long goalRoomId, @RequestParam(value = "sortCond", required = false) final GoalRoomMemberSortTypeDto sortType) { @@ -126,8 +126,8 @@ public ResponseEntity> findGoalRoomMembers( return ResponseEntity.ok(goalRoomMembers); } - @Authenticated @GetMapping("/{goalRoomId}/me") + @Authenticated public ResponseEntity findMemberGoalRoom( @MemberIdentifier final String identifier, @PathVariable final Long goalRoomId) { final MemberGoalRoomResponse memberGoalRoomResponse = goalRoomReadService.findMemberGoalRoom(identifier, @@ -135,8 +135,8 @@ public ResponseEntity findMemberGoalRoom( return ResponseEntity.ok(memberGoalRoomResponse); } - @Authenticated @GetMapping("/me") + @Authenticated public ResponseEntity> findMemberGoalRoomsByStatus( @MemberIdentifier final String identifier, @RequestParam(value = "statusCond", required = false) final GoalRoomStatusTypeRequest goalRoomStatusTypeRequest) { @@ -150,8 +150,8 @@ public ResponseEntity> findMemberGoalRoomsBy return ResponseEntity.ok(memberGoalRoomForListResponses); } - @Authenticated @GetMapping("/{goalRoomId}/todos") + @Authenticated public ResponseEntity> findAllTodos( @PathVariable final Long goalRoomId, @MemberIdentifier final String identifier) { @@ -160,19 +160,19 @@ public ResponseEntity> findAllTodos( return ResponseEntity.ok(todoResponses); } - @Authenticated @GetMapping("/{goalRoomId}/nodes") - public ResponseEntity> findAllNodes( + @Authenticated + public ResponseEntity> findAllNodes( @PathVariable final Long goalRoomId, @MemberIdentifier final String identifier ) { - final List nodeResponses = goalRoomReadService.findAllGoalRoomNodes(goalRoomId, - identifier); + final List nodeResponses = goalRoomReadService.findAllGoalRoomNodes( + goalRoomId, identifier); return ResponseEntity.ok(nodeResponses); } - @Authenticated @GetMapping("/{goalRoomId}/checkFeeds") + @Authenticated public ResponseEntity> findGoalRoomCheckFeeds( @MemberIdentifier final String identifier, @PathVariable("goalRoomId") final Long goalRoomId) { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/controller/MemberController.java b/backend/kirikiri/src/main/java/co/kirikiri/controller/MemberController.java index ff0089974..84c47dead 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/controller/MemberController.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/controller/MemberController.java @@ -2,12 +2,11 @@ import co.kirikiri.common.interceptor.Authenticated; import co.kirikiri.common.resolver.MemberIdentifier; -import co.kirikiri.service.MemberService; +import co.kirikiri.service.member.MemberService; import co.kirikiri.service.dto.member.request.MemberJoinRequest; import co.kirikiri.service.dto.member.response.MemberInformationForPublicResponse; import co.kirikiri.service.dto.member.response.MemberInformationResponse; import jakarta.validation.Valid; -import java.net.URI; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -16,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.net.URI; @RestController @RequestMapping("/members") diff --git a/backend/kirikiri/src/main/java/co/kirikiri/controller/RoadmapController.java b/backend/kirikiri/src/main/java/co/kirikiri/controller/RoadmapController.java index 531859b09..21abca873 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/controller/RoadmapController.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/controller/RoadmapController.java @@ -2,10 +2,9 @@ import co.kirikiri.common.interceptor.Authenticated; import co.kirikiri.common.resolver.MemberIdentifier; -import co.kirikiri.service.RoadmapCreateService; -import co.kirikiri.service.RoadmapReadService; import co.kirikiri.service.dto.CustomScrollRequest; import co.kirikiri.service.dto.roadmap.RoadmapGoalRoomsOrderTypeDto; +import co.kirikiri.service.dto.roadmap.request.RoadmapCategorySaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapOrderTypeRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapReviewSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapSaveRequest; @@ -16,6 +15,8 @@ import co.kirikiri.service.dto.roadmap.response.RoadmapGoalRoomResponses; import co.kirikiri.service.dto.roadmap.response.RoadmapResponse; import co.kirikiri.service.dto.roadmap.response.RoadmapReviewResponse; +import co.kirikiri.service.roadmap.RoadmapCreateService; +import co.kirikiri.service.roadmap.RoadmapReadService; import jakarta.validation.Valid; import java.net.URI; import java.util.List; @@ -41,14 +42,15 @@ public class RoadmapController { private final RoadmapCreateService roadmapCreateService; private final RoadmapReadService roadmapReadService; - @Authenticated @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @Authenticated public ResponseEntity create(final RoadmapSaveRequest request, @MemberIdentifier final String identifier) { final Long roadmapId = roadmapCreateService.create(request, identifier); return ResponseEntity.created(URI.create("/api/roadmaps/" + roadmapId)).build(); } @PostMapping("/{roadmapId}/reviews") + @Authenticated public ResponseEntity createReview( @PathVariable("roadmapId") final Long roadmapId, @MemberIdentifier final String identifier, @@ -91,6 +93,13 @@ public ResponseEntity> findAllRoadmapCategories() return ResponseEntity.ok(roadmapCategoryResponses); } + @PostMapping("/categories") + public ResponseEntity createRoadmapCategory( + @RequestBody @Valid final RoadmapCategorySaveRequest roadmapCategorySaveRequest) { + roadmapCreateService.createRoadmapCategory(roadmapCategorySaveRequest); + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + @GetMapping("/me") @Authenticated public ResponseEntity findAllMyRoadmaps(@MemberIdentifier final String identifier, diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/BaseCreatedTimeEntity.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/BaseCreatedTimeEntity.java index 2a32dad7f..383bd9634 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/BaseCreatedTimeEntity.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/BaseCreatedTimeEntity.java @@ -1,28 +1,23 @@ package co.kirikiri.domain; import jakarta.persistence.Column; -import jakarta.persistence.EntityListeners; import jakarta.persistence.MappedSuperclass; import jakarta.persistence.PrePersist; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import org.springframework.data.annotation.CreatedDate; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; @MappedSuperclass -@EntityListeners(AuditingEntityListener.class) public class BaseCreatedTimeEntity extends BaseEntity { - private static final String TIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSSSS"; + protected static final String TIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSSSS"; - @CreatedDate @Column(nullable = false, updatable = false) protected LocalDateTime createdAt; @PrePersist - public void prePersist() { + protected void prePersist() { final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TIME_FORMAT); - final String formattedTime = createdAt.format(formatter); + final String formattedTime = LocalDateTime.now().format(formatter); createdAt = LocalDateTime.parse(formattedTime, formatter); } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/BaseEntity.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/BaseEntity.java index e9cb9a77d..a66368c62 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/BaseEntity.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/BaseEntity.java @@ -1,15 +1,12 @@ package co.kirikiri.domain; -import jakarta.persistence.EntityListeners; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.MappedSuperclass; import java.util.Objects; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; @MappedSuperclass -@EntityListeners(AuditingEntityListener.class) public class BaseEntity { @Id diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/BaseUpdatedTimeEntity.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/BaseUpdatedTimeEntity.java index ac22c2f3d..7434bf778 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/BaseUpdatedTimeEntity.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/BaseUpdatedTimeEntity.java @@ -1,17 +1,29 @@ package co.kirikiri.domain; import jakarta.persistence.Column; -import jakarta.persistence.EntityListeners; import jakarta.persistence.MappedSuperclass; +import jakarta.persistence.PreUpdate; import java.time.LocalDateTime; -import org.springframework.data.annotation.LastModifiedDate; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import java.time.format.DateTimeFormatter; @MappedSuperclass -@EntityListeners(AuditingEntityListener.class) public class BaseUpdatedTimeEntity extends BaseCreatedTimeEntity { - @LastModifiedDate @Column(nullable = false) private LocalDateTime updatedAt; + + @Override + protected void prePersist() { + final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TIME_FORMAT); + final String formattedTime = LocalDateTime.now().format(formatter); + createdAt = LocalDateTime.parse(formattedTime, formatter); + updatedAt = LocalDateTime.parse(formattedTime, formatter); + } + + @PreUpdate + private void preUpdate() { + final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TIME_FORMAT); + final String formattedTime = LocalDateTime.now().format(formatter); + updatedAt = LocalDateTime.parse(formattedTime, formatter); + } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/ImageContentType.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/ImageContentType.java index 681e49136..9d8a4df07 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/ImageContentType.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/ImageContentType.java @@ -1,6 +1,6 @@ package co.kirikiri.domain; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.exception.ImageExtensionException; import java.util.Arrays; public enum ImageContentType { @@ -21,6 +21,6 @@ public static ImageContentType findImageContentType(final String imageContentTyp return Arrays.stream(values()) .filter(it -> it.extension.equals(imageContentType)) .findAny() - .orElseThrow(() -> new BadRequestException("허용되지 않는 확장자입니다.")); + .orElseThrow(() -> new ImageExtensionException("허용되지 않는 확장자입니다.")); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/auth/EncryptedToken.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/auth/EncryptedToken.java deleted file mode 100644 index 35670fa55..000000000 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/auth/EncryptedToken.java +++ /dev/null @@ -1,57 +0,0 @@ -package co.kirikiri.domain.auth; - -import co.kirikiri.exception.ServerException; -import jakarta.persistence.Column; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Base64; -import java.util.Objects; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Getter -public class EncryptedToken { - - private static final String ALGORITHM = "SHA-256"; - - @Column(name = "token", nullable = false) - private String value; - - public EncryptedToken(final String rawToken) { - this.value = encrypt(rawToken); - } - - private String encrypt(final String rawToken) { - final MessageDigest messageDigest = findMessageDigest(); - messageDigest.update(rawToken.getBytes()); - final byte[] hashedToken = messageDigest.digest(); - return Base64.getEncoder().encodeToString(hashedToken); - } - - private MessageDigest findMessageDigest() { - try { - return MessageDigest.getInstance(ALGORITHM); - } catch (final NoSuchAlgorithmException exception) { - throw new ServerException(exception.getMessage()); - } - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final EncryptedToken that = (EncryptedToken) o; - return Objects.equals(value, that.value); - } - - @Override - public int hashCode() { - return Objects.hash(value); - } -} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/auth/RefreshToken.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/auth/RefreshToken.java deleted file mode 100644 index 537187f9b..000000000 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/auth/RefreshToken.java +++ /dev/null @@ -1,55 +0,0 @@ -package co.kirikiri.domain.auth; - -import co.kirikiri.domain.member.Member; -import jakarta.persistence.Column; -import jakarta.persistence.Embedded; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import java.time.LocalDateTime; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -@Entity -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class RefreshToken { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Embedded - private EncryptedToken token; - - @Column(nullable = false) - private LocalDateTime expiredAt; - - @Column(nullable = false) - private final boolean isRevoked = false; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "member_id", nullable = false) - private Member member; - - public RefreshToken(final EncryptedToken token, final LocalDateTime expiredAt, final Member member) { - this.token = token; - this.expiredAt = expiredAt; - this.member = member; - } - - public boolean isExpired() { - return expiredAt.isBefore(LocalDateTime.now()); - } - - public EncryptedToken getToken() { - return token; - } - - public Member getMember() { - return member; - } -} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/exception/DomainException.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/exception/DomainException.java new file mode 100644 index 000000000..bf1161db4 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/exception/DomainException.java @@ -0,0 +1,8 @@ +package co.kirikiri.domain.exception; + +public class DomainException extends RuntimeException { + + public DomainException(final String message) { + super(message); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/exception/ImageExtensionException.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/exception/ImageExtensionException.java new file mode 100644 index 000000000..3a8e84f67 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/exception/ImageExtensionException.java @@ -0,0 +1,8 @@ +package co.kirikiri.domain.exception; + +public class ImageExtensionException extends DomainException { + + public ImageExtensionException(final String message) { + super(message); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/exception/UnexpectedDomainException.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/exception/UnexpectedDomainException.java new file mode 100644 index 000000000..50735c79e --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/exception/UnexpectedDomainException.java @@ -0,0 +1,8 @@ +package co.kirikiri.domain.exception; + +public class UnexpectedDomainException extends DomainException { + + public UnexpectedDomainException(final String message) { + super(message); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/BaseGoalRoomMember.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/BaseGoalRoomMember.java index 603c6a6b5..e034bc6d6 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/BaseGoalRoomMember.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/BaseGoalRoomMember.java @@ -3,25 +3,26 @@ import co.kirikiri.domain.BaseEntity; import co.kirikiri.domain.member.Member; import com.querydsl.core.annotations.QueryInit; -import jakarta.persistence.EntityListeners; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.MappedSuperclass; +import jakarta.persistence.PrePersist; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.Objects; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.springframework.data.annotation.CreatedDate; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; @MappedSuperclass -@EntityListeners(AuditingEntityListener.class) @NoArgsConstructor(access = AccessLevel.PROTECTED) public abstract class BaseGoalRoomMember extends BaseEntity { + protected static final String TIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSSSS"; + @Enumerated(value = EnumType.STRING) protected GoalRoomRole role; @@ -52,6 +53,13 @@ public BaseGoalRoomMember(final Long id, final GoalRoomRole role, final LocalDat this.member = member; } + @PrePersist + private void prePersist() { + final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TIME_FORMAT); + final String formattedTime = LocalDateTime.now().format(formatter); + joinedAt = LocalDateTime.parse(formattedTime, formatter); + } + public boolean isLeader() { return role == GoalRoomRole.LEADER; } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/CheckFeed.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/CheckFeed.java index 15c696158..f77f8fe01 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/CheckFeed.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/CheckFeed.java @@ -10,9 +10,9 @@ import jakarta.persistence.FetchType; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; -import java.time.LocalDateTime; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import java.time.LocalDateTime; @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoom.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoom.java index 2921e0a7c..e10f05f82 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoom.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoom.java @@ -1,11 +1,11 @@ package co.kirikiri.domain.goalroom; import co.kirikiri.domain.BaseUpdatedTimeEntity; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import co.kirikiri.domain.goalroom.vo.GoalRoomName; import co.kirikiri.domain.goalroom.vo.LimitedMemberCount; import co.kirikiri.domain.member.Member; import co.kirikiri.domain.roadmap.RoadmapContent; -import co.kirikiri.exception.BadRequestException; import jakarta.persistence.Column; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; @@ -75,13 +75,13 @@ public GoalRoom(final Long id, final GoalRoomName name, final LimitedMemberCount private void updateLeader(final Member member) { final GoalRoomPendingMember leader = new GoalRoomPendingMember(GoalRoomRole.LEADER, member); - leader.updateGoalRoom(this); + leader.initGoalRoom(this); goalRoomPendingMembers.add(leader); } public void join(final Member member) { final GoalRoomPendingMember newMember = new GoalRoomPendingMember(GoalRoomRole.FOLLOWER, member); - newMember.updateGoalRoom(this); + newMember.initGoalRoom(this); validateJoinGoalRoom(newMember); goalRoomPendingMembers.add(newMember); } @@ -94,19 +94,19 @@ private void validateJoinGoalRoom(final GoalRoomPendingMember member) { private void validateMemberCount() { if (getCurrentMemberCount() >= limitedMemberCount.getValue()) { - throw new BadRequestException("제한 인원이 꽉 찬 골룸에는 참여할 수 없습니다."); + throw new GoalRoomException("제한 인원이 꽉 찬 골룸에는 참여할 수 없습니다."); } } private void validateStatus() { if (status != GoalRoomStatus.RECRUITING) { - throw new BadRequestException("모집 중이지 않은 골룸에는 참여할 수 없습니다."); + throw new GoalRoomException("모집 중이지 않은 골룸에는 참여할 수 없습니다."); } } private void validateAlreadyParticipated(final GoalRoomPendingMember member) { if (goalRoomPendingMembers.containGoalRoomPendingMember(member)) { - throw new BadRequestException("이미 참여한 골룸에는 참여할 수 없습니다."); + throw new GoalRoomException("이미 참여한 골룸에는 참여할 수 없습니다."); } } @@ -143,7 +143,7 @@ public void addAllGoalRoomRoadmapNodes(final GoalRoomRoadmapNodes goalRoomRoadma private void checkTotalSize(final int totalSize) { if (totalSize > roadmapContent.nodesSize()) { - throw new BadRequestException("로드맵의 노드 수보다 골룸의 노드 수가 큽니다."); + throw new GoalRoomException("로드맵의 노드 수보다 골룸의 노드 수가 큽니다."); } } @@ -214,7 +214,7 @@ public boolean cannotStart() { private GoalRoomPendingMember findGoalRoomPendingMemberByMember(final Member member) { return goalRoomPendingMembers.findByMember(member) - .orElseThrow(() -> new BadRequestException("골룸에 참여한 사용자가 아닙니다. memberId = " + member.getId())); + .orElseThrow(() -> new GoalRoomException("골룸에 참여한 사용자가 아닙니다. memberId = " + member.getId())); } private void changeRoleIfLeaderLeave(final GoalRoomPendingMembers goalRoomPendingMembers, @@ -227,7 +227,7 @@ private void changeRoleIfLeaderLeave(final GoalRoomPendingMembers goalRoomPendin private GoalRoomMember findGoalRoomMemberByMember(final Member member) { return goalRoomMembers.findByMember(member) - .orElseThrow(() -> new BadRequestException("골룸에 참여한 사용자가 아닙니다. memberId = " + member.getId())); + .orElseThrow(() -> new GoalRoomException("골룸에 참여한 사용자가 아닙니다. memberId = " + member.getId())); } private void changeRoleIfLeaderLeave(final GoalRoomMembers goalRoomMembers, diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomMember.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomMember.java index 964584840..d99074fcd 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomMember.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomMember.java @@ -3,9 +3,9 @@ import co.kirikiri.domain.member.Member; import jakarta.persistence.Column; import jakarta.persistence.Entity; -import java.time.LocalDateTime; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import java.time.LocalDateTime; @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomMembers.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomMembers.java index 45525d93c..f05d9d369 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomMembers.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomMembers.java @@ -1,7 +1,7 @@ package co.kirikiri.domain.goalroom; +import co.kirikiri.domain.exception.UnexpectedDomainException; import co.kirikiri.domain.member.Member; -import co.kirikiri.exception.NotFoundException; import jakarta.persistence.CascadeType; import jakarta.persistence.Embeddable; import jakarta.persistence.FetchType; @@ -12,6 +12,7 @@ import java.util.Optional; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.hibernate.annotations.BatchSize; @Embeddable @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -19,6 +20,7 @@ public class GoalRoomMembers { private static final int MIN_SIZE_TO_FIND_NEXT_LEADER = 1; + @BatchSize(size = 20) @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "goalRoom") @@ -65,7 +67,7 @@ public Member findGoalRoomLeader() { .filter(GoalRoomMember::isLeader) .findFirst() .map(GoalRoomMember::getMember) - .orElseThrow(() -> new NotFoundException("골룸의 리더가 없습니다.")); + .orElseThrow(() -> new UnexpectedDomainException("골룸의 리더가 없습니다.")); } public int size() { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomPendingMember.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomPendingMember.java index f23b7dc6d..ab671fb74 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomPendingMember.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomPendingMember.java @@ -1,7 +1,6 @@ package co.kirikiri.domain.goalroom; import co.kirikiri.domain.member.Member; -import co.kirikiri.exception.ServerException; import jakarta.persistence.Entity; import java.time.LocalDateTime; import lombok.AccessLevel; @@ -29,14 +28,9 @@ public GoalRoomPendingMember(final Long id, final GoalRoomRole role, final Local super(id, role, joinedAt, goalRoom, member); } - public void updateGoalRoom(final GoalRoom goalRoom) { + public void initGoalRoom(final GoalRoom goalRoom) { if (this.goalRoom == null) { this.goalRoom = goalRoom; - return; } - if (this.goalRoom.equals(goalRoom)) { - return; - } - throw new ServerException("골룸을 변경할 수 없습니다."); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomPendingMembers.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomPendingMembers.java index 4ce31d0b3..6cd84a26c 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomPendingMembers.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomPendingMembers.java @@ -1,7 +1,7 @@ package co.kirikiri.domain.goalroom; +import co.kirikiri.domain.exception.UnexpectedDomainException; import co.kirikiri.domain.member.Member; -import co.kirikiri.exception.NotFoundException; import jakarta.persistence.CascadeType; import jakarta.persistence.Embeddable; import jakarta.persistence.FetchType; @@ -12,6 +12,7 @@ import java.util.Optional; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.hibernate.annotations.BatchSize; @Embeddable @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -19,6 +20,7 @@ public class GoalRoomPendingMembers { private static final int MIN_SIZE_TO_FIND_NEXT_LEADER = 1; + @BatchSize(size = 20) @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "goalRoom") @@ -51,7 +53,7 @@ public Member findGoalRoomLeader() { .filter(GoalRoomPendingMember::isLeader) .findFirst() .map(GoalRoomPendingMember::getMember) - .orElseThrow(() -> new NotFoundException("골룸의 리더가 없습니다.")); + .orElseThrow(() -> new UnexpectedDomainException("골룸의 리더가 없습니다.")); } public boolean isNotLeader(final Member member) { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNode.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNode.java index 72fd1a89b..a8ec84112 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNode.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNode.java @@ -1,9 +1,9 @@ package co.kirikiri.domain.goalroom; import co.kirikiri.domain.BaseEntity; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import co.kirikiri.domain.goalroom.vo.Period; import co.kirikiri.domain.roadmap.RoadmapNode; -import co.kirikiri.exception.BadRequestException; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -48,13 +48,13 @@ private void validate(final Period period, final Integer checkCount) { private void validateCheckCountPositive(final Integer checkCount) { if (checkCount < MIN_CHECK_COUNT) { - throw new BadRequestException("골룸 노드의 인증 횟수는 0보다 커야합니다."); + throw new GoalRoomException("골룸 노드의 인증 횟수는 0보다 커야합니다."); } } private void validateCheckCountWithDaysBetween(final Period period, final int checkCount) { if (checkCount > period.getDayCount()) { - throw new BadRequestException("골룸 노드의 인증 횟수가 설정 기간보다 클 수 없습니다."); + throw new GoalRoomException("골룸 노드의 인증 횟수가 설정 기간보다 클 수 없습니다."); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNodes.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNodes.java index 0e452b625..83401f80d 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNodes.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNodes.java @@ -1,7 +1,6 @@ package co.kirikiri.domain.goalroom; -import co.kirikiri.exception.BadRequestException; -import co.kirikiri.exception.NotFoundException; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import jakarta.persistence.CascadeType; import jakarta.persistence.Embeddable; import jakarta.persistence.FetchType; @@ -42,7 +41,7 @@ public void validatePeriodNoOverlap(final List nodes) { .filter(index -> nodes.get(index).isEndDateEqualOrAfterOtherStartDate(nodes.get(index + 1))) .findAny() .ifPresent(it -> { - throw new BadRequestException("골룸 노드의 기간이 겹칠 수 없습니다."); + throw new GoalRoomException("골룸 노드의 기간이 겹칠 수 없습니다."); }); } @@ -57,14 +56,14 @@ public void addAll(final GoalRoomRoadmapNodes goalRoomRoadmapNodes) { public LocalDate getGoalRoomStartDate() { return values.stream() .min(Comparator.comparing(GoalRoomRoadmapNode::getStartDate)) - .orElseThrow(() -> new NotFoundException("골룸에 노드가 존재하지 않습니다.")) + .orElseThrow(() -> new GoalRoomException("골룸에 노드가 존재하지 않습니다.")) .getStartDate(); } public LocalDate getGoalRoomEndDate() { return values.stream() .max(Comparator.comparing(GoalRoomRoadmapNode::getEndDate)) - .orElseThrow(() -> new NotFoundException("골룸에 노드가 존재하지 않습니다.")) + .orElseThrow(() -> new GoalRoomException("골룸에 노드가 존재하지 않습니다.")) .getEndDate(); } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomToDo.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomToDo.java index c8852ff13..3f84a708b 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomToDo.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomToDo.java @@ -5,9 +5,9 @@ import co.kirikiri.domain.goalroom.vo.Period; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; -import java.time.LocalDate; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import java.time.LocalDate; @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomToDos.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomToDos.java index e939c0536..1a1106bba 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomToDos.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/GoalRoomToDos.java @@ -5,11 +5,11 @@ import jakarta.persistence.FetchType; import jakarta.persistence.JoinColumn; import jakarta.persistence.OneToMany; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import java.util.ArrayList; import java.util.List; import java.util.Optional; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; @Embeddable @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/exception/GoalRoomException.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/exception/GoalRoomException.java new file mode 100644 index 000000000..514495361 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/exception/GoalRoomException.java @@ -0,0 +1,10 @@ +package co.kirikiri.domain.goalroom.exception; + +import co.kirikiri.domain.exception.DomainException; + +public class GoalRoomException extends DomainException { + + public GoalRoomException(final String message) { + super(message); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/GoalRoomName.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/GoalRoomName.java index 1e6922195..8893b12de 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/GoalRoomName.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/GoalRoomName.java @@ -1,6 +1,6 @@ package co.kirikiri.domain.goalroom.vo; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import lombok.AccessLevel; @@ -23,7 +23,7 @@ public GoalRoomName(final String value) { private void validate(final String value) { if (value.length() < MIN_LENGTH || value.length() > MAX_LENGTH) { - throw new BadRequestException("골룸 이름의 길이가 적절하지 않습니다."); + throw new GoalRoomException("골룸 이름의 길이가 적절하지 않습니다."); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/GoalRoomTodoContent.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/GoalRoomTodoContent.java index 485e07e70..4b5096307 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/GoalRoomTodoContent.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/GoalRoomTodoContent.java @@ -1,6 +1,6 @@ package co.kirikiri.domain.goalroom.vo; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import lombok.AccessLevel; @@ -23,7 +23,7 @@ public GoalRoomTodoContent(final String value) { private void validate(final String value) { if (value.length() < MIN_LENGTH || value.length() > MAX_LENGTH) { - throw new BadRequestException("투두 컨텐츠의 길이가 적절하지 않습니다."); + throw new GoalRoomException("투두 컨텐츠의 길이가 적절하지 않습니다."); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/LimitedMemberCount.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/LimitedMemberCount.java index 2c9e74844..9160fb278 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/LimitedMemberCount.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/LimitedMemberCount.java @@ -1,6 +1,6 @@ package co.kirikiri.domain.goalroom.vo; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import lombok.AccessLevel; @@ -23,7 +23,7 @@ public LimitedMemberCount(final int value) { private void validate(final int value) { if (value < MIN || value > MAX) { - throw new BadRequestException("제한 인원 수가 적절하지 않습니다."); + throw new GoalRoomException("제한 인원 수가 적절하지 않습니다."); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/Period.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/Period.java index 73370f8ba..881202f46 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/Period.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/goalroom/vo/Period.java @@ -1,6 +1,6 @@ package co.kirikiri.domain.goalroom.vo; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import java.time.LocalDate; @@ -31,13 +31,13 @@ private void validate(final LocalDate startDate, final LocalDate endDate) { private void validateStartDateAfterNow(final LocalDate startDate) { if (startDate.isBefore(LocalDate.now())) { - throw new BadRequestException("시작일은 오늘보다 전일 수 없습니다."); + throw new GoalRoomException("시작일은 오늘보다 전일 수 없습니다."); } } private void validateStartDateBeforeOrEqualEndDate(final LocalDate startDate, final LocalDate endDate) { if (startDate.isAfter(endDate)) { - throw new BadRequestException("시작일은 종료일보다 후일 수 없습니다."); + throw new GoalRoomException("시작일은 종료일보다 후일 수 없습니다."); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/EncryptedPassword.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/EncryptedPassword.java index 70e5cfbef..3dfb27793 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/EncryptedPassword.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/EncryptedPassword.java @@ -1,8 +1,7 @@ package co.kirikiri.domain.member; +import co.kirikiri.domain.exception.UnexpectedDomainException; import co.kirikiri.domain.member.vo.Password; -import co.kirikiri.exception.ServerException; -import jakarta.persistence.Column; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; @@ -16,10 +15,7 @@ public class EncryptedPassword { private static final String ALGORITHM = "SHA-256"; - @Column(nullable = false) private String password; - - @Column(nullable = false) private String salt; public EncryptedPassword(final Password unencryptedPassword) { @@ -46,7 +42,7 @@ private MessageDigest findMessageDigest() { try { return MessageDigest.getInstance(ALGORITHM); } catch (final NoSuchAlgorithmException exception) { - throw new ServerException(exception.getMessage()); + throw new UnexpectedDomainException(exception.getMessage()); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/Gender.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/Gender.java index 40827a664..238cb7cd5 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/Gender.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/Gender.java @@ -4,4 +4,5 @@ public enum Gender { MALE, FEMALE, + UNDEFINED } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/Member.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/Member.java index 222005d1d..c5c1a8e7a 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/Member.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/Member.java @@ -20,6 +20,8 @@ public class Member extends BaseUpdatedTimeEntity { @Embedded private Identifier identifier; + private String oauthId; + @Embedded private EncryptedPassword encryptedPassword; @@ -40,13 +42,19 @@ public class Member extends BaseUpdatedTimeEntity { public Member(final Identifier identifier, final EncryptedPassword encryptedPassword, final Nickname nickname, final MemberImage image, final MemberProfile memberProfile) { - this(null, identifier, encryptedPassword, nickname, image, memberProfile); + this(null, identifier, null, encryptedPassword, nickname, image, memberProfile); + } + + public Member(final Identifier identifier, final String oauthId, final Nickname nickname, + final MemberImage image, final MemberProfile memberProfile) { + this(null, identifier, oauthId, null, nickname, image, memberProfile); } - public Member(final Long id, final Identifier identifier, final EncryptedPassword encryptedPassword, + public Member(final Long id, final Identifier identifier, final String oauthId, final EncryptedPassword encryptedPassword, final Nickname nickname, final MemberImage image, final MemberProfile memberProfile) { this.id = id; this.identifier = identifier; + this.oauthId = oauthId; this.encryptedPassword = encryptedPassword; this.nickname = nickname; this.image = image; diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/MemberProfile.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/MemberProfile.java index afe56e7d7..0014aa38c 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/MemberProfile.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/MemberProfile.java @@ -5,7 +5,6 @@ import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; -import java.time.LocalDate; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -17,27 +16,19 @@ public class MemberProfile extends BaseUpdatedTimeEntity { @Column(length = 10, nullable = false) private Gender gender; - @Column(nullable = false) - private LocalDate birthday; + @Column(length = 100, nullable = false) + private String email; - @Column(length = 20, nullable = false) - private String phoneNumber; - - public MemberProfile(final Gender gender, final LocalDate birthday, final String phoneNumber) { + public MemberProfile(final Gender gender, final String email) { this.gender = gender; - this.birthday = birthday; - this.phoneNumber = phoneNumber; + this.email = email; } public Gender getGender() { return gender; } - public LocalDate getBirthday() { - return birthday; - } - - public String getPhoneNumber() { - return phoneNumber; + public String getEmail() { + return email; } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/exception/MemberException.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/exception/MemberException.java new file mode 100644 index 000000000..44f6fa57b --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/exception/MemberException.java @@ -0,0 +1,10 @@ +package co.kirikiri.domain.member.exception; + +import co.kirikiri.domain.exception.DomainException; + +public class MemberException extends DomainException { + + public MemberException(final String message) { + super(message); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/vo/Identifier.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/vo/Identifier.java index 394509bdc..f3ee6e3c1 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/vo/Identifier.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/vo/Identifier.java @@ -1,6 +1,6 @@ package co.kirikiri.domain.member.vo; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.member.exception.MemberException; import jakarta.persistence.Column; import java.util.Objects; import lombok.AccessLevel; @@ -10,8 +10,7 @@ public class Identifier { private static final int MIN_LENGTH = 4; - private static final int MAX_LENGTH = 20; - private static final String REGEX = "^[a-z0-9]+$"; + private static final int MAX_LENGTH = 40; @Column(name = "identifier", length = 50, unique = true, nullable = false) private String value; @@ -22,8 +21,8 @@ public Identifier(final String value) { } private void validate(final String value) { - if (isNotValidLength(value) || isNotValidPattern(value)) { - throw new BadRequestException("제약 조건에 맞지 않는 아이디입니다."); + if (isNotValidLength(value)) { + throw new MemberException("제약 조건에 맞지 않는 아이디입니다."); } } @@ -31,10 +30,6 @@ private boolean isNotValidLength(final String value) { return value.length() < MIN_LENGTH || value.length() > MAX_LENGTH; } - private boolean isNotValidPattern(final String value) { - return !value.matches(REGEX); - } - @Override public boolean equals(final Object o) { if (this == o) { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/vo/Nickname.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/vo/Nickname.java index db51fdedd..3032a52a4 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/vo/Nickname.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/vo/Nickname.java @@ -1,6 +1,6 @@ package co.kirikiri.domain.member.vo; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.member.exception.MemberException; import jakarta.persistence.Column; import java.util.Objects; import lombok.NoArgsConstructor; @@ -9,9 +9,9 @@ public class Nickname { private static final int MIN_LENGTH = 2; - private static final int MAX_LENGTH = 8; + private static final int MAX_LENGTH = 20; - @Column(name = "nickname", length = 15, unique = true, nullable = false) + @Column(name = "nickname", length = 30, unique = true, nullable = false) private String value; public Nickname(final String value) { @@ -21,7 +21,7 @@ public Nickname(final String value) { private void validate(final String value) { if (isNotValidLength(value)) { - throw new BadRequestException("제약 조건에 맞지 않는 닉네임입니다."); + throw new MemberException("제약 조건에 맞지 않는 닉네임입니다."); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/vo/Password.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/vo/Password.java index 54c63c621..10db63859 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/member/vo/Password.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/member/vo/Password.java @@ -1,6 +1,6 @@ package co.kirikiri.domain.member.vo; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.member.exception.MemberException; import lombok.Getter; @Getter @@ -19,7 +19,7 @@ public Password(final String value) { private void validate(final String value) { if (isNotValidLength(value) || isNotValidPattern(value)) { - throw new BadRequestException("제약 조건에 맞지 않는 비밀번호입니다."); + throw new MemberException("제약 조건에 맞지 않는 비밀번호입니다."); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/Roadmap.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/Roadmap.java index 95b6fbc7f..6c509d470 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/Roadmap.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/Roadmap.java @@ -2,7 +2,7 @@ import co.kirikiri.domain.BaseCreatedTimeEntity; import co.kirikiri.domain.member.Member; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import jakarta.persistence.Column; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; @@ -101,7 +101,7 @@ private void validate(final String title, final String introduction, final int r private void validateTitleLength(final String title) { if (title.length() < TITLE_MIN_LENGTH || title.length() > TITLE_MAX_LENGTH) { - throw new BadRequestException( + throw new RoadmapException( String.format("로드맵 제목의 길이는 최소 %d글자, 최대 %d글자입니다.", TITLE_MIN_LENGTH, TITLE_MAX_LENGTH) ); } @@ -109,7 +109,7 @@ private void validateTitleLength(final String title) { private void validateIntroductionLength(final String introduction) { if (introduction.length() < INTRODUCTION_MIN_LENGTH || introduction.length() > INTRODUCTION_MAX_LENGTH) { - throw new BadRequestException( + throw new RoadmapException( String.format("로드맵 소개글의 길이는 최소 %d글자, 최대 %d글자입니다.", INTRODUCTION_MIN_LENGTH, INTRODUCTION_MAX_LENGTH ) @@ -119,7 +119,7 @@ private void validateIntroductionLength(final String introduction) { private void validateRequiredPeriod(final int requiredPeriod) { if (requiredPeriod < REQUIRED_MIN_PERIOD || requiredPeriod > REQUIRED_MAX_PERIOD) { - throw new BadRequestException( + throw new RoadmapException( String.format("로드맵 추천 소요 기간은 최소 %d일, 최대 %d일입니다.", REQUIRED_MIN_PERIOD, REQUIRED_MAX_PERIOD) ); } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapCategory.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapCategory.java index a983dce16..521839855 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapCategory.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapCategory.java @@ -1,6 +1,7 @@ package co.kirikiri.domain.roadmap; import co.kirikiri.domain.BaseEntity; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import jakarta.persistence.Column; import jakarta.persistence.Entity; import lombok.AccessLevel; @@ -12,6 +13,9 @@ @Getter public class RoadmapCategory extends BaseEntity { + private static final int MIN_NAME_LENGTH = 1; + private static final int MAX_NAME_LENGTH = 10; + @Column(length = 15, nullable = false) private String name; @@ -21,7 +25,15 @@ public RoadmapCategory(final String name) { public RoadmapCategory(final Long id, final String name) { super.id = id; - this.name = name; + final String trimmed = name.trim(); + validateNameLength(trimmed); + this.name = trimmed; + } + + private void validateNameLength(final String name) { + if (name.length() < MIN_NAME_LENGTH || name.length() > MAX_NAME_LENGTH) { + throw new RoadmapException("카테고리 이름은 1자 이상 10자 이하입니다."); + } } public String getName() { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapContent.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapContent.java index 65d649d13..e4d918267 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapContent.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapContent.java @@ -1,7 +1,7 @@ package co.kirikiri.domain.roadmap; import co.kirikiri.domain.BaseUpdatedTimeEntity; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import jakarta.persistence.Column; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; @@ -49,7 +49,7 @@ private void validate(final String content) { private void validateContentLength(final String content) { if (content.length() > CONTENT_MAX_LENGTH) { - throw new BadRequestException(String.format("로드맵 본문의 길이는 최대 %d글자입니다.", CONTENT_MAX_LENGTH)); + throw new RoadmapException(String.format("로드맵 본문의 길이는 최대 %d글자입니다.", CONTENT_MAX_LENGTH)); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapContents.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapContents.java index 7266f63e4..4677640f2 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapContents.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapContents.java @@ -5,11 +5,11 @@ import jakarta.persistence.Embeddable; import jakarta.persistence.FetchType; import jakarta.persistence.OneToMany; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import java.util.ArrayList; import java.util.List; import java.util.Optional; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; @Embeddable @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapNode.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapNode.java index 67f00b154..dcf5bfbdf 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapNode.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapNode.java @@ -1,7 +1,7 @@ package co.kirikiri.domain.roadmap; import co.kirikiri.domain.BaseEntity; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import jakarta.persistence.Column; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; @@ -51,14 +51,14 @@ private void validate(final String title, final String content) { private void validateTitleLength(final String title) { if (title.length() < TITLE_MIN_LENGTH || title.length() > TITLE_MAX_LENGTH) { - throw new BadRequestException( + throw new RoadmapException( String.format("로드맵 노드의 제목의 길이는 최소 %d글자, 최대 %d글자입니다.", TITLE_MIN_LENGTH, TITLE_MAX_LENGTH)); } } private void validateContentLength(final String content) { if (content.length() < CONTENT_MIN_LENGTH || content.length() > CONTENT_MAX_LENGTH) { - throw new BadRequestException( + throw new RoadmapException( String.format("로드맵 노드의 설명의 길이는 최소 %d글자, 최대 %d글자입니다.", CONTENT_MIN_LENGTH, CONTENT_MAX_LENGTH)); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapNodeImages.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapNodeImages.java index 160eb73b6..8d33922dc 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapNodeImages.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapNodeImages.java @@ -1,6 +1,6 @@ package co.kirikiri.domain.roadmap; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import jakarta.persistence.CascadeType; import jakarta.persistence.Embeddable; import jakarta.persistence.FetchType; @@ -27,7 +27,7 @@ public RoadmapNodeImages(final List images) { private void validateSize(final List images) { if (images.size() > MAX_SIZE) { - throw new BadRequestException("한 로드맵 노드에 사진은 최대 2개까지 가능합니다."); + throw new RoadmapException("한 로드맵 노드에 사진은 최대 2개까지 가능합니다."); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapNodes.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapNodes.java index bf9af9556..728d15b6f 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapNodes.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapNodes.java @@ -1,6 +1,6 @@ package co.kirikiri.domain.roadmap; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import jakarta.persistence.CascadeType; import jakarta.persistence.Embeddable; import jakarta.persistence.FetchType; @@ -32,7 +32,7 @@ private void validateTitleDistinct(final List roadmapNodes) { .collect(Collectors.toSet()) .size(); if (roadmapNodes.size() != distinctNameCount) { - throw new BadRequestException("한 로드맵에 같은 이름의 노드가 존재할 수 없습니다."); + throw new RoadmapException("한 로드맵에 같은 이름의 노드가 존재할 수 없습니다."); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapReview.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapReview.java index f38b30b25..1b36d1f92 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapReview.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapReview.java @@ -2,7 +2,7 @@ import co.kirikiri.domain.BaseUpdatedTimeEntity; import co.kirikiri.domain.member.Member; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -53,13 +53,13 @@ private void validate(final String content, final Double rate) { private void validateContentLength(final String content) { if (content.length() > CONTENT_MAX_LENGTH) { - throw new BadRequestException(String.format("리뷰는 최대 %d글자까지 입력할 수 있습니다.", CONTENT_MAX_LENGTH)); + throw new RoadmapException(String.format("리뷰는 최대 %d글자까지 입력할 수 있습니다.", CONTENT_MAX_LENGTH)); } } private void validateRate(final Double rate) { if (!Pattern.matches(RATE_FORMAT, String.valueOf(rate))) { - throw new BadRequestException(String.format("별점은 %d부터 %d까지 0.%d 단위로 설정할 수 있습니다.", + throw new RoadmapException(String.format("별점은 %d부터 %d까지 0.%d 단위로 설정할 수 있습니다.", MIN_RATE, MAX_RATE, RATE_UNIT)); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapReviews.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapReviews.java index b006fcbcb..706c14b6f 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapReviews.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapReviews.java @@ -4,10 +4,10 @@ import jakarta.persistence.Embeddable; import jakarta.persistence.FetchType; import jakarta.persistence.OneToMany; -import java.util.ArrayList; -import java.util.List; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import java.util.ArrayList; +import java.util.List; @Embeddable @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapTag.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapTag.java index 416be4829..2dcd55fdc 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapTag.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapTag.java @@ -6,6 +6,7 @@ import jakarta.persistence.Entity; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import java.util.Objects; @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -23,6 +24,27 @@ public RoadmapTag(final Long id, final RoadmapTagName name) { this.name = name; } + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + final RoadmapTag that = (RoadmapTag) o; + return Objects.equals(getId(), that.getId()) && Objects.equals(getName(), that.getName()); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), getId(), getName()); + } + + @Override public Long getId() { return id; } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapTags.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapTags.java index 8fdbdb5be..763c920cb 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapTags.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/RoadmapTags.java @@ -1,7 +1,7 @@ package co.kirikiri.domain.roadmap; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import co.kirikiri.domain.roadmap.vo.RoadmapTagName; -import co.kirikiri.exception.BadRequestException; import jakarta.persistence.CascadeType; import jakarta.persistence.Embeddable; import jakarta.persistence.FetchType; @@ -13,6 +13,7 @@ import java.util.stream.Collectors; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.hibernate.annotations.BatchSize; @Embeddable @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -24,6 +25,7 @@ public class RoadmapTags { cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, orphanRemoval = true) @JoinColumn(name = "roadmap_id", updatable = false, nullable = false) + @BatchSize(size = 20) private final Set values = new HashSet<>(); public RoadmapTags(final List roadmapTags) { @@ -38,7 +40,7 @@ private void validate(final List roadmapTags) { private void validateCount(final List roadmapTags) { if (roadmapTags.size() > MAX_COUNT) { - throw new BadRequestException( + throw new RoadmapException( String.format("태그의 개수는 최대 %d개까지 가능합니다.", MAX_COUNT)); } } @@ -48,7 +50,7 @@ private void validateDuplicatedName(final List roadmapTags) { .map(RoadmapTag::getName) .collect(Collectors.toSet()); if (roadmapTags.size() != nonDuplicatedNames.size()) { - throw new BadRequestException("태그 이름은 중복될 수 없습니다."); + throw new RoadmapException("태그 이름은 중복될 수 없습니다."); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/exception/RoadmapException.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/exception/RoadmapException.java new file mode 100644 index 000000000..86610f60b --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/exception/RoadmapException.java @@ -0,0 +1,10 @@ +package co.kirikiri.domain.roadmap.exception; + +import co.kirikiri.domain.exception.DomainException; + +public class RoadmapException extends DomainException { + + public RoadmapException(final String message) { + super(message); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/vo/RoadmapTagName.java b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/vo/RoadmapTagName.java index d4929c78f..711208319 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/vo/RoadmapTagName.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/domain/roadmap/vo/RoadmapTagName.java @@ -1,6 +1,6 @@ package co.kirikiri.domain.roadmap.vo; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import jakarta.persistence.Column; import java.util.Objects; import lombok.AccessLevel; @@ -23,7 +23,7 @@ public RoadmapTagName(final String value) { private void validate(final String name) { if (name.length() < MIN_LENGTH || name.length() > MAX_LENGTH) { - throw new BadRequestException( + throw new RoadmapException( String.format("태그 이름은 최소 %d자부터 최대 %d자까지 가능합니다.", MIN_LENGTH, MAX_LENGTH)); } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/infra/AmazonS3FileService.java b/backend/kirikiri/src/main/java/co/kirikiri/infra/AmazonS3FileService.java index 2516a0dba..429359a26 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/infra/AmazonS3FileService.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/infra/AmazonS3FileService.java @@ -1,20 +1,22 @@ package co.kirikiri.infra; -import co.kirikiri.exception.ServerException; import co.kirikiri.service.FileService; import co.kirikiri.service.dto.FileInformation; +import co.kirikiri.service.exception.ServerException; import com.amazonaws.SdkClientException; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; import com.amazonaws.services.s3.model.ObjectMetadata; -import org.springframework.core.env.Environment; -import org.springframework.http.HttpMethod; -import org.springframework.stereotype.Service; import java.io.InputStream; import java.net.URL; import java.util.Date; +import lombok.RequiredArgsConstructor; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Service; @Service +@RequiredArgsConstructor public class AmazonS3FileService implements FileService { private static final String ROOT_DIRECTORY_PROPERTY = "cloud.aws.s3.root-directory"; @@ -25,19 +27,23 @@ public class AmazonS3FileService implements FileService { private final AmazonS3 amazonS3; private final Environment environment; - - public AmazonS3FileService(final AmazonS3 amazonS3, final Environment environment) { - this.amazonS3 = amazonS3; - this.environment = environment; - } + private final CloudFrontService cloudFrontService; @Override public void save(final String path, final FileInformation fileInformation) { - final String key = makeKey(path); + final String realPath = makeRealPath(path); + final String key = makeKey(realPath); final ObjectMetadata objectMetadata = makeObjectMetadata(fileInformation); putObjectToS3(key, fileInformation.inputStream(), objectMetadata); } + private String makeRealPath(final String path) { + if (path.startsWith(DIRECTORY_SEPARATOR)) { + return path; + } + return DIRECTORY_SEPARATOR + path; + } + private String makeKey(final String path) { return findProperty(ROOT_DIRECTORY_PROPERTY) + DIRECTORY_SEPARATOR + findProperty(SUB_DIRECTORY_PROPERTY) + path; @@ -68,7 +74,11 @@ private String getBucketName() { @Override public URL generateUrl(final String path, final HttpMethod httpMethod) { - final String key = makeKey(path); + if (httpMethod.equals(HttpMethod.GET)) { + return cloudFrontService.generateGetUrl(path); + } + final String realPath = makeRealPath(path); + final String key = makeKey(realPath); final Date expiration = createExpiration(Long.parseLong(findProperty(EXPIRATION_PROPERTY))); final GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(getBucketName(), key) diff --git a/backend/kirikiri/src/main/java/co/kirikiri/infra/CloudFrontService.java b/backend/kirikiri/src/main/java/co/kirikiri/infra/CloudFrontService.java new file mode 100644 index 000000000..2c95c30ff --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/infra/CloudFrontService.java @@ -0,0 +1,44 @@ +package co.kirikiri.infra; + +import co.kirikiri.service.exception.ServerException; +import java.net.MalformedURLException; +import java.net.URL; +import lombok.RequiredArgsConstructor; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CloudFrontService { + + private static final String CLOUD_FRONT_DISTRIBUTION_DOMAIN = "cloud.aws.cloud-front.distribution-domain"; + private static final String DIRECTORY_SEPARATOR = "/"; + + private final Environment environment; + + public URL generateGetUrl(final String path) { + final String cloudFrontDistributionDomain = findProperty(CLOUD_FRONT_DISTRIBUTION_DOMAIN); + final String realPath = makeRealPath(path); + final String policyResourcePath = cloudFrontDistributionDomain + realPath; + return generateToUrl(policyResourcePath); + } + + private String findProperty(final String property) { + return environment.getProperty(property); + } + + private String makeRealPath(final String path) { + if (path.startsWith(DIRECTORY_SEPARATOR)) { + return path; + } + return DIRECTORY_SEPARATOR + path; + } + + private URL generateToUrl(final String url) { + try { + return new URL(url); + } catch (final MalformedURLException exception) { + throw new ServerException(exception.getMessage()); + } + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/infra/NaverOauthNetworkService.java b/backend/kirikiri/src/main/java/co/kirikiri/infra/NaverOauthNetworkService.java new file mode 100644 index 000000000..6cd0e7cd1 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/infra/NaverOauthNetworkService.java @@ -0,0 +1,56 @@ +package co.kirikiri.infra; + +import co.kirikiri.service.OauthNetworkService; +import lombok.RequiredArgsConstructor; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; +import java.util.Map; + +@Service +@RequiredArgsConstructor +public class NaverOauthNetworkService implements OauthNetworkService { + + private static final String QUERY_PARAMETER_EQUAL = "="; + private static final String QUERY_PARAMETER_DELIMITER = "&"; + private static final String CLIENT_ID_PROPERTY = "oauth.naver.client-id"; + private static final String CLIENT_SECRET_PROPERTY = "oauth.naver.client-secret"; + private static final String TOKEN_URL_PROPERTY = "oauth.naver.token-url"; + private static final String MEMBER_INFO_URL_PROPERTY = "oauth.naver.member-info-url"; + + private final RestTemplate restTemplate; + private final Environment environment; + + @Override + public ResponseEntity requestToken(final Class clazz, final Map queryParams) { + final String baseUrl = String.format(findProperty(TOKEN_URL_PROPERTY) + "client_id=%s&client_secret=%s&", + findProperty(CLIENT_ID_PROPERTY), findProperty(CLIENT_SECRET_PROPERTY)); + final StringBuilder stringBuilder = new StringBuilder(baseUrl); + for (final Map.Entry entry : queryParams.entrySet()) { + stringBuilder.append(entry.getKey()) + .append(QUERY_PARAMETER_EQUAL) + .append(entry.getValue()) + .append(QUERY_PARAMETER_DELIMITER); + } + final String url = stringBuilder.substring(0, stringBuilder.lastIndexOf(QUERY_PARAMETER_DELIMITER)); + return restTemplate.getForEntity(url, clazz); + } + + @Override + public ResponseEntity requestMemberInfo(final Class clazz, final Map headers) { + final HttpHeaders httpHeaders = new HttpHeaders(); + for (final Map.Entry entry : headers.entrySet()) { + httpHeaders.set(entry.getKey(), entry.getValue()); + } + final HttpEntity httpEntity = new HttpEntity<>(httpHeaders); + return restTemplate.exchange(findProperty(MEMBER_INFO_URL_PROPERTY), HttpMethod.GET, httpEntity, clazz); + } + + private String findProperty(final String property) { + return environment.getProperty(property); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/QuerydslRepositorySupporter.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/QuerydslRepositorySupporter.java index 2f9f79d55..685533ef7 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/QuerydslRepositorySupporter.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/QuerydslRepositorySupporter.java @@ -1,6 +1,6 @@ package co.kirikiri.persistence; -import co.kirikiri.exception.ServerException; +import co.kirikiri.service.exception.ServerException; import com.querydsl.core.types.EntityPath; import com.querydsl.core.types.Expression; import com.querydsl.core.types.dsl.PathBuilder; diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/auth/RefreshTokenQueryRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/auth/RefreshTokenQueryRepository.java deleted file mode 100644 index 771f49681..000000000 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/auth/RefreshTokenQueryRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.kirikiri.persistence.auth; - -import co.kirikiri.domain.auth.EncryptedToken; -import co.kirikiri.domain.auth.RefreshToken; -import java.util.Optional; - -public interface RefreshTokenQueryRepository { - - Optional findByTokenAndIsRevokedFalse(final EncryptedToken token); -} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/auth/RefreshTokenQueryRepositoryImpl.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/auth/RefreshTokenQueryRepositoryImpl.java deleted file mode 100644 index 31672da4b..000000000 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/auth/RefreshTokenQueryRepositoryImpl.java +++ /dev/null @@ -1,28 +0,0 @@ -package co.kirikiri.persistence.auth; - -import static co.kirikiri.domain.auth.QRefreshToken.refreshToken; -import static co.kirikiri.domain.member.QMember.member; - -import co.kirikiri.domain.auth.EncryptedToken; -import co.kirikiri.domain.auth.RefreshToken; -import co.kirikiri.persistence.QuerydslRepositorySupporter; -import java.util.Optional; - -public class RefreshTokenQueryRepositoryImpl extends QuerydslRepositorySupporter implements - RefreshTokenQueryRepository { - - public RefreshTokenQueryRepositoryImpl() { - super(RefreshToken.class); - } - - @Override - public Optional findByTokenAndIsRevokedFalse(final EncryptedToken token) { - - return Optional.ofNullable(selectFrom(refreshToken) - .join(refreshToken.member, member) - .fetchJoin() - .where(refreshToken.token.eq(token)) - .where(refreshToken.isRevoked.isFalse()) - .fetchOne()); - } -} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/auth/RefreshTokenRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/auth/RefreshTokenRepository.java index bf457b877..18e789945 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/auth/RefreshTokenRepository.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/auth/RefreshTokenRepository.java @@ -1,8 +1,10 @@ package co.kirikiri.persistence.auth; -import co.kirikiri.domain.auth.RefreshToken; -import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; -public interface RefreshTokenRepository extends JpaRepository, RefreshTokenQueryRepository { +public interface RefreshTokenRepository { + void save(final String refreshToken, final String memberIdentifier); + + Optional findMemberIdentifierByRefreshToken(final String refreshToken); } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/auth/RefreshTokenRepositoryImpl.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/auth/RefreshTokenRepositoryImpl.java new file mode 100644 index 000000000..7ca0a5de2 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/auth/RefreshTokenRepositoryImpl.java @@ -0,0 +1,37 @@ +package co.kirikiri.persistence.auth; + +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +@Repository +public class RefreshTokenRepositoryImpl implements RefreshTokenRepository { + + private final RedisTemplate redisTemplate; + private final Long refreshTokenValidityInSeconds; + + public RefreshTokenRepositoryImpl(final RedisTemplate redisTemplate, + @Value("${jwt.refresh-token-validity-in-seconds}") final Long refreshTokenValidityInSeconds) { + this.redisTemplate = redisTemplate; + this.refreshTokenValidityInSeconds = refreshTokenValidityInSeconds; + } + + @Override + public void save(final String refreshToken, final String memberIdentifier) { + final long timeToLiveSeconds = refreshTokenValidityInSeconds / 1000; + + redisTemplate.opsForValue() + .set(refreshToken, memberIdentifier, timeToLiveSeconds, TimeUnit.SECONDS); + } + + @Override + public Optional findMemberIdentifierByRefreshToken(final String refreshToken) { + final String memberIdentifier = redisTemplate.opsForValue().get(refreshToken); + if (memberIdentifier == null) { + return Optional.empty(); + } + return Optional.of(memberIdentifier); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/dto/RoadmapSearchTagName.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/dto/RoadmapSearchTagName.java index d059b45f5..c090385c1 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/dto/RoadmapSearchTagName.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/dto/RoadmapSearchTagName.java @@ -1,6 +1,6 @@ package co.kirikiri.persistence.dto; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.service.exception.BadRequestException; public record RoadmapSearchTagName( String value diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/dto/RoadmapSearchTitle.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/dto/RoadmapSearchTitle.java index 35291df93..8469ce5d7 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/dto/RoadmapSearchTitle.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/dto/RoadmapSearchTitle.java @@ -1,6 +1,6 @@ package co.kirikiri.persistence.dto; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.service.exception.BadRequestException; public record RoadmapSearchTitle( String value diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/CheckFeedRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/CheckFeedRepository.java index 1440fb02b..25f009dcd 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/CheckFeedRepository.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/CheckFeedRepository.java @@ -4,11 +4,11 @@ import co.kirikiri.domain.goalroom.GoalRoom; import co.kirikiri.domain.goalroom.GoalRoomMember; import co.kirikiri.domain.goalroom.GoalRoomRoadmapNode; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; public interface CheckFeedRepository extends JpaRepository, CheckFeedQueryRepository { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberJdbcRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberJdbcRepository.java new file mode 100644 index 000000000..9a7b2e8b5 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberJdbcRepository.java @@ -0,0 +1,9 @@ +package co.kirikiri.persistence.goalroom; + +import co.kirikiri.domain.goalroom.GoalRoomMember; +import java.util.List; + +public interface GoalRoomMemberJdbcRepository { + + void saveAllInBatch(final List goalRoomMembers); +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberJdbcRepositoryImpl.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberJdbcRepositoryImpl.java new file mode 100644 index 000000000..28758b191 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberJdbcRepositoryImpl.java @@ -0,0 +1,30 @@ +package co.kirikiri.persistence.goalroom; + +import co.kirikiri.domain.goalroom.GoalRoomMember; +import java.util.List; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; + +@Repository +public class GoalRoomMemberJdbcRepositoryImpl implements GoalRoomMemberJdbcRepository { + + private final JdbcTemplate jdbcTemplate; + + public GoalRoomMemberJdbcRepositoryImpl(final JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public void saveAllInBatch(final List goalRoomMembers) { + final String sql = "INSERT INTO goal_room_member " + + "(goal_room_id, member_id, role, joined_at, accomplishment_rate) " + + "VALUES (?, ?, ?, ?, ?)"; + jdbcTemplate.batchUpdate(sql, goalRoomMembers, goalRoomMembers.size(), ((ps, goalRoomMember) -> { + ps.setLong(1, goalRoomMember.getGoalRoom().getId()); + ps.setLong(2, goalRoomMember.getMember().getId()); + ps.setString(3, goalRoomMember.getRole().name()); + ps.setObject(4, goalRoomMember.getJoinedAt()); + ps.setDouble(5, goalRoomMember.getAccomplishmentRate()); + })); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberQueryRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberQueryRepository.java index 33428b2b1..0087e6a93 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberQueryRepository.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberQueryRepository.java @@ -4,9 +4,9 @@ import co.kirikiri.domain.goalroom.GoalRoomStatus; import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.persistence.goalroom.dto.GoalRoomMemberSortType; +import org.springframework.data.repository.query.Param; import java.util.List; import java.util.Optional; -import org.springframework.data.repository.query.Param; public interface GoalRoomMemberQueryRepository { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberRepository.java index 22c1e050b..aa1f912c8 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberRepository.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomMemberRepository.java @@ -9,7 +9,8 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -public interface GoalRoomMemberRepository extends JpaRepository, GoalRoomMemberQueryRepository { +public interface GoalRoomMemberRepository extends JpaRepository, + GoalRoomMemberQueryRepository, GoalRoomMemberJdbcRepository { @Query("select gm from GoalRoomMember gm " + "inner join fetch gm.goalRoom g " diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomPendingMemberRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomPendingMemberRepository.java index a72f9397c..cdd2d45db 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomPendingMemberRepository.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomPendingMemberRepository.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -28,4 +29,8 @@ Optional findByGoalRoomAndMemberIdentifier( + "where g=:goalRoom " + "and gp.member = m") List findAllByGoalRoom(@Param("goalRoom") final GoalRoom goalRoom); + + @Modifying + @Query("DELETE FROM GoalRoomPendingMember gp WHERE gp.id IN :ids") + void deleteAllByIdIn(@Param("ids") final List ids); } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomQueryRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomQueryRepository.java index 3892d3985..5a18b19d9 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomQueryRepository.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomQueryRepository.java @@ -5,19 +5,22 @@ import co.kirikiri.domain.member.Member; import co.kirikiri.domain.roadmap.Roadmap; import co.kirikiri.persistence.goalroom.dto.RoadmapGoalRoomsOrderType; +import java.time.LocalDate; import java.util.List; import java.util.Optional; public interface GoalRoomQueryRepository { + Optional findGoalRoomByIdWithPessimisticLock(Long goalRoomId); + Optional findByIdWithRoadmapContent(final Long goalRoomId); Optional findByIdWithContentAndTodos(final Long goalRoomId); - List findGoalRoomsWithPendingMembersByRoadmapAndCond(final Roadmap roadmap, - final RoadmapGoalRoomsOrderType filterType, - final Long lastId, - final int pageSize); + List findGoalRoomsByRoadmapAndCond(final Roadmap roadmap, + final RoadmapGoalRoomsOrderType filterType, + final Long lastId, + final int pageSize); Optional findByIdWithTodos(final Long goalRoomId); @@ -28,4 +31,6 @@ List findGoalRoomsWithPendingMembersByRoadmapAndCond(final Roadmap roa Optional findByIdWithNodes(final Long goalRoomId); List findByRoadmap(final Roadmap roadmap); + + List findAllRecruitingGoalRoomsByStartDateEarlierThan(final LocalDate startDate); } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomQueryRepositoryImpl.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomQueryRepositoryImpl.java index 4beabc68b..dad601666 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomQueryRepositoryImpl.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomQueryRepositoryImpl.java @@ -5,8 +5,6 @@ import static co.kirikiri.domain.goalroom.QGoalRoomPendingMember.goalRoomPendingMember; import static co.kirikiri.domain.goalroom.QGoalRoomRoadmapNode.goalRoomRoadmapNode; import static co.kirikiri.domain.goalroom.QGoalRoomToDo.goalRoomToDo; -import static co.kirikiri.domain.member.QMember.member; -import static co.kirikiri.domain.member.QMemberProfile.memberProfile; import static co.kirikiri.domain.roadmap.QRoadmapContent.roadmapContent; import co.kirikiri.domain.goalroom.GoalRoom; @@ -17,6 +15,8 @@ import co.kirikiri.persistence.goalroom.dto.RoadmapGoalRoomsOrderType; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.dsl.BooleanExpression; +import jakarta.persistence.LockModeType; +import java.time.LocalDate; import java.util.List; import java.util.Optional; @@ -28,6 +28,16 @@ public GoalRoomQueryRepositoryImpl() { super(GoalRoom.class); } + @Override + public Optional findGoalRoomByIdWithPessimisticLock(final Long goalRoomId) { + return Optional.ofNullable(selectFrom(goalRoom) + .innerJoin(goalRoom.goalRoomPendingMembers.values, goalRoomPendingMember) + .fetchJoin() + .where(goalRoom.id.eq(goalRoomId)) + .setLockMode(LockModeType.PESSIMISTIC_WRITE) + .fetchOne()); + } + @Override public Optional findByIdWithRoadmapContent(final Long goalRoomId) { return Optional.ofNullable(selectFrom(goalRoom) @@ -42,28 +52,22 @@ public Optional findByIdWithContentAndTodos(final Long goalRoomId) { return Optional.ofNullable(selectFrom(goalRoom) .innerJoin(goalRoom.roadmapContent, roadmapContent) .fetchJoin() - .innerJoin(goalRoom.goalRoomToDos.values, goalRoomToDo) + .leftJoin(goalRoom.goalRoomToDos.values, goalRoomToDo) .fetchJoin() .where(goalRoomIdCond(goalRoomId)) .fetchOne()); } @Override - public List findGoalRoomsWithPendingMembersByRoadmapAndCond(final Roadmap roadmap, - final RoadmapGoalRoomsOrderType orderType, - final Long lastId, - final int pageSize) { + public List findGoalRoomsByRoadmapAndCond(final Roadmap roadmap, + final RoadmapGoalRoomsOrderType orderType, + final Long lastId, + final int pageSize) { return selectFrom(goalRoom) .innerJoin(goalRoom.roadmapContent, roadmapContent) .on(roadmapContent.roadmap.eq(roadmap)) - .innerJoin(goalRoom.goalRoomPendingMembers.values, goalRoomPendingMember) - .fetchJoin() - .innerJoin(goalRoomPendingMember.member, member) - .fetchJoin() - .innerJoin(member.memberProfile, memberProfile) - .fetchJoin() .where( - statusCond(GoalRoomStatus.RECRUITING), + statusCond(orderType), lessThanLastId(lastId, orderType), roadmapCond(roadmap)) .limit(pageSize + LIMIT_OFFSET) @@ -106,6 +110,8 @@ public Optional findByIdWithNodes(final Long goalRoomId) { return Optional.ofNullable(selectFrom(goalRoom) .innerJoin(goalRoom.goalRoomRoadmapNodes.values, goalRoomRoadmapNode) .fetchJoin() + .innerJoin(goalRoom.roadmapContent, roadmapContent) + .fetchJoin() .where(goalRoomIdCond(goalRoomId)) .fetchOne()); } @@ -118,6 +124,16 @@ public List findByRoadmap(final Roadmap roadmap) { .fetch(); } + @Override + public List findAllRecruitingGoalRoomsByStartDateEarlierThan(final LocalDate date) { + return selectFrom(goalRoom) + .innerJoin(goalRoom.goalRoomPendingMembers.values, goalRoomPendingMember) + .fetchJoin() + .where(statusCond(GoalRoomStatus.RECRUITING)) + .where(equalOrEarlierStartDateThan(date)) + .fetch(); + } + private BooleanExpression goalRoomIdCond(final Long goalRoomId) { return goalRoom.id.eq(goalRoomId); } @@ -126,6 +142,13 @@ private BooleanExpression statusCond(final GoalRoomStatus status) { return goalRoom.status.eq(status); } + private BooleanExpression statusCond(final RoadmapGoalRoomsOrderType orderType) { + if (orderType == RoadmapGoalRoomsOrderType.CLOSE_TO_DEADLINE) { + return statusCond(GoalRoomStatus.RECRUITING); + } + return null; + } + private OrderSpecifier sortCond(final RoadmapGoalRoomsOrderType orderType) { if (orderType == RoadmapGoalRoomsOrderType.CLOSE_TO_DEADLINE) { return goalRoom.startDate.asc(); @@ -153,4 +176,8 @@ private BooleanExpression lessThanLastId(final Long lastId, final RoadmapGoalRoo private BooleanExpression roadmapCond(final Roadmap roadmap) { return goalRoom.roadmapContent.roadmap.eq(roadmap); } + + private BooleanExpression equalOrEarlierStartDateThan(final LocalDate date) { + return goalRoom.startDate.loe(date); + } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomRepository.java index ebcc375b1..7f517ae99 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomRepository.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomRepository.java @@ -7,10 +7,8 @@ import org.springframework.data.jpa.repository.JpaRepository; public interface GoalRoomRepository extends JpaRepository, GoalRoomQueryRepository { - - @Override + Optional findById(final Long goalRoomId); - List findAllByStartDate(final LocalDate startDate); List findAllByEndDate(final LocalDate endDate); } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomToDoCheckRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomToDoCheckRepository.java index 5b8ec6464..bc5609216 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomToDoCheckRepository.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/goalroom/GoalRoomToDoCheckRepository.java @@ -4,12 +4,12 @@ import co.kirikiri.domain.goalroom.GoalRoomToDo; import co.kirikiri.domain.goalroom.GoalRoomToDoCheck; import co.kirikiri.domain.member.vo.Identifier; -import java.util.List; -import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.util.List; +import java.util.Optional; public interface GoalRoomToDoCheckRepository extends JpaRepository { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/member/MemberRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/member/MemberRepository.java index e09aad8ea..4dd4e97ca 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/member/MemberRepository.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/member/MemberRepository.java @@ -3,12 +3,14 @@ import co.kirikiri.domain.member.Member; import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Nickname; -import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; public interface MemberRepository extends JpaRepository, MemberQueryRepository { Optional findByIdentifier(final Identifier identifier); Optional findByNickname(final Nickname nickname); + + Optional findByOauthId(final String oauthId); } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapCategoryRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapCategoryRepository.java index 5d1596636..37d52022b 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapCategoryRepository.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapCategoryRepository.java @@ -2,7 +2,9 @@ import co.kirikiri.domain.roadmap.RoadmapCategory; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; public interface RoadmapCategoryRepository extends JpaRepository { + Optional findByName(final String name); } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapContentRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapContentRepository.java index f7c20aaa9..722761e75 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapContentRepository.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapContentRepository.java @@ -2,10 +2,10 @@ import co.kirikiri.domain.roadmap.Roadmap; import co.kirikiri.domain.roadmap.RoadmapContent; -import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.util.Optional; public interface RoadmapContentRepository extends JpaRepository { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapNodeRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapNodeRepository.java index 674c23bfe..cbe15b11b 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapNodeRepository.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapNodeRepository.java @@ -2,8 +2,8 @@ import co.kirikiri.domain.roadmap.RoadmapContent; import co.kirikiri.domain.roadmap.RoadmapNode; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; public interface RoadmapNodeRepository extends JpaRepository { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapQueryRepositoryImpl.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapQueryRepositoryImpl.java index a2105efc0..95680b8aa 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapQueryRepositoryImpl.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapQueryRepositoryImpl.java @@ -59,7 +59,6 @@ public List findRoadmapsByCategory(final RoadmapCategory category, fina .fetchJoin() .innerJoin(roadmap.creator, member) .fetchJoin() - .leftJoin(roadmap.tags.values, roadmapTag) .where( lessThanLastId(lastId, orderType), statusCond(RoadmapStatus.CREATED), @@ -77,7 +76,6 @@ public List findRoadmapsByCond(final RoadmapSearchDto searchRequest, fi .fetchJoin() .innerJoin(roadmap.creator, member) .fetchJoin() - .leftJoin(roadmap.tags.values, roadmapTag) .where( lessThanLastId(lastId, orderType), statusCond(RoadmapStatus.CREATED), diff --git a/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapReviewRepository.java b/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapReviewRepository.java index 729324c74..b83bb24f2 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapReviewRepository.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/persistence/roadmap/RoadmapReviewRepository.java @@ -3,8 +3,8 @@ import co.kirikiri.domain.member.Member; import co.kirikiri.domain.roadmap.Roadmap; import co.kirikiri.domain.roadmap.RoadmapReview; -import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; public interface RoadmapReviewRepository extends JpaRepository, RoadmapReviewQueryRepository { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/CacheKeyGenerator.java b/backend/kirikiri/src/main/java/co/kirikiri/service/CacheKeyGenerator.java new file mode 100644 index 000000000..2a11fcd5d --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/CacheKeyGenerator.java @@ -0,0 +1,27 @@ +package co.kirikiri.service; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.stream.Collectors; +import org.springframework.cache.interceptor.KeyGenerator; +import org.springframework.stereotype.Component; + +@Component +public class CacheKeyGenerator implements KeyGenerator { + + private static final String DELIMITER = "_"; + + @Override + public Object generate(final Object target, final Method method, final Object... params) { + return String.format("%s-%s-%s", + target.getClass().getSimpleName(), + method.getName(), + arrayToDelimitedString(params)); + } + + private Object arrayToDelimitedString(final Object... params) { + return Arrays.stream(params) + .map(o -> o == null ? "" : String.valueOf(o.hashCode())) + .collect(Collectors.joining(DELIMITER)); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/OauthNetworkService.java b/backend/kirikiri/src/main/java/co/kirikiri/service/OauthNetworkService.java new file mode 100644 index 000000000..ad5f67286 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/OauthNetworkService.java @@ -0,0 +1,11 @@ +package co.kirikiri.service; + +import org.springframework.http.ResponseEntity; +import java.util.Map; + +public interface OauthNetworkService { + + ResponseEntity requestToken(final Class clazz, final Map queryParams); + + ResponseEntity requestMemberInfo(final Class clazz, final Map headers); +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/RandomNumberGenerator.java b/backend/kirikiri/src/main/java/co/kirikiri/service/RandomNumberGenerator.java index b4997b01f..edc031a4b 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/RandomNumberGenerator.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/RandomNumberGenerator.java @@ -1,7 +1,7 @@ package co.kirikiri.service; -import java.util.Random; import org.springframework.stereotype.Component; +import java.util.Random; @Component public class RandomNumberGenerator implements NumberGenerator { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/UUIDFilePathGenerator.java b/backend/kirikiri/src/main/java/co/kirikiri/service/UUIDFilePathGenerator.java index 9fa83e2ed..6d6450e2c 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/UUIDFilePathGenerator.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/UUIDFilePathGenerator.java @@ -1,5 +1,6 @@ package co.kirikiri.service; +import co.kirikiri.service.exception.BadRequestException; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.UUID; @@ -9,7 +10,7 @@ public class UUIDFilePathGenerator implements FilePathGenerator { private static final String DIRECTORY_SEPARATOR = "/"; - private static final String UUID_ORIGINAL_FILE_NAME_SEPARATOR = "_"; + private static final String FILE_SEPARATOR = "."; @Override public String makeFilePath(final ImageDirType dirType, final String originalFileName) { @@ -17,8 +18,22 @@ public String makeFilePath(final ImageDirType dirType, final String originalFile final DateTimeFormatter formatter = DateTimeFormatter.ofPattern( String.format("yyyy%sMMdd", DIRECTORY_SEPARATOR)); final String dateString = currentDate.format(formatter); + return makePath(dirType, originalFileName, dateString); + } + + private String makePath(final ImageDirType dirType, final String originalFileName, final String dateString) { + return DIRECTORY_SEPARATOR + dateString + + DIRECTORY_SEPARATOR + dirType.getDirName() + + DIRECTORY_SEPARATOR + UUID.randomUUID() + + makeFileExtension(originalFileName); + } - return DIRECTORY_SEPARATOR + dateString + DIRECTORY_SEPARATOR + dirType.getDirName() - + DIRECTORY_SEPARATOR + UUID.randomUUID() + UUID_ORIGINAL_FILE_NAME_SEPARATOR + originalFileName; + private String makeFileExtension(final String originalFileName) { + try { + final int fileSeparatorIndex = originalFileName.lastIndexOf(FILE_SEPARATOR); + return originalFileName.substring(fileSeparatorIndex); + } catch (final StringIndexOutOfBoundsException exception) { + throw new BadRequestException("원본 파일이름에 확장자가 존재하지 않습니다"); + } } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/aop/ExceptionConvert.java b/backend/kirikiri/src/main/java/co/kirikiri/service/aop/ExceptionConvert.java new file mode 100644 index 000000000..1a2b42941 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/aop/ExceptionConvert.java @@ -0,0 +1,12 @@ +package co.kirikiri.service.aop; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExceptionConvert { + +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/aop/ExceptionConvertAop.java b/backend/kirikiri/src/main/java/co/kirikiri/service/aop/ExceptionConvertAop.java new file mode 100644 index 000000000..4a9fb96ad --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/aop/ExceptionConvertAop.java @@ -0,0 +1,24 @@ +package co.kirikiri.service.aop; + +import co.kirikiri.domain.exception.DomainException; +import co.kirikiri.domain.exception.UnexpectedDomainException; +import co.kirikiri.service.exception.BadRequestException; +import co.kirikiri.service.exception.ServerException; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; + +@Aspect +@Component +public class ExceptionConvertAop { + + @AfterThrowing(pointcut = "within(@co.kirikiri.service.aop.ExceptionConvert *)", throwing = "exception") + public void convertException(final Throwable exception) { + if (exception instanceof UnexpectedDomainException) { + throw new ServerException(exception.getMessage()); + } + if (exception instanceof DomainException) { + throw new BadRequestException(exception.getMessage()); + } + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/AuthService.java b/backend/kirikiri/src/main/java/co/kirikiri/service/auth/AuthService.java similarity index 66% rename from backend/kirikiri/src/main/java/co/kirikiri/service/AuthService.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/auth/AuthService.java index 34becf89a..f8cc195f0 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/AuthService.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/auth/AuthService.java @@ -1,18 +1,17 @@ -package co.kirikiri.service; +package co.kirikiri.service.auth; -import co.kirikiri.domain.auth.EncryptedToken; -import co.kirikiri.domain.auth.RefreshToken; import co.kirikiri.domain.member.Member; +import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Password; -import co.kirikiri.exception.AuthenticationException; import co.kirikiri.persistence.auth.RefreshTokenRepository; import co.kirikiri.persistence.member.MemberRepository; +import co.kirikiri.service.aop.ExceptionConvert; import co.kirikiri.service.dto.auth.LoginDto; import co.kirikiri.service.dto.auth.request.LoginRequest; import co.kirikiri.service.dto.auth.request.ReissueTokenRequest; import co.kirikiri.service.dto.auth.response.AuthenticationResponse; +import co.kirikiri.service.exception.AuthenticationException; import co.kirikiri.service.mapper.AuthMapper; -import java.time.LocalDateTime; import java.util.Map; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -21,6 +20,7 @@ @Service @Transactional(readOnly = true) @RequiredArgsConstructor +@ExceptionConvert public class AuthService { private final RefreshTokenRepository refreshTokenRepository; @@ -48,16 +48,17 @@ private void checkPassword(final Password password, final Member member) { private AuthenticationResponse makeAuthenticationResponse(final Member member) { final String refreshToken = tokenProvider.createRefreshToken(member.getIdentifier().getValue(), Map.of()); - saveRefreshToken(member, refreshToken); + saveRefreshToken(refreshToken, member); final String accessToken = tokenProvider.createAccessToken(member.getIdentifier().getValue(), Map.of()); return AuthMapper.convertToAuthenticationResponse(refreshToken, accessToken); } - private void saveRefreshToken(final Member member, final String rawRefreshToken) { - final EncryptedToken encryptedToken = new EncryptedToken(rawRefreshToken); - final LocalDateTime expiredAt = tokenProvider.findTokenExpiredAt(rawRefreshToken); - final RefreshToken refreshToken = new RefreshToken(encryptedToken, expiredAt, member); - refreshTokenRepository.save(refreshToken); + private void saveRefreshToken(final String refreshToken, final Member member) { + refreshTokenRepository.save(refreshToken, member.getIdentifier().getValue()); + } + + public AuthenticationResponse oauthLogin(final Member member) { + return makeAuthenticationResponse(member); } public boolean isCertified(final String token) { @@ -67,11 +68,8 @@ public boolean isCertified(final String token) { @Transactional public AuthenticationResponse reissueToken(final ReissueTokenRequest reissueTokenRequest) { checkTokenValid(reissueTokenRequest.refreshToken()); - final EncryptedToken clientRefreshToken = AuthMapper.convertToEncryptedToken(reissueTokenRequest); - final RefreshToken refreshToken = findSavedRefreshToken(clientRefreshToken); - checkTokenExpired(refreshToken); - refreshTokenRepository.delete(refreshToken); - final Member member = refreshToken.getMember(); + final String memberIdentifier = findMemberIdentifierByRefreshToken(reissueTokenRequest.refreshToken()); + final Member member = findMemberByRefreshToken(memberIdentifier); return makeAuthenticationResponse(member); } @@ -81,15 +79,14 @@ private void checkTokenValid(final String token) { } } - private RefreshToken findSavedRefreshToken(final EncryptedToken clientRefreshToken) { - return refreshTokenRepository.findByTokenAndIsRevokedFalse(clientRefreshToken) - .orElseThrow(() -> new AuthenticationException("토큰이 유효하지 않습니다.")); + private String findMemberIdentifierByRefreshToken(final String clientRefreshToken) { + return refreshTokenRepository.findMemberIdentifierByRefreshToken(clientRefreshToken) + .orElseThrow(() -> new AuthenticationException("토큰이 만료 되었습니다.")); } - private void checkTokenExpired(final RefreshToken refreshToken) { - if (refreshToken.isExpired()) { - throw new AuthenticationException("토큰이 만료 되었습니다."); - } + private Member findMemberByRefreshToken(final String memberIdentifier) { + return memberRepository.findByIdentifier(new Identifier(memberIdentifier)) + .orElseThrow(() -> new AuthenticationException("존재하지 않는 회원입니다.")); } public String findIdentifierByToken(final String token) { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/JwtTokenProvider.java b/backend/kirikiri/src/main/java/co/kirikiri/service/auth/JwtTokenProvider.java similarity index 97% rename from backend/kirikiri/src/main/java/co/kirikiri/service/JwtTokenProvider.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/auth/JwtTokenProvider.java index 4dc82f64e..2b91cf904 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/JwtTokenProvider.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/auth/JwtTokenProvider.java @@ -1,6 +1,6 @@ -package co.kirikiri.service; +package co.kirikiri.service.auth; -import co.kirikiri.exception.AuthenticationException; +import co.kirikiri.service.exception.AuthenticationException; import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jws; diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/auth/NaverOauthService.java b/backend/kirikiri/src/main/java/co/kirikiri/service/auth/NaverOauthService.java new file mode 100644 index 000000000..d0630697e --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/auth/NaverOauthService.java @@ -0,0 +1,81 @@ +package co.kirikiri.service.auth; + +import co.kirikiri.domain.member.Member; +import co.kirikiri.persistence.member.MemberRepository; +import co.kirikiri.service.OauthNetworkService; +import co.kirikiri.service.dto.auth.NaverMemberProfileDto; +import co.kirikiri.service.dto.auth.NaverMemberProfileResponseDto; +import co.kirikiri.service.dto.auth.NaverOauthTokenDto; +import co.kirikiri.service.dto.auth.OauthRedirectResponse; +import co.kirikiri.service.dto.auth.response.AuthenticationResponse; +import co.kirikiri.service.dto.member.OauthMemberJoinDto; +import co.kirikiri.service.dto.member.request.GenderType; +import co.kirikiri.service.mapper.OauthMapper; +import co.kirikiri.service.member.MemberService; +import java.math.BigInteger; +import java.security.SecureRandom; +import java.util.Map; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class NaverOauthService { + + private static final String OAUTH_NAVER_REDIRECT_URL_PROPERTY = "oauth.naver.redirect-url"; + private static final String OAUTH_NAVER_CALLBACK_URL_PROPERTY = "oauth.naver.callback-url"; + private static final String OAUTH_NAVER_CLIENT_ID_PROPERTY = "oauth.naver.client-id"; + private static final String BEARER = "Bearer "; + + private final MemberRepository memberRepository; + private final MemberService memberService; + private final AuthService authService; + private final OauthNetworkService oauthNetworkService; + private final Environment environment; + + public OauthRedirectResponse makeOauthUrl() { + final String state = generateState(); + final String redirectUrl = getProperty(OAUTH_NAVER_REDIRECT_URL_PROPERTY); + final String clientId = getProperty(OAUTH_NAVER_CLIENT_ID_PROPERTY); + final String callBackUrl = getProperty(OAUTH_NAVER_CALLBACK_URL_PROPERTY); + final String url = String.format(redirectUrl, clientId, callBackUrl, state); + return OauthMapper.convertToOauthRedirectDto(url, state); + } + + private String generateState() { + final SecureRandom random = new SecureRandom(); + return new BigInteger(130, random).toString(32); + } + + private String getProperty(final String property) { + return environment.getProperty(property); + } + + @Transactional + public AuthenticationResponse login(final Map queryParams) { + final NaverOauthTokenDto naverOauthTokenDto = oauthNetworkService.requestToken(NaverOauthTokenDto.class, + queryParams).getBody(); + final NaverMemberProfileDto naverMemberProfileDto = getNaverMemberProfileDto(naverOauthTokenDto.accessToken()); + final NaverMemberProfileResponseDto naverMemberProfileResponseDto = naverMemberProfileDto.response(); + final Optional optionalMember = memberRepository.findByOauthId(naverMemberProfileResponseDto.id()); + if (optionalMember.isPresent()) { + final Member member = optionalMember.get(); + return authService.oauthLogin(member); + } + return memberService.oauthJoin( + new OauthMemberJoinDto(naverMemberProfileResponseDto.id(), naverMemberProfileResponseDto.email(), + naverMemberProfileResponseDto.nickname(), + GenderType.findByOauthType(naverMemberProfileResponseDto.gender()))); + } + + private NaverMemberProfileDto getNaverMemberProfileDto(final String accessToken) { + final Map headers = Map.of(HttpHeaders.AUTHORIZATION, BEARER + accessToken); + return oauthNetworkService.requestMemberInfo(NaverMemberProfileDto.class, headers) + .getBody(); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/TokenProvider.java b/backend/kirikiri/src/main/java/co/kirikiri/service/auth/TokenProvider.java similarity index 92% rename from backend/kirikiri/src/main/java/co/kirikiri/service/TokenProvider.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/auth/TokenProvider.java index f1d44c998..3bed60faa 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/TokenProvider.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/auth/TokenProvider.java @@ -1,4 +1,4 @@ -package co.kirikiri.service; +package co.kirikiri.service.auth; import java.time.LocalDateTime; import java.util.Map; diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/AuthenticationTokenDto.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/AuthenticationTokenDto.java new file mode 100644 index 000000000..8e56708f4 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/AuthenticationTokenDto.java @@ -0,0 +1,7 @@ +package co.kirikiri.service.dto.auth; + +public record AuthenticationTokenDto( + String accessToken, + String refreshToken +) { +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/NaverMemberProfileDto.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/NaverMemberProfileDto.java new file mode 100644 index 000000000..66218b592 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/NaverMemberProfileDto.java @@ -0,0 +1,12 @@ +package co.kirikiri.service.dto.auth; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +@JsonNaming(value = PropertyNamingStrategies.LowerCaseStrategy.class) +public record NaverMemberProfileDto( + String resultCode, + String message, + NaverMemberProfileResponseDto response +) { +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/NaverMemberProfileResponseDto.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/NaverMemberProfileResponseDto.java new file mode 100644 index 000000000..c2e073300 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/NaverMemberProfileResponseDto.java @@ -0,0 +1,13 @@ +package co.kirikiri.service.dto.auth; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +@JsonNaming(value = PropertyNamingStrategies.LowerCaseStrategy.class) +public record NaverMemberProfileResponseDto( + String id, + String email, + String nickname, + String gender +) { +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/NaverOauthTokenDto.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/NaverOauthTokenDto.java new file mode 100644 index 000000000..eb3b782ea --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/NaverOauthTokenDto.java @@ -0,0 +1,13 @@ +package co.kirikiri.service.dto.auth; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class) +public record NaverOauthTokenDto( + String accessToken, + String refreshToken, + String tokenType, + Integer expiresIn +) { +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/OauthRedirectResponse.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/OauthRedirectResponse.java new file mode 100644 index 000000000..983d60487 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/auth/OauthRedirectResponse.java @@ -0,0 +1,7 @@ +package co.kirikiri.service.dto.auth; + +public record OauthRedirectResponse( + String url, + String state +) { +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/GoalRoomCreateDto.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/GoalRoomCreateDto.java index 28f4583cd..8d7482748 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/GoalRoomCreateDto.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/GoalRoomCreateDto.java @@ -1,6 +1,5 @@ package co.kirikiri.service.dto.goalroom; -import co.kirikiri.domain.goalroom.GoalRoomToDo; import co.kirikiri.domain.goalroom.vo.GoalRoomName; import co.kirikiri.domain.goalroom.vo.LimitedMemberCount; import java.util.List; @@ -9,7 +8,6 @@ public record GoalRoomCreateDto( Long roadmapContentId, GoalRoomName goalRoomName, LimitedMemberCount limitedMemberCount, - GoalRoomToDo goalRoomToDo, List goalRoomRoadmapNodeDtos ) { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/GoalRoomRoadmapNodeDetailDto.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/GoalRoomRoadmapNodeDetailDto.java new file mode 100644 index 000000000..d1808167f --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/GoalRoomRoadmapNodeDetailDto.java @@ -0,0 +1,16 @@ +package co.kirikiri.service.dto.goalroom; + +import java.time.LocalDate; +import java.util.List; + +public record GoalRoomRoadmapNodeDetailDto( + Long id, + String title, + String description, + List imageUrls, + LocalDate startDate, + LocalDate endDate, + Integer checkCount +) { + +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/RoadmapGoalRoomDto.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/RoadmapGoalRoomDto.java index 0954a480c..618204f0c 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/RoadmapGoalRoomDto.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/RoadmapGoalRoomDto.java @@ -1,12 +1,15 @@ package co.kirikiri.service.dto.goalroom; +import co.kirikiri.domain.goalroom.GoalRoomStatus; import co.kirikiri.service.dto.member.MemberDto; + import java.time.LocalDate; import java.time.LocalDateTime; public record RoadmapGoalRoomDto( Long goalRoomId, String name, + GoalRoomStatus status, Integer currentMemberCount, Integer limitedMemberCount, LocalDateTime createdAt, diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/request/GoalRoomCreateRequest.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/request/GoalRoomCreateRequest.java index e5c1e43b0..546273c53 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/request/GoalRoomCreateRequest.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/request/GoalRoomCreateRequest.java @@ -16,9 +16,6 @@ public record GoalRoomCreateRequest( @NotNull(message = "골룸 제한 인원은 빈 값일 수 없습니다.") Integer limitedMemberCount, - @Valid - GoalRoomTodoRequest goalRoomTodo, - @Valid List goalRoomRoadmapNodeRequests ) { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/response/GoalRoomRoadmapNodeDetailResponse.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/response/GoalRoomRoadmapNodeDetailResponse.java new file mode 100644 index 000000000..62a1422bc --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/goalroom/response/GoalRoomRoadmapNodeDetailResponse.java @@ -0,0 +1,16 @@ +package co.kirikiri.service.dto.goalroom.response; + +import java.time.LocalDate; +import java.util.List; + +public record GoalRoomRoadmapNodeDetailResponse( + Long id, + String title, + String description, + List imageUrls, + LocalDate startDate, + LocalDate endDate, + Integer checkCount +) { + +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/MemberInformationDto.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/MemberInformationDto.java index 68e0d8c03..c11785204 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/MemberInformationDto.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/MemberInformationDto.java @@ -1,15 +1,12 @@ package co.kirikiri.service.dto.member; -import java.time.LocalDate; - public record MemberInformationDto( Long id, String nickname, String profileImageUrl, String gender, String identifier, - String phoneNumber, - LocalDate birthday + String email ) { } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/MemberJoinDto.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/MemberJoinDto.java index a88b08868..fadfda7b1 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/MemberJoinDto.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/MemberJoinDto.java @@ -4,15 +4,13 @@ import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Nickname; import co.kirikiri.domain.member.vo.Password; -import java.time.LocalDate; public record MemberJoinDto( Identifier identifier, Password password, Nickname nickname, - String phoneNumber, Gender gender, - LocalDate birthday + String email ) { } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/OauthMemberJoinDto.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/OauthMemberJoinDto.java new file mode 100644 index 000000000..713493688 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/OauthMemberJoinDto.java @@ -0,0 +1,11 @@ +package co.kirikiri.service.dto.member; + +import co.kirikiri.service.dto.member.request.GenderType; + +public record OauthMemberJoinDto( + String oauthId, + String email, + String nickname, + GenderType gender +) { +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/request/GenderType.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/request/GenderType.java index eb9ff514c..164ebc537 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/request/GenderType.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/request/GenderType.java @@ -1,5 +1,24 @@ package co.kirikiri.service.dto.member.request; +import co.kirikiri.service.exception.BadRequestException; +import java.util.Arrays; + public enum GenderType { - MALE, FEMALE + + MALE("M"), + FEMALE("F"), + UNDEFINED("U"); + + private final String oauthGenderType; + + GenderType(final String oauthGenderType) { + this.oauthGenderType = oauthGenderType; + } + + public static GenderType findByOauthType(final String oauthGenderType) { + return Arrays.stream(values()) + .filter(it -> it.oauthGenderType.equals(oauthGenderType)) + .findAny() + .orElseThrow(() -> new BadRequestException("존재하지 않는 성별 타입입니다.")); + } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/request/MemberJoinRequest.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/request/MemberJoinRequest.java index cfbd230cd..1aaf4f39b 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/request/MemberJoinRequest.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/request/MemberJoinRequest.java @@ -1,13 +1,13 @@ package co.kirikiri.service.dto.member.request; -import com.fasterxml.jackson.annotation.JsonFormat; +import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Pattern; -import java.time.LocalDate; public record MemberJoinRequest( - @NotBlank(message = "아이디는 빈 값일 수 없습니다.") + + @Pattern(regexp = "^[a-z0-9]+$", message = "형식에 맞지 않는 아이디입니다.") String identifier, @NotBlank(message = "비밀번호는 빈 값일 수 없습니다.") @@ -16,16 +16,12 @@ public record MemberJoinRequest( @NotBlank(message = "닉네임은 빈 값일 수 없습니다.") String nickname, - @NotBlank(message = "전화번호는 빈 값일 수 없습니다.") - @Pattern(regexp = "^010-\\d{4}-\\d{4}$", message = "전화번호 형식이 맞지 않습니다.") - String phoneNumber, - @NotNull(message = "성별은 빈 값일 수 없습니다.") GenderType genderType, - @NotNull(message = "생일은 빈 값일 수 없습니다.") - @JsonFormat(pattern = "yyyyMMdd") - LocalDate birthday + @NotBlank(message = "이메일은 빈 값일 수 없습니다.") + @Email(message = "이메일 형식이 아닙니다.") + String email ) { } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/response/MemberInformationResponse.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/response/MemberInformationResponse.java index 9ad52eb8f..1be4e1933 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/response/MemberInformationResponse.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/member/response/MemberInformationResponse.java @@ -1,15 +1,12 @@ package co.kirikiri.service.dto.member.response; -import java.time.LocalDate; - public record MemberInformationResponse( Long id, String nickname, String profileImageUrl, String gender, String identifier, - String phoneNumber, - LocalDate birthday + String email ) { } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/roadmap/request/RoadmapCategorySaveRequest.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/roadmap/request/RoadmapCategorySaveRequest.java new file mode 100644 index 000000000..5a107d70a --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/roadmap/request/RoadmapCategorySaveRequest.java @@ -0,0 +1,11 @@ +package co.kirikiri.service.dto.roadmap.request; + +import jakarta.validation.constraints.NotBlank; + +public record RoadmapCategorySaveRequest( + + @NotBlank(message = "카테고리 이름은 빈 값일 수 없습니다.") + String name +) { + +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/roadmap/request/RoadmapNodeSaveRequest.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/roadmap/request/RoadmapNodeSaveRequest.java index e36754ec2..863c876db 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/roadmap/request/RoadmapNodeSaveRequest.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/roadmap/request/RoadmapNodeSaveRequest.java @@ -1,11 +1,11 @@ package co.kirikiri.service.dto.roadmap.request; import jakarta.validation.constraints.NotBlank; -import java.util.List; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import org.springframework.web.multipart.MultipartFile; +import java.util.List; @NoArgsConstructor @AllArgsConstructor diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/roadmap/response/RoadmapGoalRoomResponse.java b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/roadmap/response/RoadmapGoalRoomResponse.java index 7ea65cffe..2d63964e5 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/dto/roadmap/response/RoadmapGoalRoomResponse.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/dto/roadmap/response/RoadmapGoalRoomResponse.java @@ -1,5 +1,6 @@ package co.kirikiri.service.dto.roadmap.response; +import co.kirikiri.domain.goalroom.GoalRoomStatus; import co.kirikiri.service.dto.member.response.MemberResponse; import java.time.LocalDate; import java.time.LocalDateTime; @@ -7,6 +8,7 @@ public record RoadmapGoalRoomResponse( Long goalRoomId, String name, + GoalRoomStatus status, Integer currentMemberCount, Integer limitedMemberCount, LocalDateTime createdAt, diff --git a/backend/kirikiri/src/main/java/co/kirikiri/exception/AuthenticationException.java b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/AuthenticationException.java similarity index 80% rename from backend/kirikiri/src/main/java/co/kirikiri/exception/AuthenticationException.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/exception/AuthenticationException.java index 303cb5908..6e08c9c38 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/exception/AuthenticationException.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/AuthenticationException.java @@ -1,4 +1,4 @@ -package co.kirikiri.exception; +package co.kirikiri.service.exception; public class AuthenticationException extends BusinessException { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/exception/BadRequestException.java b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/BadRequestException.java similarity index 79% rename from backend/kirikiri/src/main/java/co/kirikiri/exception/BadRequestException.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/exception/BadRequestException.java index e88a97266..a6000ad1a 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/exception/BadRequestException.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/BadRequestException.java @@ -1,4 +1,4 @@ -package co.kirikiri.exception; +package co.kirikiri.service.exception; public class BadRequestException extends BusinessException { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/exception/BusinessException.java b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/BusinessException.java similarity index 78% rename from backend/kirikiri/src/main/java/co/kirikiri/exception/BusinessException.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/exception/BusinessException.java index 32c3e413d..404a22614 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/exception/BusinessException.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/BusinessException.java @@ -1,4 +1,4 @@ -package co.kirikiri.exception; +package co.kirikiri.service.exception; public class BusinessException extends RuntimeException { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/exception/ConflictException.java b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/ConflictException.java similarity index 78% rename from backend/kirikiri/src/main/java/co/kirikiri/exception/ConflictException.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/exception/ConflictException.java index e40e602dc..dc0103c4a 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/exception/ConflictException.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/ConflictException.java @@ -1,4 +1,4 @@ -package co.kirikiri.exception; +package co.kirikiri.service.exception; public class ConflictException extends BusinessException { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/exception/ForbiddenException.java b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/ForbiddenException.java similarity index 79% rename from backend/kirikiri/src/main/java/co/kirikiri/exception/ForbiddenException.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/exception/ForbiddenException.java index 11c23e4ac..e945efb65 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/exception/ForbiddenException.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/ForbiddenException.java @@ -1,4 +1,4 @@ -package co.kirikiri.exception; +package co.kirikiri.service.exception; public class ForbiddenException extends RuntimeException { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/exception/NotFoundException.java b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/NotFoundException.java similarity index 78% rename from backend/kirikiri/src/main/java/co/kirikiri/exception/NotFoundException.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/exception/NotFoundException.java index ae007e40e..135762e67 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/exception/NotFoundException.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/NotFoundException.java @@ -1,4 +1,4 @@ -package co.kirikiri.exception; +package co.kirikiri.service.exception; public class NotFoundException extends BusinessException { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/exception/ServerException.java b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/ServerException.java similarity index 78% rename from backend/kirikiri/src/main/java/co/kirikiri/exception/ServerException.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/exception/ServerException.java index aa1a6efad..105a85b63 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/exception/ServerException.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/exception/ServerException.java @@ -1,4 +1,4 @@ -package co.kirikiri.exception; +package co.kirikiri.service.exception; public class ServerException extends RuntimeException { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/GoalRoomCreateService.java b/backend/kirikiri/src/main/java/co/kirikiri/service/goalroom/GoalRoomCreateService.java similarity index 95% rename from backend/kirikiri/src/main/java/co/kirikiri/service/GoalRoomCreateService.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/goalroom/GoalRoomCreateService.java index 63eec340a..7e34b03ea 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/GoalRoomCreateService.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/goalroom/GoalRoomCreateService.java @@ -1,4 +1,4 @@ -package co.kirikiri.service; +package co.kirikiri.service.goalroom; import co.kirikiri.domain.ImageContentType; import co.kirikiri.domain.goalroom.CheckFeed; @@ -15,15 +15,16 @@ import co.kirikiri.domain.roadmap.Roadmap; import co.kirikiri.domain.roadmap.RoadmapContent; import co.kirikiri.domain.roadmap.RoadmapNode; -import co.kirikiri.exception.BadRequestException; -import co.kirikiri.exception.NotFoundException; import co.kirikiri.persistence.goalroom.CheckFeedRepository; import co.kirikiri.persistence.goalroom.GoalRoomMemberRepository; -import co.kirikiri.persistence.goalroom.GoalRoomPendingMemberRepository; import co.kirikiri.persistence.goalroom.GoalRoomRepository; import co.kirikiri.persistence.goalroom.GoalRoomToDoCheckRepository; import co.kirikiri.persistence.member.MemberRepository; import co.kirikiri.persistence.roadmap.RoadmapContentRepository; +import co.kirikiri.service.FilePathGenerator; +import co.kirikiri.service.FileService; +import co.kirikiri.service.ImageDirType; +import co.kirikiri.service.aop.ExceptionConvert; import co.kirikiri.service.dto.FileInformation; import co.kirikiri.service.dto.goalroom.GoalRoomCreateDto; import co.kirikiri.service.dto.goalroom.GoalRoomRoadmapNodeDto; @@ -31,19 +32,22 @@ import co.kirikiri.service.dto.goalroom.request.GoalRoomCreateRequest; import co.kirikiri.service.dto.goalroom.request.GoalRoomTodoRequest; import co.kirikiri.service.dto.goalroom.response.GoalRoomToDoCheckResponse; +import co.kirikiri.service.exception.BadRequestException; +import co.kirikiri.service.exception.NotFoundException; import co.kirikiri.service.mapper.GoalRoomMapper; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.List; @Service @Transactional @RequiredArgsConstructor +@ExceptionConvert public class GoalRoomCreateService { private final FileService fileService; @@ -53,7 +57,6 @@ public class GoalRoomCreateService { private final RoadmapContentRepository roadmapContentRepository; private final GoalRoomMemberRepository goalRoomMemberRepository; private final GoalRoomToDoCheckRepository goalRoomToDoCheckRepository; - private final GoalRoomPendingMemberRepository goalRoomPendingMemberRepository; private final CheckFeedRepository checkFeedRepository; public Long create(final GoalRoomCreateRequest goalRoomCreateRequest, final String memberIdentifier) { @@ -68,7 +71,6 @@ public Long create(final GoalRoomCreateRequest goalRoomCreateRequest, final Stri final GoalRoom goalRoom = new GoalRoom(goalRoomCreateDto.goalRoomName(), goalRoomCreateDto.limitedMemberCount(), roadmapContent, leader); goalRoom.addAllGoalRoomRoadmapNodes(goalRoomRoadmapNodes); - goalRoom.addGoalRoomTodo(goalRoomCreateDto.goalRoomToDo()); return goalRoomRepository.save(goalRoom).getId(); } @@ -116,12 +118,12 @@ private Member findMemberByIdentifier(final String memberIdentifier) { public void join(final String identifier, final Long goalRoomId) { final Member member = findMemberByIdentifier(identifier); - final GoalRoom goalRoom = findGoalRoomById(goalRoomId); + final GoalRoom goalRoom = findGoalRoomByIdWithPessimisticLock(goalRoomId); goalRoom.join(member); } - private GoalRoom findGoalRoomById(final Long goalRoomId) { - return goalRoomRepository.findById(goalRoomId) + private GoalRoom findGoalRoomByIdWithPessimisticLock(final Long goalRoomId) { + return goalRoomRepository.findGoalRoomByIdWithPessimisticLock(goalRoomId) .orElseThrow(() -> new NotFoundException("존재하지 않는 골룸입니다. goalRoomId = " + goalRoomId)); } @@ -137,6 +139,11 @@ public Long addGoalRoomTodo(final Long goalRoomId, final String identifier, return goalRoom.findLastGoalRoomTodo().getId(); } + private GoalRoom findGoalRoomById(final Long goalRoomId) { + return goalRoomRepository.findById(goalRoomId) + .orElseThrow(() -> new NotFoundException("존재하지 않는 골룸입니다. goalRoomId = " + goalRoomId)); + } + private void checkGoalRoomCompleted(final GoalRoom goalRoom) { if (goalRoom.isCompleted()) { throw new BadRequestException("이미 종료된 골룸입니다."); diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/GoalRoomReadService.java b/backend/kirikiri/src/main/java/co/kirikiri/service/goalroom/GoalRoomReadService.java similarity index 87% rename from backend/kirikiri/src/main/java/co/kirikiri/service/GoalRoomReadService.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/goalroom/GoalRoomReadService.java index 312a109a1..09480bbef 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/GoalRoomReadService.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/goalroom/GoalRoomReadService.java @@ -1,4 +1,4 @@ -package co.kirikiri.service; +package co.kirikiri.service.goalroom; import co.kirikiri.domain.goalroom.CheckFeed; import co.kirikiri.domain.goalroom.GoalRoom; @@ -11,8 +11,7 @@ import co.kirikiri.domain.goalroom.GoalRoomToDos; import co.kirikiri.domain.member.Member; import co.kirikiri.domain.member.vo.Identifier; -import co.kirikiri.exception.ForbiddenException; -import co.kirikiri.exception.NotFoundException; +import co.kirikiri.domain.roadmap.RoadmapNode; import co.kirikiri.persistence.goalroom.CheckFeedRepository; import co.kirikiri.persistence.goalroom.GoalRoomMemberRepository; import co.kirikiri.persistence.goalroom.GoalRoomPendingMemberRepository; @@ -20,21 +19,26 @@ import co.kirikiri.persistence.goalroom.GoalRoomToDoCheckRepository; import co.kirikiri.persistence.goalroom.dto.GoalRoomMemberSortType; import co.kirikiri.persistence.member.MemberRepository; +import co.kirikiri.service.FileService; +import co.kirikiri.service.aop.ExceptionConvert; import co.kirikiri.service.dto.goalroom.CheckFeedDto; import co.kirikiri.service.dto.goalroom.GoalRoomCheckFeedDto; import co.kirikiri.service.dto.goalroom.GoalRoomMemberDto; import co.kirikiri.service.dto.goalroom.GoalRoomMemberSortTypeDto; +import co.kirikiri.service.dto.goalroom.GoalRoomRoadmapNodeDetailDto; import co.kirikiri.service.dto.goalroom.MemberGoalRoomForListDto; import co.kirikiri.service.dto.goalroom.request.GoalRoomStatusTypeRequest; import co.kirikiri.service.dto.goalroom.response.GoalRoomCertifiedResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomCheckFeedResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomMemberResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomResponse; -import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodeResponse; +import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodeDetailResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomTodoResponse; import co.kirikiri.service.dto.member.MemberDto; import co.kirikiri.service.dto.member.response.MemberGoalRoomForListResponse; import co.kirikiri.service.dto.member.response.MemberGoalRoomResponse; +import co.kirikiri.service.exception.ForbiddenException; +import co.kirikiri.service.exception.NotFoundException; import co.kirikiri.service.mapper.GoalRoomMapper; import java.net.URL; import java.time.LocalDate; @@ -50,6 +54,7 @@ @Service @Transactional(readOnly = true) @RequiredArgsConstructor +@ExceptionConvert public class GoalRoomReadService { private final MemberRepository memberRepository; @@ -216,7 +221,8 @@ private List findCheckFeedsByNodeAndGoalRoomStatus(final GoalRoom goa public List findMemberGoalRooms(final String identifier) { final Member member = findMemberByIdentifier(new Identifier(identifier)); final List memberGoalRooms = goalRoomRepository.findByMember(member); - final List memberGoalRoomForListDtos = makeMemberGoalRoomForListDto(memberGoalRooms); + final List memberGoalRoomForListDtos = makeMemberGoalRoomForListDto( + memberGoalRooms); return GoalRoomMapper.convertToMemberGoalRoomForListResponses(memberGoalRoomForListDtos); } @@ -241,20 +247,46 @@ public List findMemberGoalRoomsByStatusType(final final Member member = findMemberByIdentifier(new Identifier(identifier)); final GoalRoomStatus goalRoomStatus = GoalRoomMapper.convertToGoalRoomStatus(goalRoomStatusTypeRequest); final List memberGoalRooms = goalRoomRepository.findByMemberAndStatus(member, goalRoomStatus); - final List memberGoalRoomForListDtos = makeMemberGoalRoomForListDto(memberGoalRooms); + final List memberGoalRoomForListDtos = makeMemberGoalRoomForListDto( + memberGoalRooms); return GoalRoomMapper.convertToMemberGoalRoomForListResponses(memberGoalRoomForListDtos); } - public List findAllGoalRoomNodes(final Long goalRoomId, final String identifier) { - final GoalRoomRoadmapNodes goalRoomNodes = findGoalRoomNodesByGoalRoomId(goalRoomId); + public List findAllGoalRoomNodes(final Long goalRoomId, + final String identifier) { + final GoalRoom goalRoom = findGoalRoomWithNodesByGoalRoomId(goalRoomId); + final GoalRoomRoadmapNodes goalRoomNodes = goalRoom.getGoalRoomRoadmapNodes(); validateGoalRoomMember(goalRoomId, identifier); - return GoalRoomMapper.convertGoalRoomNodeResponses(goalRoomNodes); + final List goalRoomRoadmapNodeDetailDtos = makeGoalRoomNodeDetailDtos( + goalRoomNodes); + + return GoalRoomMapper.convertGoalRoomNodeDetailResponses(goalRoomRoadmapNodeDetailDtos); } - private GoalRoomRoadmapNodes findGoalRoomNodesByGoalRoomId(final Long goalRoomId) { + private GoalRoom findGoalRoomWithNodesByGoalRoomId(final Long goalRoomId) { return goalRoomRepository.findByIdWithNodes(goalRoomId) - .orElseThrow(() -> new NotFoundException("존재하지 않는 골룸입니다. goalRoomId = " + goalRoomId)) - .getGoalRoomRoadmapNodes(); + .orElseThrow(() -> new NotFoundException("존재하지 않는 골룸입니다. goalRoomId = " + goalRoomId)); + } + + public List makeGoalRoomNodeDetailDtos( + final GoalRoomRoadmapNodes nodes) { + return nodes.getValues().stream() + .map(this::makeGoalRoomNodeDetailResponse) + .toList(); + } + + private GoalRoomRoadmapNodeDetailDto makeGoalRoomNodeDetailResponse(final GoalRoomRoadmapNode node) { + final RoadmapNode roadmapNode = node.getRoadmapNode(); + return new GoalRoomRoadmapNodeDetailDto(node.getId(), roadmapNode.getTitle(), roadmapNode.getContent(), + makeRoadmapNodeImageUrls(roadmapNode), node.getStartDate(), node.getEndDate(), node.getCheckCount()); + } + + private List makeRoadmapNodeImageUrls(final RoadmapNode roadmapNode) { + return roadmapNode.getRoadmapNodeImages() + .getValues() + .stream() + .map(it -> fileService.generateUrl(it.getServerFilePath(), HttpMethod.GET).toExternalForm()) + .toList(); } public List findGoalRoomCheckFeeds(final String identifier, final Long goalRoomId) { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/AuthMapper.java b/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/AuthMapper.java index ec3df85d4..4809ca258 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/AuthMapper.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/AuthMapper.java @@ -1,11 +1,9 @@ package co.kirikiri.service.mapper; -import co.kirikiri.domain.auth.EncryptedToken; import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Password; import co.kirikiri.service.dto.auth.LoginDto; import co.kirikiri.service.dto.auth.request.LoginRequest; -import co.kirikiri.service.dto.auth.request.ReissueTokenRequest; import co.kirikiri.service.dto.auth.response.AuthenticationResponse; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -21,8 +19,4 @@ public static AuthenticationResponse convertToAuthenticationResponse(final Strin final String accessToken) { return new AuthenticationResponse(refreshToken, accessToken); } - - public static EncryptedToken convertToEncryptedToken(final ReissueTokenRequest reissueTokenRequest) { - return new EncryptedToken(reissueTokenRequest.refreshToken()); - } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/GoalRoomMapper.java b/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/GoalRoomMapper.java index 905f0f24c..a7a7fdef6 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/GoalRoomMapper.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/GoalRoomMapper.java @@ -11,7 +11,6 @@ import co.kirikiri.domain.goalroom.vo.GoalRoomTodoContent; import co.kirikiri.domain.goalroom.vo.LimitedMemberCount; import co.kirikiri.domain.goalroom.vo.Period; -import co.kirikiri.exception.ServerException; import co.kirikiri.persistence.goalroom.dto.GoalRoomMemberSortType; import co.kirikiri.persistence.goalroom.dto.RoadmapGoalRoomsOrderType; import co.kirikiri.service.dto.FileInformation; @@ -20,6 +19,7 @@ import co.kirikiri.service.dto.goalroom.GoalRoomCreateDto; import co.kirikiri.service.dto.goalroom.GoalRoomMemberDto; import co.kirikiri.service.dto.goalroom.GoalRoomMemberSortTypeDto; +import co.kirikiri.service.dto.goalroom.GoalRoomRoadmapNodeDetailDto; import co.kirikiri.service.dto.goalroom.GoalRoomRoadmapNodeDto; import co.kirikiri.service.dto.goalroom.MemberGoalRoomForListDto; import co.kirikiri.service.dto.goalroom.RoadmapGoalRoomDto; @@ -33,6 +33,7 @@ import co.kirikiri.service.dto.goalroom.response.GoalRoomCheckFeedResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomMemberResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomResponse; +import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodeDetailResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodeResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodesResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomToDoCheckResponse; @@ -45,15 +46,16 @@ import co.kirikiri.service.dto.roadmap.RoadmapGoalRoomsOrderTypeDto; import co.kirikiri.service.dto.roadmap.response.RoadmapGoalRoomResponse; import co.kirikiri.service.dto.roadmap.response.RoadmapGoalRoomResponses; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.springframework.web.multipart.MultipartFile; +import co.kirikiri.service.exception.ServerException; import java.io.IOException; import java.time.LocalDate; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class GoalRoomMapper { @@ -62,8 +64,6 @@ public class GoalRoomMapper { private static final int MAX_MEMBER_GOAL_ROOM_CHECK_FEED_NUMBER = 4; public static GoalRoomCreateDto convertToGoalRoomCreateDto(final GoalRoomCreateRequest goalRoomCreateRequest) { - final GoalRoomTodoRequest goalRoomTodoRequest = goalRoomCreateRequest.goalRoomTodo(); - final GoalRoomToDo goalRoomToDo = convertToGoalRoomTodo(goalRoomTodoRequest); final List goalRoomRoadmapNodeRequests = goalRoomCreateRequest.goalRoomRoadmapNodeRequests(); final List goalRoomRoadmapNodeDtos = makeGoalRoomRoadmapNodeDtos( goalRoomRoadmapNodeRequests); @@ -72,7 +72,7 @@ public static GoalRoomCreateDto convertToGoalRoomCreateDto(final GoalRoomCreateR goalRoomCreateRequest.roadmapContentId(), new GoalRoomName(goalRoomCreateRequest.name()), new LimitedMemberCount(goalRoomCreateRequest.limitedMemberCount()), - goalRoomToDo, goalRoomRoadmapNodeDtos); + goalRoomRoadmapNodeDtos); } public static GoalRoomToDo convertToGoalRoomTodo(final GoalRoomTodoRequest goalRoomTodoRequest) { @@ -108,6 +108,21 @@ private static GoalRoomRoadmapNodeResponse convertGoalRoomNodeResponse(final Goa node.getEndDate(), node.getCheckCount()); } + public static List convertGoalRoomNodeDetailResponses( + final List goalRoomRoadmapNodeDetailDtos) { + return goalRoomRoadmapNodeDetailDtos.stream() + .map(GoalRoomMapper::convertGoalRoomNodeDetailResponse) + .toList(); + } + + private static GoalRoomRoadmapNodeDetailResponse convertGoalRoomNodeDetailResponse( + final GoalRoomRoadmapNodeDetailDto goalRoomRoadmapNodeDetailDto) { + return new GoalRoomRoadmapNodeDetailResponse(goalRoomRoadmapNodeDetailDto.id(), + goalRoomRoadmapNodeDetailDto.title(), goalRoomRoadmapNodeDetailDto.description(), + goalRoomRoadmapNodeDetailDto.imageUrls(), goalRoomRoadmapNodeDetailDto.startDate(), + goalRoomRoadmapNodeDetailDto.endDate(), goalRoomRoadmapNodeDetailDto.checkCount()); + } + public static GoalRoomCertifiedResponse convertGoalRoomCertifiedResponse(final GoalRoom goalRoom, final boolean isJoined) { final GoalRoomRoadmapNodes nodes = goalRoom.getGoalRoomRoadmapNodes(); @@ -137,7 +152,8 @@ public static RoadmapGoalRoomResponses convertToRoadmapGoalRoomResponses( private static RoadmapGoalRoomResponse convertToRoadmapGoalRoomResponse( final RoadmapGoalRoomDto roadmapGoalRoomDto) { return new RoadmapGoalRoomResponse(roadmapGoalRoomDto.goalRoomId(), roadmapGoalRoomDto.name(), - roadmapGoalRoomDto.currentMemberCount(), roadmapGoalRoomDto.limitedMemberCount(), + roadmapGoalRoomDto.status(), roadmapGoalRoomDto.currentMemberCount(), + roadmapGoalRoomDto.limitedMemberCount(), roadmapGoalRoomDto.createdAt(), roadmapGoalRoomDto.startDate(), roadmapGoalRoomDto.endDate(), convertToMemberResponse(roadmapGoalRoomDto.goalRoomLeader())); } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/MemberMapper.java b/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/MemberMapper.java index dba8f260e..409e662ee 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/MemberMapper.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/MemberMapper.java @@ -21,15 +21,14 @@ public static MemberJoinDto convertToMemberJoinDto(final MemberJoinRequest reque final Password password = new Password(request.password()); final Nickname nickname = new Nickname(request.nickname()); final Gender gender = Gender.valueOf(request.genderType().name()); - return new MemberJoinDto(identifier, password, nickname, request.phoneNumber(), gender, request.birthday()); + return new MemberJoinDto(identifier, password, nickname, gender, request.email()); } public static MemberInformationResponse convertToMemberInformationResponse( final MemberInformationDto memberInformationDto) { return new MemberInformationResponse(memberInformationDto.id(), memberInformationDto.nickname(), memberInformationDto.profileImageUrl(), memberInformationDto.gender(), - memberInformationDto.identifier(), - memberInformationDto.phoneNumber(), memberInformationDto.birthday()); + memberInformationDto.identifier(), memberInformationDto.email()); } public static MemberInformationForPublicResponse convertToMemberInformationForPublicResponse( diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/OauthMapper.java b/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/OauthMapper.java new file mode 100644 index 000000000..d302d2f00 --- /dev/null +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/OauthMapper.java @@ -0,0 +1,10 @@ +package co.kirikiri.service.mapper; + +import co.kirikiri.service.dto.auth.OauthRedirectResponse; + +public class OauthMapper { + + public static OauthRedirectResponse convertToOauthRedirectDto(final String url, final String state) { + return new OauthRedirectResponse(url, state); + } +} diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/RoadmapMapper.java b/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/RoadmapMapper.java index e89811241..a5efc4376 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/RoadmapMapper.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/RoadmapMapper.java @@ -3,7 +3,6 @@ import co.kirikiri.domain.member.Member; import co.kirikiri.domain.roadmap.Roadmap; import co.kirikiri.domain.roadmap.RoadmapCategory; -import co.kirikiri.exception.ServerException; import co.kirikiri.persistence.dto.RoadmapOrderType; import co.kirikiri.service.dto.FileInformation; import co.kirikiri.service.dto.member.MemberDto; @@ -21,6 +20,7 @@ import co.kirikiri.service.dto.roadmap.RoadmapSaveDto; import co.kirikiri.service.dto.roadmap.RoadmapTagDto; import co.kirikiri.service.dto.roadmap.RoadmapTagSaveDto; +import co.kirikiri.service.dto.roadmap.request.RoadmapCategorySaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapNodeSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapOrderTypeRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapReviewSaveRequest; @@ -36,12 +36,13 @@ import co.kirikiri.service.dto.roadmap.response.RoadmapResponse; import co.kirikiri.service.dto.roadmap.response.RoadmapReviewResponse; import co.kirikiri.service.dto.roadmap.response.RoadmapTagResponse; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.springframework.web.multipart.MultipartFile; +import co.kirikiri.service.exception.ServerException; import java.io.IOException; import java.util.Collections; import java.util.List; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class RoadmapMapper { @@ -77,7 +78,8 @@ private static RoadmapNodeSaveDto convertToRoadmapNodesSaveDto(final RoadmapNode private static FileInformation converToRoadmapNodeImageDto(final MultipartFile it) { try { - return new FileInformation(it.getOriginalFilename(), it.getSize(), it.getContentType(), it.getInputStream()); + return new FileInformation(it.getOriginalFilename(), it.getSize(), it.getContentType(), + it.getInputStream()); } catch (final IOException exception) { throw new ServerException(exception.getMessage()); } @@ -209,4 +211,8 @@ private static RoadmapReviewResponse convertToRoadmapReviewResponse( new MemberResponse(memberDto.id(), memberDto.name(), memberDto.imageUrl()), roadmapReviewReadDto.createdAt(), roadmapReviewReadDto.content(), roadmapReviewReadDto.rate()); } + + public static RoadmapCategory convertToRoadmapCategory(final RoadmapCategorySaveRequest request) { + return new RoadmapCategory(request.name()); + } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/ScrollResponseMapper.java b/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/ScrollResponseMapper.java index 198e55b7c..c9d3b4c64 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/ScrollResponseMapper.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/mapper/ScrollResponseMapper.java @@ -1,8 +1,8 @@ package co.kirikiri.service.mapper; -import java.util.List; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import java.util.List; @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class ScrollResponseMapper { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/MemberService.java b/backend/kirikiri/src/main/java/co/kirikiri/service/member/MemberService.java similarity index 67% rename from backend/kirikiri/src/main/java/co/kirikiri/service/MemberService.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/member/MemberService.java index de5f7246b..2fec1552c 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/MemberService.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/member/MemberService.java @@ -1,23 +1,34 @@ -package co.kirikiri.service; +package co.kirikiri.service.member; import co.kirikiri.domain.ImageContentType; import co.kirikiri.domain.member.EncryptedPassword; +import co.kirikiri.domain.member.Gender; import co.kirikiri.domain.member.Member; import co.kirikiri.domain.member.MemberImage; import co.kirikiri.domain.member.MemberProfile; import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Nickname; -import co.kirikiri.exception.ConflictException; -import co.kirikiri.exception.NotFoundException; +import co.kirikiri.persistence.auth.RefreshTokenRepository; import co.kirikiri.persistence.member.MemberRepository; +import co.kirikiri.service.FileService; +import co.kirikiri.service.NumberGenerator; +import co.kirikiri.service.aop.ExceptionConvert; +import co.kirikiri.service.auth.TokenProvider; +import co.kirikiri.service.dto.auth.response.AuthenticationResponse; import co.kirikiri.service.dto.member.MemberInformationDto; import co.kirikiri.service.dto.member.MemberInformationForPublicDto; import co.kirikiri.service.dto.member.MemberJoinDto; +import co.kirikiri.service.dto.member.OauthMemberJoinDto; import co.kirikiri.service.dto.member.request.MemberJoinRequest; import co.kirikiri.service.dto.member.response.MemberInformationForPublicResponse; import co.kirikiri.service.dto.member.response.MemberInformationResponse; +import co.kirikiri.service.exception.ConflictException; +import co.kirikiri.service.exception.NotFoundException; +import co.kirikiri.service.mapper.AuthMapper; import co.kirikiri.service.mapper.MemberMapper; import java.net.URL; +import java.util.Map; +import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.core.env.Environment; import org.springframework.http.HttpMethod; @@ -27,44 +38,74 @@ @Service @Transactional(readOnly = true) @RequiredArgsConstructor +@ExceptionConvert public class MemberService { private static final String DEFAULT_ORIGINAL_FILE_NAME_PROPERTY = "image.default.originalFileName"; private static final String DEFAULT_SERVER_FILE_PATH_PROPERTY = "image.default.serverFilePath"; private static final String DEFAULT_IMAGE_CONTENT_TYPE_PROPERTY = "image.default.imageContentType"; private static final String DEFAULT_EXTENSION = "image.default.extension"; + private static final int MAX_IDENTIFIER_LENGTH = 40; - private final MemberRepository memberRepository; private final Environment environment; private final NumberGenerator numberGenerator; private final FileService fileService; + private final TokenProvider tokenProvider; + private final MemberRepository memberRepository; + private final RefreshTokenRepository refreshTokenRepository; @Transactional public Long join(final MemberJoinRequest memberJoinRequest) { final MemberJoinDto memberJoinDto = MemberMapper.convertToMemberJoinDto(memberJoinRequest); checkIdentifierDuplicate(memberJoinDto.identifier()); - checkNicknameDuplicate(memberJoinDto.nickname()); final EncryptedPassword encryptedPassword = new EncryptedPassword(memberJoinDto.password()); - final MemberProfile memberProfile = new MemberProfile(memberJoinDto.gender(), - memberJoinDto.birthday(), memberJoinDto.phoneNumber()); + final MemberProfile memberProfile = new MemberProfile(memberJoinDto.gender(), memberJoinDto.email()); final Member member = new Member(memberJoinDto.identifier(), encryptedPassword, memberJoinDto.nickname(), findDefaultMemberImage(), memberProfile); return memberRepository.save(member).getId(); } - private void checkNicknameDuplicate(final Nickname nickname) { - if (memberRepository.findByNickname(nickname).isPresent()) { - throw new ConflictException("이미 존재하는 닉네임입니다."); - } - } - private void checkIdentifierDuplicate(final Identifier identifier) { if (memberRepository.findByIdentifier(identifier).isPresent()) { throw new ConflictException("이미 존재하는 아이디입니다."); } } + @Transactional + public AuthenticationResponse oauthJoin(final OauthMemberJoinDto oauthMemberJoinDto) { + final MemberProfile memberProfile = new MemberProfile(Gender.valueOf(oauthMemberJoinDto.gender().name()), + oauthMemberJoinDto.email()); + final Identifier identifier = makeIdentifier(oauthMemberJoinDto); + final Nickname nickname = new Nickname(oauthMemberJoinDto.nickname()); + final Member member = new Member(identifier, oauthMemberJoinDto.oauthId(), nickname, findDefaultMemberImage(), + memberProfile); + memberRepository.save(member); + return makeAuthenticationResponse(member); + } + + private Identifier makeIdentifier(final OauthMemberJoinDto oauthMemberJoinDto) { + final String originalIdentifier = oauthMemberJoinDto.email() + .split("@")[0]; + final String uuid = UUID.randomUUID().toString(); + final String identifierWithUUID = originalIdentifier + uuid; + if (identifierWithUUID.length() > MAX_IDENTIFIER_LENGTH) { + return new Identifier(identifierWithUUID.substring(0, MAX_IDENTIFIER_LENGTH)); + } + return new Identifier(identifierWithUUID); + } + + private AuthenticationResponse makeAuthenticationResponse(final Member member) { + final String refreshToken = tokenProvider.createRefreshToken(member.getIdentifier().getValue(), Map.of()); + saveRefreshToken(refreshToken, member); + final String accessToken = tokenProvider.createAccessToken(member.getIdentifier().getValue(), Map.of()); + return AuthMapper.convertToAuthenticationResponse(refreshToken, accessToken); + } + + private void saveRefreshToken(final String refreshToken, final Member member) { + refreshTokenRepository.save(refreshToken, member.getIdentifier().getValue()); + } + private MemberImage findDefaultMemberImage() { final String defaultOriginalFileName = environment.getProperty(DEFAULT_ORIGINAL_FILE_NAME_PROPERTY); final String defaultServerFilePath = environment.getProperty(DEFAULT_SERVER_FILE_PATH_PROPERTY); @@ -88,7 +129,7 @@ public MemberInformationDto makeMemberInformationDto(final Member member) { final URL imageUrl = fileService.generateUrl(memberImage.getServerFilePath(), HttpMethod.GET); return new MemberInformationDto(member.getId(), member.getNickname().getValue(), imageUrl.toExternalForm(), memberProfile.getGender().name(), member.getIdentifier().getValue(), - memberProfile.getPhoneNumber(), memberProfile.getBirthday()); + memberProfile.getEmail()); } private Member findMemberInformationByIdentifier(final String identifier) { diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/RoadmapCreateEventListener.java b/backend/kirikiri/src/main/java/co/kirikiri/service/roadmap/RoadmapCreateEventListener.java similarity index 92% rename from backend/kirikiri/src/main/java/co/kirikiri/service/RoadmapCreateEventListener.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/roadmap/RoadmapCreateEventListener.java index 8c22e011e..833c59de6 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/RoadmapCreateEventListener.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/roadmap/RoadmapCreateEventListener.java @@ -1,4 +1,4 @@ -package co.kirikiri.service; +package co.kirikiri.service.roadmap; import co.kirikiri.domain.ImageContentType; import co.kirikiri.domain.roadmap.Roadmap; @@ -6,21 +6,26 @@ import co.kirikiri.domain.roadmap.RoadmapNode; import co.kirikiri.domain.roadmap.RoadmapNodeImage; import co.kirikiri.domain.roadmap.RoadmapNodeImages; -import co.kirikiri.exception.BadRequestException; -import co.kirikiri.exception.ServerException; import co.kirikiri.persistence.roadmap.RoadmapContentRepository; +import co.kirikiri.service.FilePathGenerator; +import co.kirikiri.service.FileService; +import co.kirikiri.service.ImageDirType; +import co.kirikiri.service.aop.ExceptionConvert; import co.kirikiri.service.dto.FileInformation; import co.kirikiri.service.dto.roadmap.RoadmapNodeSaveDto; import co.kirikiri.service.event.RoadmapCreateEvent; +import co.kirikiri.service.exception.BadRequestException; +import co.kirikiri.service.exception.ServerException; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.event.TransactionalEventListener; -import java.util.List; @Service @RequiredArgsConstructor +@ExceptionConvert public class RoadmapCreateEventListener { private final RoadmapContentRepository roadmapContentRepository; diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/RoadmapCreateService.java b/backend/kirikiri/src/main/java/co/kirikiri/service/roadmap/RoadmapCreateService.java similarity index 87% rename from backend/kirikiri/src/main/java/co/kirikiri/service/RoadmapCreateService.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/roadmap/RoadmapCreateService.java index 348b45f38..77bce647b 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/RoadmapCreateService.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/roadmap/RoadmapCreateService.java @@ -1,4 +1,4 @@ -package co.kirikiri.service; +package co.kirikiri.service.roadmap; import co.kirikiri.domain.goalroom.GoalRoom; import co.kirikiri.domain.goalroom.GoalRoomMember; @@ -15,33 +15,38 @@ import co.kirikiri.domain.roadmap.RoadmapTag; import co.kirikiri.domain.roadmap.RoadmapTags; import co.kirikiri.domain.roadmap.vo.RoadmapTagName; -import co.kirikiri.exception.AuthenticationException; -import co.kirikiri.exception.BadRequestException; -import co.kirikiri.exception.ForbiddenException; -import co.kirikiri.exception.NotFoundException; import co.kirikiri.persistence.goalroom.GoalRoomMemberRepository; import co.kirikiri.persistence.goalroom.GoalRoomRepository; import co.kirikiri.persistence.member.MemberRepository; import co.kirikiri.persistence.roadmap.RoadmapCategoryRepository; import co.kirikiri.persistence.roadmap.RoadmapRepository; import co.kirikiri.persistence.roadmap.RoadmapReviewRepository; +import co.kirikiri.service.aop.ExceptionConvert; import co.kirikiri.service.dto.roadmap.RoadmapNodeSaveDto; import co.kirikiri.service.dto.roadmap.RoadmapReviewDto; import co.kirikiri.service.dto.roadmap.RoadmapSaveDto; import co.kirikiri.service.dto.roadmap.RoadmapTagSaveDto; +import co.kirikiri.service.dto.roadmap.request.RoadmapCategorySaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapReviewSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapSaveRequest; import co.kirikiri.service.event.RoadmapCreateEvent; +import co.kirikiri.service.exception.AuthenticationException; +import co.kirikiri.service.exception.BadRequestException; +import co.kirikiri.service.exception.ConflictException; +import co.kirikiri.service.exception.ForbiddenException; +import co.kirikiri.service.exception.NotFoundException; import co.kirikiri.service.mapper.RoadmapMapper; +import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; @Service @Transactional @RequiredArgsConstructor +@ExceptionConvert public class RoadmapCreateService { private final MemberRepository memberRepository; @@ -52,6 +57,7 @@ public class RoadmapCreateService { private final RoadmapCategoryRepository roadmapCategoryRepository; private final ApplicationEventPublisher applicationEventPublisher; + @CacheEvict(value = "roadmapList", allEntries = true) public Long create(final RoadmapSaveRequest request, final String identifier) { final Member member = findMemberByIdentifier(identifier); final RoadmapCategory roadmapCategory = findRoadmapCategoryById(request.categoryId()); @@ -152,6 +158,7 @@ private void validateReviewCount(final Roadmap roadmap, final Member member) { } } + @CacheEvict(value = {"roadmapList", "roadmap"}, allEntries = true) public void deleteRoadmap(final String identifier, final Long roadmapId) { final Roadmap roadmap = findRoadmapById(roadmapId); validateRoadmapCreator(roadmapId, identifier); @@ -167,4 +174,14 @@ private void validateRoadmapCreator(final Long roadmapId, final String identifie roadmapRepository.findByIdAndMemberIdentifier(roadmapId, identifier) .orElseThrow(() -> new ForbiddenException("해당 로드맵을 생성한 사용자가 아닙니다.")); } + + @CacheEvict(value = "categoryList", allEntries = true) + public void createRoadmapCategory(final RoadmapCategorySaveRequest roadmapCategorySaveRequest) { + final RoadmapCategory roadmapCategory = RoadmapMapper.convertToRoadmapCategory(roadmapCategorySaveRequest); + roadmapCategoryRepository.findByName(roadmapCategory.getName()) + .ifPresent(it -> { + throw new ConflictException("이미 존재하는 이름의 카테고리입니다."); + }); + roadmapCategoryRepository.save(roadmapCategory); + } } diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/RoadmapReadService.java b/backend/kirikiri/src/main/java/co/kirikiri/service/roadmap/RoadmapReadService.java similarity index 94% rename from backend/kirikiri/src/main/java/co/kirikiri/service/RoadmapReadService.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/roadmap/RoadmapReadService.java index 8b117639f..7afa4fce1 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/RoadmapReadService.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/roadmap/RoadmapReadService.java @@ -1,4 +1,4 @@ -package co.kirikiri.service; +package co.kirikiri.service.roadmap; import co.kirikiri.domain.goalroom.GoalRoom; import co.kirikiri.domain.member.Member; @@ -10,7 +10,6 @@ import co.kirikiri.domain.roadmap.RoadmapNodes; import co.kirikiri.domain.roadmap.RoadmapReview; import co.kirikiri.domain.roadmap.RoadmapTags; -import co.kirikiri.exception.NotFoundException; import co.kirikiri.persistence.dto.RoadmapOrderType; import co.kirikiri.persistence.dto.RoadmapSearchDto; import co.kirikiri.persistence.goalroom.GoalRoomRepository; @@ -20,6 +19,8 @@ import co.kirikiri.persistence.roadmap.RoadmapContentRepository; import co.kirikiri.persistence.roadmap.RoadmapRepository; import co.kirikiri.persistence.roadmap.RoadmapReviewRepository; +import co.kirikiri.service.FileService; +import co.kirikiri.service.aop.ExceptionConvert; import co.kirikiri.service.dto.CustomScrollRequest; import co.kirikiri.service.dto.goalroom.RoadmapGoalRoomDto; import co.kirikiri.service.dto.goalroom.RoadmapGoalRoomScrollDto; @@ -42,12 +43,14 @@ import co.kirikiri.service.dto.roadmap.response.RoadmapGoalRoomResponses; import co.kirikiri.service.dto.roadmap.response.RoadmapResponse; import co.kirikiri.service.dto.roadmap.response.RoadmapReviewResponse; +import co.kirikiri.service.exception.NotFoundException; import co.kirikiri.service.mapper.GoalRoomMapper; import co.kirikiri.service.mapper.RoadmapMapper; import co.kirikiri.service.mapper.ScrollResponseMapper; import java.net.URL; import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -55,6 +58,7 @@ @Service @Transactional(readOnly = true) @RequiredArgsConstructor +@ExceptionConvert public class RoadmapReadService { private final RoadmapRepository roadmapRepository; @@ -65,6 +69,7 @@ public class RoadmapReadService { private final MemberRepository memberRepository; private final FileService fileService; + @Cacheable(value = "roadmap", keyGenerator = "cacheKeyGenerator", cacheManager = "redisCacheManager") public RoadmapResponse findRoadmap(final Long id) { final Roadmap roadmap = findRoadmapById(id); final RoadmapContent recentRoadmapContent = findRecentContent(roadmap); @@ -125,6 +130,7 @@ private RoadmapContent findRecentContent(final Roadmap roadmap) { .orElseThrow(() -> new NotFoundException("로드맵에 컨텐츠가 존재하지 않습니다.")); } + @Cacheable(value = "roadmapList", keyGenerator = "cacheKeyGenerator", cacheManager = "redisCacheManager") public RoadmapForListResponses findRoadmapsByOrderType(final Long categoryId, final RoadmapOrderTypeRequest orderTypeRequest, final CustomScrollRequest scrollRequest) { @@ -145,7 +151,7 @@ private RoadmapCategory findCategoryById(final Long categoryId) { .orElseThrow(() -> new NotFoundException("존재하지 않는 카테고리입니다. categoryId = " + categoryId)); } - public RoadmapForListScrollDto makeRoadmapForListScrollDto(final List roadmaps, final int requestSize) { + private RoadmapForListScrollDto makeRoadmapForListScrollDto(final List roadmaps, final int requestSize) { final List roadmapForListDtos = roadmaps.stream() .map(this::makeRoadmapForListDto) .toList(); @@ -197,6 +203,7 @@ public RoadmapForListResponses search(final RoadmapOrderTypeRequest orderTypeReq return RoadmapMapper.convertRoadmapResponses(roadmapForListScrollDto); } + @Cacheable(value = "categoryList", keyGenerator = "cacheKeyGenerator", cacheManager = "redisCacheManager") public List findAllRoadmapCategories() { final List roadmapCategories = roadmapCategoryRepository.findAll(); return RoadmapMapper.convertRoadmapCategoryResponses(roadmapCategories); @@ -220,9 +227,9 @@ public RoadmapGoalRoomResponses findRoadmapGoalRoomsByOrderType(final Long roadm final CustomScrollRequest scrollRequest) { final Roadmap roadmap = findRoadmapById(roadmapId); final RoadmapGoalRoomsOrderType orderType = GoalRoomMapper.convertToGoalRoomOrderType(orderTypeDto); - final List goalRoomsWithPendingMembers = goalRoomRepository.findGoalRoomsWithPendingMembersByRoadmapAndCond( + final List goalRooms = goalRoomRepository.findGoalRoomsByRoadmapAndCond( roadmap, orderType, scrollRequest.lastId(), scrollRequest.size()); - final RoadmapGoalRoomScrollDto roadmapGoalRoomScrollDto = makeGoalRoomDtos(goalRoomsWithPendingMembers, + final RoadmapGoalRoomScrollDto roadmapGoalRoomScrollDto = makeGoalRoomDtos(goalRooms, scrollRequest.size()); return GoalRoomMapper.convertToRoadmapGoalRoomResponses(roadmapGoalRoomScrollDto); } @@ -239,7 +246,7 @@ public RoadmapGoalRoomScrollDto makeGoalRoomDtos(final List goalRooms, private RoadmapGoalRoomDto makeGoalRoomDto(final GoalRoom goalRoom) { final Member goalRoomLeader = goalRoom.findGoalRoomLeader(); - return new RoadmapGoalRoomDto(goalRoom.getId(), goalRoom.getName().getValue(), + return new RoadmapGoalRoomDto(goalRoom.getId(), goalRoom.getName().getValue(), goalRoom.getStatus(), goalRoom.getCurrentMemberCount(), goalRoom.getLimitedMemberCount().getValue(), goalRoom.getCreatedAt(), goalRoom.getStartDate(), goalRoom.getEndDate(), makeMemberDto(goalRoomLeader)); diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/GoalRoomScheduler.java b/backend/kirikiri/src/main/java/co/kirikiri/service/scheduler/GoalRoomScheduler.java similarity index 61% rename from backend/kirikiri/src/main/java/co/kirikiri/service/GoalRoomScheduler.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/scheduler/GoalRoomScheduler.java index 66bb9eed2..71792ac6b 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/GoalRoomScheduler.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/scheduler/GoalRoomScheduler.java @@ -1,9 +1,13 @@ -package co.kirikiri.service; +package co.kirikiri.service.scheduler; +import co.kirikiri.domain.BaseEntity; import co.kirikiri.domain.goalroom.GoalRoom; import co.kirikiri.domain.goalroom.GoalRoomMember; import co.kirikiri.domain.goalroom.GoalRoomPendingMember; +import co.kirikiri.persistence.goalroom.GoalRoomMemberRepository; +import co.kirikiri.persistence.goalroom.GoalRoomPendingMemberRepository; import co.kirikiri.persistence.goalroom.GoalRoomRepository; +import co.kirikiri.service.aop.ExceptionConvert; import java.time.LocalDate; import java.util.List; import lombok.RequiredArgsConstructor; @@ -14,25 +18,29 @@ @Component @Transactional @RequiredArgsConstructor +@ExceptionConvert public class GoalRoomScheduler { private final GoalRoomRepository goalRoomRepository; + private final GoalRoomPendingMemberRepository goalRoomPendingMemberRepository; + private final GoalRoomMemberRepository goalRoomMemberRepository; @Scheduled(cron = "0 0 0 * * *") public void startGoalRooms() { - final List goalRoomsToStart = goalRoomRepository.findAllByStartDate(LocalDate.now()); + final List goalRoomsToStart = goalRoomRepository.findAllRecruitingGoalRoomsByStartDateEarlierThan( + LocalDate.now()); for (final GoalRoom goalRoom : goalRoomsToStart) { final List goalRoomPendingMembers = goalRoom.getGoalRoomPendingMembers().getValues(); - saveGoalRoomMemberFromPendingMembers(goalRoomPendingMembers, goalRoom); + saveGoalRoomMemberFromPendingMembers(goalRoomPendingMembers); goalRoom.start(); } } - private void saveGoalRoomMemberFromPendingMembers(final List goalRoomPendingMembers, - final GoalRoom goalRoom) { + private void saveGoalRoomMemberFromPendingMembers(final List goalRoomPendingMembers) { final List goalRoomMembers = makeGoalRoomMembers(goalRoomPendingMembers); - goalRoom.addAllGoalRoomMembers(goalRoomMembers); - goalRoom.deleteAllPendingMembers(); + goalRoomMemberRepository.saveAllInBatch(goalRoomMembers); + final List ids = makeGoalRoomPendingMemberIds(goalRoomPendingMembers); + goalRoomPendingMemberRepository.deleteAllByIdIn(ids); } private List makeGoalRoomMembers(final List goalRoomPendingMembers) { @@ -42,9 +50,14 @@ private List makeGoalRoomMembers(final List makeGoalRoomPendingMemberIds(final List goalRoomPendingMembers) { + return goalRoomPendingMembers.stream() + .map(BaseEntity::getId) + .toList(); } @Scheduled(cron = "0 0 4 * * *") diff --git a/backend/kirikiri/src/main/java/co/kirikiri/service/RoadmapScheduler.java b/backend/kirikiri/src/main/java/co/kirikiri/service/scheduler/RoadmapScheduler.java similarity index 94% rename from backend/kirikiri/src/main/java/co/kirikiri/service/RoadmapScheduler.java rename to backend/kirikiri/src/main/java/co/kirikiri/service/scheduler/RoadmapScheduler.java index 2d58282be..92af456a9 100644 --- a/backend/kirikiri/src/main/java/co/kirikiri/service/RoadmapScheduler.java +++ b/backend/kirikiri/src/main/java/co/kirikiri/service/scheduler/RoadmapScheduler.java @@ -1,10 +1,11 @@ -package co.kirikiri.service; +package co.kirikiri.service.scheduler; import co.kirikiri.domain.goalroom.GoalRoom; import co.kirikiri.domain.roadmap.Roadmap; import co.kirikiri.domain.roadmap.RoadmapStatus; import co.kirikiri.persistence.goalroom.GoalRoomRepository; import co.kirikiri.persistence.roadmap.RoadmapRepository; +import co.kirikiri.service.aop.ExceptionConvert; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; @@ -14,6 +15,7 @@ @Component @Transactional @RequiredArgsConstructor +@ExceptionConvert public class RoadmapScheduler { private static final int DELETE_AFTER_MONTH = 3; diff --git a/backend/kirikiri/src/main/resources/db/migration/V1__init.sql b/backend/kirikiri/src/main/resources/db/migration/V1__init.sql index 83727cbed..8820f876b 100644 --- a/backend/kirikiri/src/main/resources/db/migration/V1__init.sql +++ b/backend/kirikiri/src/main/resources/db/migration/V1__init.sql @@ -7,7 +7,7 @@ create table member_profile created_at datetime(6) not null, updated_at datetime(6) not null, primary key (id) -) engine=InnoDB; +) engine = InnoDB; create table member_image ( @@ -16,7 +16,7 @@ create table member_image original_file_name varchar(100) not null, server_file_path varchar(255) not null, primary key (id) -) engine=InnoDB; +) engine = InnoDB; create table member ( @@ -25,8 +25,8 @@ create table member password varchar(255) not null, salt varchar(255) not null, nickname varchar(15) not null, - created_at datetime(6) not null, - updated_at datetime(6) not null, + created_at datetime(6) not null, + updated_at datetime(6) not null, member_profile_id bigint not null, member_image_id bigint not null, primary key (id), @@ -38,26 +38,26 @@ create table member foreign key (member_profile_id) references member_profile (id), constraint FK_member_member_image_id foreign key (member_image_id) references member_image (id) -) engine=InnoDB; +) engine = InnoDB; create table refresh_token ( id bigint not null auto_increment, token varchar(255) not null, - expired_at datetime(6) not null, + expired_at datetime(6) not null, is_revoked bit not null, member_id bigint not null, primary key (id), constraint FK_refresh_token_member_id foreign key (member_id) references member (id) -) engine=InnoDB; +) engine = InnoDB; create table roadmap_category ( id bigint not null auto_increment, name varchar(15) not null, primary key (id) -) engine=InnoDB; +) engine = InnoDB; create table roadmap ( @@ -67,7 +67,7 @@ create table roadmap difficulty varchar(30) not null, required_period integer not null, status varchar(10) not null, - created_at datetime(6) not null, + created_at datetime(6) not null, category_id bigint not null, member_id bigint not null, primary key (id), @@ -75,19 +75,19 @@ create table roadmap foreign key (category_id) references roadmap_category (id), constraint FK_roadmap_member_id foreign key (member_id) references member (id) -) engine=InnoDB; +) engine = InnoDB; create table roadmap_content ( - id bigint not null auto_increment, + id bigint not null auto_increment, content varchar(2200), created_at datetime(6) not null, updated_at datetime(6) not null, - roadmap_id bigint not null, + roadmap_id bigint not null, primary key (id), constraint FK_roadmap_content_roadmap_id foreign key (roadmap_id) references roadmap (id) -) engine=InnoDB; +) engine = InnoDB; create table roadmap_node ( @@ -98,7 +98,7 @@ create table roadmap_node primary key (id), constraint FK_roadmap_node_roadmap_content_id foreign key (roadmap_content_id) references roadmap_content (id) -) engine=InnoDB; +) engine = InnoDB; create table roadmap_node_image ( @@ -110,7 +110,7 @@ create table roadmap_node_image primary key (id), constraint FK_roadmap_node_image_roadmap_node_id foreign key (roadmap_node_id) references roadmap_node (id) -) engine=InnoDB; +) engine = InnoDB; create table goal_room ( @@ -126,7 +126,7 @@ create table goal_room primary key (id), constraint FK_goal_room_roadmap_content_id foreign key (roadmap_content_id) references roadmap_content (id) -) engine=InnoDB; +) engine = InnoDB; create table goal_room_pending_member ( @@ -140,7 +140,7 @@ create table goal_room_pending_member foreign key (goal_room_id) references goal_room (id), constraint FK_goal_room_pending_member_member_id foreign key (member_id) references member (id) -) engine=InnoDB; +) engine = InnoDB; create table goal_room_member ( @@ -155,7 +155,7 @@ create table goal_room_member foreign key (goal_room_id) references goal_room (id), constraint FK_goal_room_member_member_id foreign key (member_id) references member (id) -) engine=InnoDB; +) engine = InnoDB; create table goal_room_to_do ( @@ -163,13 +163,13 @@ create table goal_room_to_do content varchar(300) not null, start_date date not null, end_date date not null, - created_at datetime(6) not null, - updated_at datetime(6) not null, + created_at datetime(6) not null, + updated_at datetime(6) not null, goal_room_id bigint not null, primary key (id), constraint FK_goal_room_to_do_goal_room_id foreign key (goal_room_id) references goal_room (id) -) engine=InnoDB; +) engine = InnoDB; create table goal_room_roadmap_node ( @@ -184,7 +184,7 @@ create table goal_room_roadmap_node foreign key (roadmap_node_id) references roadmap_node (id), constraint goal_room_roadmap_node_goal_room_id foreign key (goal_room_id) references goal_room (id) -) engine=InnoDB; +) engine = InnoDB; create table check_feed ( @@ -201,23 +201,23 @@ create table check_feed foreign key (goal_room_roadmap_node_id) references goal_room_roadmap_node (id), constraint FK_check_feed_goal_room_member_id foreign key (goal_room_member_id) references goal_room_member (id) -) engine=InnoDB; +) engine = InnoDB; create table roadmap_review ( - id bigint not null auto_increment, - rate float(53) not null, + id bigint not null auto_increment, + rate float(53) not null, content varchar(1200), created_at datetime(6) not null, updated_at datetime(6) not null, - member_id bigint not null, - roadmap_id bigint not null, + member_id bigint not null, + roadmap_id bigint not null, primary key (id), constraint FK_roadmap_review_roadmap_id foreign key (roadmap_id) references roadmap (id), constraint FK_roadmap_review_member_id foreign key (member_id) references member (id) -) engine=InnoDB; +) engine = InnoDB; create table roadmap_tag ( @@ -227,7 +227,7 @@ create table roadmap_tag primary key (id), constraint FK_roadmap_tag_roadmap_id foreign key (roadmap_id) references roadmap (id) -) engine=InnoDB; +) engine = InnoDB; create table goal_room_to_do_check ( @@ -239,4 +239,4 @@ create table goal_room_to_do_check foreign key (goal_room_member_id) references goal_room_member (id), constraint FK_goal_room_to_do_check_goal_room_to_do_id foreign key (goal_room_to_do_id) references goal_room_to_do (id) -) engine=InnoDB; +) engine = InnoDB; diff --git a/backend/kirikiri/src/main/resources/db/migration/V2__alter_member_and_member_profile_table.sql b/backend/kirikiri/src/main/resources/db/migration/V2__alter_member_and_member_profile_table.sql new file mode 100644 index 000000000..449938fe6 --- /dev/null +++ b/backend/kirikiri/src/main/resources/db/migration/V2__alter_member_and_member_profile_table.sql @@ -0,0 +1,17 @@ +ALTER TABLE member + MODIFY COLUMN nickname varchar(30) NOT NULL; + +ALTER TABLE member + MODIFY COLUMN password varchar(255) NULL; + +ALTER TABLE member + ADD COLUMN oauth_id varchar(255) NULL; + +ALTER TABLE member_profile + DROP COLUMN phone_number; + +ALTER TABLE member_profile + DROP COLUMN birthday; + +ALTER TABLE member_profile + ADD COLUMN email varchar(100) NULL; diff --git a/backend/kirikiri/src/main/resources/db/migration/V3__modify_salt_null_and_email_not_null.sql b/backend/kirikiri/src/main/resources/db/migration/V3__modify_salt_null_and_email_not_null.sql new file mode 100644 index 000000000..4a00d8d46 --- /dev/null +++ b/backend/kirikiri/src/main/resources/db/migration/V3__modify_salt_null_and_email_not_null.sql @@ -0,0 +1,5 @@ +ALTER TABLE member + MODIFY COLUMN salt VARCHAR (255) NULL; + +ALTER TABLE member_profile + MODIFY COLUMN email VARCHAR (100) NOT NULL; diff --git a/backend/kirikiri/src/main/resources/db/migration/V4__drop_refresh_token_table.sql b/backend/kirikiri/src/main/resources/db/migration/V4__drop_refresh_token_table.sql new file mode 100644 index 000000000..994308065 --- /dev/null +++ b/backend/kirikiri/src/main/resources/db/migration/V4__drop_refresh_token_table.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS refresh_token; diff --git a/backend/kirikiri/src/main/resources/logback-spring.xml b/backend/kirikiri/src/main/resources/logback-spring.xml index af830e368..09fb905e2 100644 --- a/backend/kirikiri/src/main/resources/logback-spring.xml +++ b/backend/kirikiri/src/main/resources/logback-spring.xml @@ -27,7 +27,7 @@ ${LOG_PATH}/%d{yyyy-MM-dd}/${LOG_FILE_NAME}_%i.log 10MB - 30 + 10 ${LOG_PATTERN} diff --git a/backend/kirikiri/src/main/resources/properties b/backend/kirikiri/src/main/resources/properties index 41b18591e..2fdc5b50c 160000 --- a/backend/kirikiri/src/main/resources/properties +++ b/backend/kirikiri/src/main/resources/properties @@ -1 +1 @@ -Subproject commit 41b18591e522e5fb41069236a5fa7756997ef3a7 +Subproject commit 2fdc5b50cd9c5095f16c7b28ad1275c60289f930 diff --git a/backend/kirikiri/src/test/java/co/kirikiri/common/interceptor/AuthInterceptorTest.java b/backend/kirikiri/src/test/java/co/kirikiri/common/interceptor/AuthInterceptorTest.java index 9c0889d96..606505846 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/common/interceptor/AuthInterceptorTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/common/interceptor/AuthInterceptorTest.java @@ -6,8 +6,8 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; -import co.kirikiri.exception.AuthenticationException; -import co.kirikiri.service.AuthService; +import co.kirikiri.service.auth.AuthService; +import co.kirikiri.service.exception.AuthenticationException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; diff --git a/backend/kirikiri/src/test/java/co/kirikiri/common/resolver/MemberIdentifierArgumentResolverTest.java b/backend/kirikiri/src/test/java/co/kirikiri/common/resolver/MemberIdentifierArgumentResolverTest.java index dfe250b02..c9843407f 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/common/resolver/MemberIdentifierArgumentResolverTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/common/resolver/MemberIdentifierArgumentResolverTest.java @@ -5,8 +5,10 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; -import co.kirikiri.exception.AuthenticationException; -import co.kirikiri.service.AuthService; +import co.kirikiri.common.interceptor.Authenticated; +import co.kirikiri.service.auth.AuthService; +import co.kirikiri.service.exception.AuthenticationException; +import co.kirikiri.service.exception.ServerException; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -50,6 +52,8 @@ class MemberIdentifierArgumentResolverTest { .thenReturn(String.class); when(parameter.hasParameterAnnotation(MemberIdentifier.class)) .thenReturn(true); + when(parameter.hasMethodAnnotation(Authenticated.class)) + .thenReturn(true); //when final boolean result = memberIdentifierArgumentResolver.supportsParameter(parameter); @@ -63,6 +67,8 @@ class MemberIdentifierArgumentResolverTest { //given Mockito.>when(parameter.getParameterType()) .thenReturn(List.class); + when(parameter.hasMethodAnnotation(Authenticated.class)) + .thenReturn(true); //when final boolean result = memberIdentifierArgumentResolver.supportsParameter(parameter); @@ -78,6 +84,8 @@ class MemberIdentifierArgumentResolverTest { .thenReturn(String.class); when(parameter.hasParameterAnnotation(MemberIdentifier.class)) .thenReturn(false); + when(parameter.hasMethodAnnotation(Authenticated.class)) + .thenReturn(true); //when final boolean result = memberIdentifierArgumentResolver.supportsParameter(parameter); @@ -86,6 +94,19 @@ class MemberIdentifierArgumentResolverTest { assertThat(result).isFalse(); } + @Test + void String_타입이고_Authenticated가_붙지_않은_인자인_경우_예외가_발생한다() { + //given + when(parameter.hasMethodAnnotation(Authenticated.class)) + .thenReturn(false); + + //when + //then + assertThatThrownBy(() -> memberIdentifierArgumentResolver.supportsParameter(parameter)) + .isInstanceOf(ServerException.class) + .hasMessageContaining("MemberIdentifier는 인증된 사용자만 사용 가능합니다. (@Authenticated)"); + } + @Test void 정상적으로_토큰이_들어온_경우_토큰을_인증한다() { // given diff --git a/backend/kirikiri/src/test/java/co/kirikiri/common/resolver/RoadmapSaveArgumentResolverTest.java b/backend/kirikiri/src/test/java/co/kirikiri/common/resolver/RoadmapSaveArgumentResolverTest.java index 757128140..80973fc0f 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/common/resolver/RoadmapSaveArgumentResolverTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/common/resolver/RoadmapSaveArgumentResolverTest.java @@ -4,9 +4,9 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.when; -import co.kirikiri.exception.BadRequestException; import co.kirikiri.service.dto.member.request.MemberJoinRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapSaveRequest; +import co.kirikiri.service.exception.BadRequestException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import javax.xml.validation.Validator; diff --git a/backend/kirikiri/src/test/java/co/kirikiri/controller/AuthCreateApiTest.java b/backend/kirikiri/src/test/java/co/kirikiri/controller/AuthCreateApiTest.java index 575a2aa23..8b1741f4c 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/controller/AuthCreateApiTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/controller/AuthCreateApiTest.java @@ -1,8 +1,10 @@ package co.kirikiri.controller; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.doThrow; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; @@ -12,12 +14,14 @@ import co.kirikiri.controller.helper.ControllerTestHelper; import co.kirikiri.controller.helper.FieldDescriptionHelper.FieldDescription; -import co.kirikiri.exception.AuthenticationException; -import co.kirikiri.service.AuthService; +import co.kirikiri.service.auth.AuthService; +import co.kirikiri.service.auth.NaverOauthService; import co.kirikiri.service.dto.ErrorResponse; +import co.kirikiri.service.dto.auth.OauthRedirectResponse; import co.kirikiri.service.dto.auth.request.LoginRequest; import co.kirikiri.service.dto.auth.request.ReissueTokenRequest; import co.kirikiri.service.dto.auth.response.AuthenticationResponse; +import co.kirikiri.service.exception.AuthenticationException; import com.fasterxml.jackson.core.type.TypeReference; import java.util.List; import org.junit.jupiter.api.Test; @@ -37,6 +41,9 @@ class AuthCreateApiTest extends ControllerTestHelper { @MockBean private AuthService authService; + @MockBean + private NaverOauthService naverOauthService; + @Test void 정상적으로_로그인에_성공한다() throws Exception { //given @@ -46,8 +53,8 @@ class AuthCreateApiTest extends ControllerTestHelper { given(authService.login(request)) .willReturn(expectedResponse); - final List requestFieldDescription = makeSuccessRequestFieldDescription(); - final List responseFieldDescription = makeSuccessResponseFieldDescription(); + final List requestFieldDescription = makeLoginSuccessRequestFieldDescription(); + final List responseFieldDescription = makeLoginSuccessResponseFieldDescription(); //when final MvcResult mvcResult = 로그인(jsonRequest, status().isOk()) @@ -258,6 +265,26 @@ class AuthCreateApiTest extends ControllerTestHelper { .isEqualTo(errorResponse); } + @Test + void 네이버_로그인_페이지를_정상적으로_반환한다() throws Exception { + // given + final OauthRedirectResponse expectedResponse = new OauthRedirectResponse("Naver_Login_Redirect_Page_URL", + "state"); + given(naverOauthService.makeOauthUrl()).willReturn(expectedResponse); + + 네이버_로그인_페이지(status().isOk()); + } + + @Test + void 네이버에서_콜백요청을_받아_사용자_정보를_반환한다() throws Exception { + // given + final AuthenticationResponse expectedResponse = new AuthenticationResponse("refresh_token", "access_token"); + given(naverOauthService.login(any())) + .willReturn(expectedResponse); + + 네이버_사용자_정보_요청(status().isOk()); + } + private ResultActions 로그인(final String jsonRequest, final ResultMatcher result) throws Exception { return mockMvc.perform(post(API_PREFIX + "/auth/login") .content(jsonRequest) @@ -276,7 +303,27 @@ class AuthCreateApiTest extends ControllerTestHelper { .andDo(print()); } - private List makeSuccessRequestFieldDescription() { + private ResultActions 네이버_로그인_페이지(final ResultMatcher result) throws Exception { + return mockMvc.perform(get(API_PREFIX + "/auth/oauth/naver") + .param("code", "code") + .param("state", "state") + .contentType(MediaType.APPLICATION_JSON) + .contextPath(API_PREFIX)) + .andExpect(result) + .andDo(print()); + } + + private ResultActions 네이버_사용자_정보_요청(final ResultMatcher result) throws Exception { + return mockMvc.perform(get(API_PREFIX + "/auth/login/oauth") + .param("code", "code") + .param("state", "state") + .contentType(MediaType.APPLICATION_JSON) + .contextPath(API_PREFIX)) + .andExpect(result) + .andDo(print()); + } + + private List makeLoginSuccessRequestFieldDescription() { return List.of( new FieldDescription("identifier", "사용자 아이디", "- 길이 : 4 ~ 20 +" + "\n" + @@ -288,7 +335,7 @@ private List makeSuccessRequestFieldDescription() { ); } - private List makeSuccessResponseFieldDescription() { + private List makeLoginSuccessResponseFieldDescription() { return List.of( new FieldDescription("refreshToken", "리프레시 토큰"), new FieldDescription("accessToken", "액세스 토큰") diff --git a/backend/kirikiri/src/test/java/co/kirikiri/controller/GoalRoomCreateApiTest.java b/backend/kirikiri/src/test/java/co/kirikiri/controller/GoalRoomCreateApiTest.java index b49c2a716..01b22f4ee 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/controller/GoalRoomCreateApiTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/controller/GoalRoomCreateApiTest.java @@ -26,15 +26,15 @@ import co.kirikiri.controller.helper.ControllerTestHelper; import co.kirikiri.controller.helper.FieldDescriptionHelper.FieldDescription; -import co.kirikiri.exception.BadRequestException; -import co.kirikiri.exception.NotFoundException; -import co.kirikiri.service.GoalRoomCreateService; -import co.kirikiri.service.GoalRoomReadService; import co.kirikiri.service.dto.ErrorResponse; import co.kirikiri.service.dto.goalroom.request.GoalRoomCreateRequest; import co.kirikiri.service.dto.goalroom.request.GoalRoomRoadmapNodeRequest; import co.kirikiri.service.dto.goalroom.request.GoalRoomTodoRequest; import co.kirikiri.service.dto.goalroom.response.GoalRoomToDoCheckResponse; +import co.kirikiri.service.exception.BadRequestException; +import co.kirikiri.service.exception.NotFoundException; +import co.kirikiri.service.goalroom.GoalRoomCreateService; +import co.kirikiri.service.goalroom.GoalRoomReadService; import com.fasterxml.jackson.core.type.TypeReference; import java.time.LocalDate; import java.util.ArrayList; @@ -66,8 +66,7 @@ class GoalRoomCreateApiTest extends ControllerTestHelper { void 정상적으로_골룸을_생성한다() throws Exception { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); given(goalRoomCreateService.create(any(), any())) .willReturn(1L); @@ -92,8 +91,7 @@ class GoalRoomCreateApiTest extends ControllerTestHelper { void 골룸_생성_시_요청에_빈값이_있을_경우() throws Exception { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(null, null, - null, new GoalRoomTodoRequest(null, null, null), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(null, null, null, null)))); + null, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(null, null, null, null)))); final String jsonRequest = objectMapper.writeValueAsString(request); //when @@ -103,24 +101,19 @@ null, new GoalRoomTodoRequest(null, null, null), //then final ErrorResponse roadmapCheckCountIdErrorResponse = new ErrorResponse("인증 횟수는 빈 값일 수 없습니다."); final ErrorResponse roadmapNodeIdErrorResponse = new ErrorResponse("로드맵 노드 아이디는 빈 값일 수 없습니다."); - final ErrorResponse goalRoomTodoContentErrorResponse = new ErrorResponse("투두의 컨텐츠는 빈 값일 수 없습니다."); final ErrorResponse limitedMemberCountErrorResponse = new ErrorResponse("골룸 제한 인원은 빈 값일 수 없습니다."); final ErrorResponse goalRoomNameErrorResponse = new ErrorResponse("골룸 이름을 빈 값일 수 없습니다."); final ErrorResponse roadmapContentIdErrorResponse = new ErrorResponse("로드맵 컨텐츠 아이디는 빈 값일 수 없습니다."); final ErrorResponse goalRoomNodeStartDateErrorResponse = new ErrorResponse("로드맵 노드 시작 날짜는 빈 값일 수 없습니다."); final ErrorResponse goalRoomNodeEndDateErrorResponse = new ErrorResponse("로드맵 노드 종료 날짜는 빈 값일 수 없습니다."); - final ErrorResponse goalRoomTodoStartDateErrorResponse = new ErrorResponse("골룸 투두 시작 날짜는 빈 값일 수 없습니다."); - final ErrorResponse goalRoomTodoEndDateErrorResponse = new ErrorResponse("골룸 투두 종료 날짜는 빈 값일 수 없습니다."); final List responses = jsonToClass(mvcResult, new TypeReference<>() { }); assertThat(responses).usingRecursiveComparison() .ignoringCollectionOrder() .isEqualTo(List.of(roadmapCheckCountIdErrorResponse, roadmapNodeIdErrorResponse, - goalRoomTodoContentErrorResponse, limitedMemberCountErrorResponse, - goalRoomNameErrorResponse, roadmapContentIdErrorResponse, - goalRoomNodeStartDateErrorResponse, goalRoomNodeEndDateErrorResponse, - goalRoomTodoStartDateErrorResponse, goalRoomTodoEndDateErrorResponse + limitedMemberCountErrorResponse, goalRoomNameErrorResponse, roadmapContentIdErrorResponse, + goalRoomNodeStartDateErrorResponse, goalRoomNodeEndDateErrorResponse )); } @@ -128,8 +121,7 @@ null, new GoalRoomTodoRequest(null, null, null), void 골룸_생성_시_로드맵이_존재하지_않을_경우() throws Exception { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); final String jsonRequest = objectMapper.writeValueAsString(request); doThrow(new NotFoundException("존재하지 않는 로드맵입니다.")) .when(goalRoomCreateService) @@ -151,8 +143,7 @@ null, new GoalRoomTodoRequest(null, null, null), void 골룸_생성_시_삭제된_로드맵_경우() throws Exception { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); final String jsonRequest = objectMapper.writeValueAsString(request); doThrow(new BadRequestException("삭제된 로드맵에 대해 골룸을 생성할 수 없습니다.")) .when(goalRoomCreateService) @@ -174,8 +165,7 @@ null, new GoalRoomTodoRequest(null, null, null), void 골룸_생성_시_로드맵의_노드_크기와_요청의_노드_크기가_일치하지_않을_경우() throws Exception { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); final String jsonRequest = objectMapper.writeValueAsString(request); doThrow(new BadRequestException("모든 노드에 대해 기간이 설정돼야 합니다.")) .when(goalRoomCreateService) @@ -196,8 +186,7 @@ null, new GoalRoomTodoRequest(null, null, null), void 골룸_생성_시_로드맵에_존재하지_않는_노드일_경우() throws Exception { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); final String jsonRequest = objectMapper.writeValueAsString(request); doThrow(new NotFoundException("로드맵에 존재하지 않는 노드입니다.")) .when(goalRoomCreateService) @@ -218,8 +207,7 @@ null, new GoalRoomTodoRequest(null, null, null), void 골룸_생성_시_존재하지_않는_회원일_경우() throws Exception { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); final String jsonRequest = objectMapper.writeValueAsString(request); doThrow(new NotFoundException("존재하지 않는 회원입니다.")) .when(goalRoomCreateService) @@ -236,56 +224,11 @@ null, new GoalRoomTodoRequest(null, null, null), assertThat(response).isEqualTo(expectedResponse); } - @Test - void 골룸_생성_시_골룸_투두의_시작_날짜보다_종료_날짜가_빠른_경우() throws Exception { - //given - final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TEN_DAY_LATER, TODAY), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); - final String jsonRequest = objectMapper.writeValueAsString(request); - doThrow(new BadRequestException("시작일은 종료일보다 후일 수 없습니다.")) - .when(goalRoomCreateService) - .create(any(), any()); - - //when - final MvcResult mvcResult = 골룸_생성(jsonRequest, status().isBadRequest()) - .andReturn(); - - //then - final ErrorResponse expectedResponse = new ErrorResponse("시작일은 종료일보다 후일 수 없습니다."); - final ErrorResponse response = jsonToClass(mvcResult, new TypeReference<>() { - }); - assertThat(response).isEqualTo(expectedResponse); - } - - @Test - void 골룸_생성_시_골룸_투두의_시작_날짜가_오늘보다_전일_경우() throws Exception { - //given - final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY.minusDays(10), TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); - final String jsonRequest = objectMapper.writeValueAsString(request); - doThrow(new BadRequestException("시작일은 오늘보다 전일 수 없습니다.")) - .when(goalRoomCreateService) - .create(any(), any()); - - //when - final MvcResult mvcResult = 골룸_생성(jsonRequest, status().isBadRequest()) - .andReturn(); - - //then - final ErrorResponse expectedResponse = new ErrorResponse("시작일은 오늘보다 전일 수 없습니다."); - final ErrorResponse response = jsonToClass(mvcResult, new TypeReference<>() { - }); - assertThat(response).isEqualTo(expectedResponse); - } - @Test void 골룸_생성_시_골룸_노드의_시작_날짜보다_종료_날짜가_빠른_경우() throws Exception { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TEN_DAY_LATER, TODAY)))); + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TEN_DAY_LATER, TODAY)))); final String jsonRequest = objectMapper.writeValueAsString(request); doThrow(new BadRequestException("시작일은 종료일보다 후일 수 없습니다.")) .when(goalRoomCreateService) @@ -306,7 +249,7 @@ null, new GoalRoomTodoRequest(null, null, null), void 골룸_생성_시_골룸_노드의_시작_날짜가_오늘보다_전일_경우() throws Exception { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY.minusDays(10), TEN_DAY_LATER)))); final String jsonRequest = objectMapper.writeValueAsString(request); doThrow(new BadRequestException("시작일은 오늘보다 전일 수 없습니다.")) @@ -328,8 +271,7 @@ null, new GoalRoomTodoRequest(null, null, null), void 골룸_생성_시_골룸_노드의_인증_횟수가_0보다_작을_경우() throws Exception { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 0, TODAY, TEN_DAY_LATER)))); + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 0, TODAY, TEN_DAY_LATER)))); final String jsonRequest = objectMapper.writeValueAsString(request); doThrow(new BadRequestException("골룸 노드의 인증 횟수는 0보다 커야합니다.")) .when(goalRoomCreateService) @@ -350,8 +292,7 @@ null, new GoalRoomTodoRequest(null, null, null), void 골룸_생성_시_골룸_노드의_인증_횟수가_기간보다_클_경우() throws Exception { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 11, TODAY, TEN_DAY_LATER)))); + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 11, TODAY, TEN_DAY_LATER)))); final String jsonRequest = objectMapper.writeValueAsString(request); doThrow(new BadRequestException("골룸 노드의 인증 횟수가 설정 기간보다 클 수 없습니다.")) .when(goalRoomCreateService) @@ -1261,15 +1202,11 @@ null, new GoalRoomTodoRequest(null, null, null), private List makeCreateGoalRoomSuccessRequestFieldDescription() { return List.of( - new FieldDescription("roadmapContentId", "로드맵 컨텐츠 id"), + new FieldDescription("roadmapContentId", "로드맵 컨텐츠 oauthId"), new FieldDescription("name", "골룸 이름", "- 길이 : 1 ~ 40"), new FieldDescription("limitedMemberCount", "최대 제한 인원", "- 길이 : 1 ~ 20"), - new FieldDescription("goalRoomTodo", "최초 골룸 투두"), - new FieldDescription("goalRoomTodo.content", "골룸 투두 컨텐츠", "- 길이 : 1 ~ 250"), - new FieldDescription("goalRoomTodo.startDate", "골룸 투두 시작일", "- yyyyMMdd 형식"), - new FieldDescription("goalRoomTodo.endDate", "골룸 투두 종료일", "- yyyyMMdd 형식"), new FieldDescription("goalRoomRoadmapNodeRequests", "골룸 노드 정보"), - new FieldDescription("goalRoomRoadmapNodeRequests[].roadmapNodeId", "설정할 로드맵 노드의 id"), + new FieldDescription("goalRoomRoadmapNodeRequests[].roadmapNodeId", "설정할 로드맵 노드의 oauthId"), new FieldDescription("goalRoomRoadmapNodeRequests[].checkCount", "골룸 노드의 인증 횟수"), new FieldDescription("goalRoomRoadmapNodeRequests[].startDate", "골룸 노드의 시작일", "- yyyyMMdd 형식"), new FieldDescription("goalRoomRoadmapNodeRequests[].endDate", "골룸 노드의 종료일", "- yyyyMMdd 형식") diff --git a/backend/kirikiri/src/test/java/co/kirikiri/controller/GoalRoomReadApiTest.java b/backend/kirikiri/src/test/java/co/kirikiri/controller/GoalRoomReadApiTest.java index 06c18fd8f..1ad346fbb 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/controller/GoalRoomReadApiTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/controller/GoalRoomReadApiTest.java @@ -20,11 +20,6 @@ import co.kirikiri.controller.helper.ControllerTestHelper; import co.kirikiri.domain.goalroom.GoalRoomStatus; -import co.kirikiri.exception.BadRequestException; -import co.kirikiri.exception.ForbiddenException; -import co.kirikiri.exception.NotFoundException; -import co.kirikiri.service.GoalRoomCreateService; -import co.kirikiri.service.GoalRoomReadService; import co.kirikiri.service.dto.ErrorResponse; import co.kirikiri.service.dto.goalroom.request.GoalRoomStatusTypeRequest; import co.kirikiri.service.dto.goalroom.response.CheckFeedResponse; @@ -32,6 +27,7 @@ import co.kirikiri.service.dto.goalroom.response.GoalRoomCheckFeedResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomMemberResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomResponse; +import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodeDetailResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodeResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodesResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomToDoCheckResponse; @@ -39,6 +35,11 @@ import co.kirikiri.service.dto.member.response.MemberGoalRoomForListResponse; import co.kirikiri.service.dto.member.response.MemberGoalRoomResponse; import co.kirikiri.service.dto.member.response.MemberResponse; +import co.kirikiri.service.exception.BadRequestException; +import co.kirikiri.service.exception.ForbiddenException; +import co.kirikiri.service.exception.NotFoundException; +import co.kirikiri.service.goalroom.GoalRoomCreateService; +import co.kirikiri.service.goalroom.GoalRoomReadService; import com.fasterxml.jackson.core.type.TypeReference; import java.time.LocalDate; import java.time.LocalDateTime; @@ -535,9 +536,11 @@ class GoalRoomReadApiTest extends ControllerTestHelper { void 골룸의_노드를_조회한다() throws Exception { // given final LocalDate today = LocalDate.now(); - final List goalRoomNodeResponses = List.of( - new GoalRoomRoadmapNodeResponse(1L, "골룸 노드 1", today, today.plusDays(10), 10), - new GoalRoomRoadmapNodeResponse(2L, "골룸 노드 2", today.plusDays(20), today.plusDays(30), 5)); + final List goalRoomNodeResponses = List.of( + new GoalRoomRoadmapNodeDetailResponse(1L, "골룸 노드 1", "골룸 노드 본문1", + List.of("image1-filepath", "image2-filepath"), today, today.plusDays(10), 10), + new GoalRoomRoadmapNodeDetailResponse(2L, "골룸 노드 2", "골룸 노드 본문2", + List.of("image1-filepath", "image2-filepath"), today.plusDays(20), today.plusDays(30), 5)); when(goalRoomReadService.findAllGoalRoomNodes(any(), any())) .thenReturn(goalRoomNodeResponses); @@ -558,6 +561,8 @@ class GoalRoomReadApiTest extends ControllerTestHelper { responseFields( fieldWithPath("[0].id").description("골룸 로드맵 노드 아이디"), fieldWithPath("[0].title").description("노드 제목"), + fieldWithPath("[0].description").description("노드 본문"), + fieldWithPath("[0].imageUrls[0]").description("노드 이미지 파일 경로"), fieldWithPath("[0].startDate").description("노드 시작 날짜"), fieldWithPath("[0].endDate").description("노드 종료 날짜"), fieldWithPath("[0].checkCount").description("인증 횟수") @@ -565,7 +570,7 @@ class GoalRoomReadApiTest extends ControllerTestHelper { .andReturn(); // then - final List response = jsonToClass(mvcResult, new TypeReference<>() { + final List response = jsonToClass(mvcResult, new TypeReference<>() { }); assertThat(response) diff --git a/backend/kirikiri/src/test/java/co/kirikiri/controller/MemberCreateApiTest.java b/backend/kirikiri/src/test/java/co/kirikiri/controller/MemberCreateApiTest.java index bd50249d1..0764ac644 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/controller/MemberCreateApiTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/controller/MemberCreateApiTest.java @@ -1,5 +1,6 @@ package co.kirikiri.controller; +import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_EMAIL; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doThrow; @@ -12,14 +13,13 @@ import co.kirikiri.controller.helper.ControllerTestHelper; import co.kirikiri.controller.helper.FieldDescriptionHelper.FieldDescription; -import co.kirikiri.exception.BadRequestException; -import co.kirikiri.exception.ConflictException; -import co.kirikiri.service.MemberService; import co.kirikiri.service.dto.ErrorResponse; import co.kirikiri.service.dto.member.request.GenderType; import co.kirikiri.service.dto.member.request.MemberJoinRequest; +import co.kirikiri.service.exception.BadRequestException; +import co.kirikiri.service.exception.ConflictException; +import co.kirikiri.service.member.MemberService; import com.fasterxml.jackson.core.type.TypeReference; -import java.time.LocalDate; import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -40,7 +40,7 @@ class MemberCreateApiTest extends ControllerTestHelper { void 정상적으로_회원가입에_성공한다() throws Exception { //given final MemberJoinRequest memberJoinRequest = new MemberJoinRequest("identifier1", "password1!", - "nickname", "010-1234-5678", GenderType.MALE, LocalDate.now()); + "nickname", GenderType.MALE, DEFAULT_EMAIL); final String jsonRequest = objectMapper.writeValueAsString(memberJoinRequest); //when @@ -57,7 +57,7 @@ class MemberCreateApiTest extends ControllerTestHelper { void 회원가입_시_아이디가_형식에_맞지않을때() throws Exception { //given final MemberJoinRequest memberJoinRequest = new MemberJoinRequest("identifier1@!#!@#", "password1!", - "nickname", "010-1234-5678", GenderType.MALE, LocalDate.now()); + "nickname", GenderType.MALE, DEFAULT_EMAIL); final String jsonRequest = objectMapper.writeValueAsString(memberJoinRequest); //when @@ -73,7 +73,7 @@ class MemberCreateApiTest extends ControllerTestHelper { void 회원가입_시_비밀번호가_형식에_맞지않을때() throws Exception { //given final MemberJoinRequest memberJoinRequest = new MemberJoinRequest("identifier1", "password1!₩", - "nickname", "010-1234-5678", GenderType.MALE, LocalDate.now()); + "nickname", GenderType.MALE, DEFAULT_EMAIL); final String jsonRequest = objectMapper.writeValueAsString(memberJoinRequest); //when @@ -89,7 +89,7 @@ class MemberCreateApiTest extends ControllerTestHelper { void 회원가입_시_닉네임이_형식에_맞지않을때() throws Exception { //given final MemberJoinRequest memberJoinRequest = new MemberJoinRequest("identifier1", "password1!", - "a", "010-1234-5678", GenderType.MALE, LocalDate.now()); + "a", GenderType.MALE, DEFAULT_EMAIL); final String jsonRequest = objectMapper.writeValueAsString(memberJoinRequest); //when @@ -102,10 +102,10 @@ class MemberCreateApiTest extends ControllerTestHelper { } @Test - void 회원가입_시_전화번호_형식에_맞지않을때() throws Exception { + void 회원가입_시_이메일_형식에_맞지않을때() throws Exception { //given final MemberJoinRequest memberJoinRequest = new MemberJoinRequest("identifier1", "password1!", - "nickname", "010-1234-56789", GenderType.MALE, LocalDate.now()); + "nickname", GenderType.MALE, "kirikiri"); final String jsonRequest = objectMapper.writeValueAsString(memberJoinRequest); //when @@ -118,7 +118,7 @@ class MemberCreateApiTest extends ControllerTestHelper { .andDo(print()) .andReturn(); - final ErrorResponse expectedResponse = new ErrorResponse("전화번호 형식이 맞지 않습니다."); + final ErrorResponse expectedResponse = new ErrorResponse("이메일 형식이 아닙니다."); final List responses = jsonToClass(mvcResult, new TypeReference<>() { }); @@ -129,7 +129,7 @@ class MemberCreateApiTest extends ControllerTestHelper { void 회원가입_시_아이디에_빈값이_들어올_때() throws Exception { //given final MemberJoinRequest memberJoinRequest = new MemberJoinRequest("", "password1!", - "nickname", "010-1234-5678", GenderType.MALE, LocalDate.now()); + "nickname", GenderType.MALE, DEFAULT_EMAIL); final String jsonRequest = objectMapper.writeValueAsString(memberJoinRequest); //when @@ -142,7 +142,7 @@ class MemberCreateApiTest extends ControllerTestHelper { .andDo(print()) .andReturn(); - final ErrorResponse expectedResponse = new ErrorResponse("아이디는 빈 값일 수 없습니다."); + final ErrorResponse expectedResponse = new ErrorResponse("형식에 맞지 않는 아이디입니다."); final List responses = jsonToClass(mvcResult, new TypeReference<>() { }); @@ -153,7 +153,7 @@ class MemberCreateApiTest extends ControllerTestHelper { void 회원가입_시_비밀번호에_빈값이_들어올_때() throws Exception { //given final MemberJoinRequest memberJoinRequest = new MemberJoinRequest("identifier", "", - "nickname", "010-1234-5678", GenderType.MALE, LocalDate.now()); + "nickname", GenderType.MALE, DEFAULT_EMAIL); final String jsonRequest = objectMapper.writeValueAsString(memberJoinRequest); //when @@ -177,7 +177,7 @@ class MemberCreateApiTest extends ControllerTestHelper { void 회원가입_시_닉네임에_빈값이_들어올_때() throws Exception { //given final MemberJoinRequest memberJoinRequest = new MemberJoinRequest("identifier", "identifier1!", - "", "010-1234-5678", GenderType.MALE, LocalDate.now()); + "", GenderType.MALE, DEFAULT_EMAIL); final String jsonRequest = objectMapper.writeValueAsString(memberJoinRequest); //when @@ -198,10 +198,10 @@ class MemberCreateApiTest extends ControllerTestHelper { } @Test - void 회원가입_시_전화번호에_빈값이_들어올_때() throws Exception { + void 회원가입_시_이메일에_빈값이_들어올_때() throws Exception { //given final MemberJoinRequest memberJoinRequest = new MemberJoinRequest("identifier", "password1!", - "nickname", "", GenderType.MALE, LocalDate.now()); + "nickname", GenderType.MALE, ""); final String jsonRequest = objectMapper.writeValueAsString(memberJoinRequest); //when @@ -214,21 +214,20 @@ class MemberCreateApiTest extends ControllerTestHelper { .andDo(print()) .andReturn(); - final ErrorResponse blankResponse = new ErrorResponse("전화번호는 빈 값일 수 없습니다."); - final ErrorResponse patternResponse = new ErrorResponse("전화번호 형식이 맞지 않습니다."); + final ErrorResponse patternResponse = new ErrorResponse("이메일은 빈 값일 수 없습니다."); final List responses = jsonToClass(mvcResult, new TypeReference<>() { }); assertThat(responses).usingRecursiveComparison() .ignoringCollectionOrder() - .isEqualTo(List.of(patternResponse, blankResponse)); + .isEqualTo(List.of(patternResponse)); } @Test - void 회원가입_시_아이디_비밀번호_닉네임_전화번호_필드에_빈값이_들어올_때() throws Exception { + void 회원가입_시_아이디_비밀번호_닉네임_이메일_필드에_빈값이_들어올_때() throws Exception { //given final MemberJoinRequest memberJoinRequest = new MemberJoinRequest("", "", - "", "", GenderType.MALE, LocalDate.now()); + "", GenderType.MALE, ""); final String jsonRequest = objectMapper.writeValueAsString(memberJoinRequest); //when @@ -241,25 +240,23 @@ class MemberCreateApiTest extends ControllerTestHelper { .andDo(print()) .andReturn(); - final ErrorResponse identifierResponse = new ErrorResponse("아이디는 빈 값일 수 없습니다."); + final ErrorResponse identifierResponse = new ErrorResponse("형식에 맞지 않는 아이디입니다."); final ErrorResponse passwordResponse = new ErrorResponse("비밀번호는 빈 값일 수 없습니다."); final ErrorResponse nicknameResponse = new ErrorResponse("닉네임은 빈 값일 수 없습니다."); - final ErrorResponse phoneNumberBlankResponse = new ErrorResponse("전화번호는 빈 값일 수 없습니다."); - final ErrorResponse phoneNumberPatternResponse = new ErrorResponse("전화번호 형식이 맞지 않습니다."); + final ErrorResponse emailResponse = new ErrorResponse("이메일은 빈 값일 수 없습니다."); final List responses = jsonToClass(mvcResult, new TypeReference<>() { }); assertThat(responses).usingRecursiveComparison() .ignoringCollectionOrder() - .isEqualTo(List.of(identifierResponse, passwordResponse, nicknameResponse, phoneNumberBlankResponse, - phoneNumberPatternResponse)); + .isEqualTo(List.of(identifierResponse, passwordResponse, nicknameResponse, emailResponse)); } @Test void 회원가입_시_중복된_아이디일_때() throws Exception { //given final MemberJoinRequest memberJoinRequest = new MemberJoinRequest("identifier1", "password1!", - "nickname", "010-1234-5678", GenderType.MALE, LocalDate.now()); + "nickname", GenderType.MALE, DEFAULT_EMAIL); final String jsonRequest = objectMapper.writeValueAsString(memberJoinRequest); //when @@ -275,7 +272,7 @@ class MemberCreateApiTest extends ControllerTestHelper { void 회원가입_시_중복된_닉네임일_때() throws Exception { //given final MemberJoinRequest memberJoinRequest = new MemberJoinRequest("identifier1", "password1!", - "nickname", "010-1234-5678", GenderType.MALE, LocalDate.now()); + "nickname", GenderType.MALE, DEFAULT_EMAIL); final String jsonRequest = objectMapper.writeValueAsString(memberJoinRequest); //when @@ -306,15 +303,10 @@ private List makeSuccessRequestFieldDescription() { "- 영어 소문자, 숫자, 특수문자 +" + "\n" + "- 특수문자[!,@,#,$,%,^,&,*,(,),~] 사용 가능"), new FieldDescription("nickname", "회원 닉네임", "- 길이 : 2 ~ 8"), - new FieldDescription("phoneNumber", "회원 휴대폰 번호", - "- 길이 : 13 +" + "\n" + - "- 번호 형식 : 010-xxxx-xxxx"), new FieldDescription("genderType", "회원 성별", - "- 길이 : 4 , 6 +" + "\n" + - "- MALE, FEMALE"), - new FieldDescription("birthday", "회원 생년월일", - "- 길이 : 6 +" + "\n" + - "- yyyyMMdd") + "- 길이 : 4 , 6 +" + "\n" + "- MALE, FEMALE"), + new FieldDescription("email", "회원 이메일", + "- 이메일 형식") ); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/controller/MemberReadApiTest.java b/backend/kirikiri/src/test/java/co/kirikiri/controller/MemberReadApiTest.java index e1c2e8836..cfb492596 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/controller/MemberReadApiTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/controller/MemberReadApiTest.java @@ -14,13 +14,12 @@ import co.kirikiri.controller.helper.ControllerTestHelper; import co.kirikiri.domain.member.Gender; -import co.kirikiri.exception.NotFoundException; -import co.kirikiri.service.MemberService; import co.kirikiri.service.dto.ErrorResponse; import co.kirikiri.service.dto.member.response.MemberInformationForPublicResponse; import co.kirikiri.service.dto.member.response.MemberInformationResponse; +import co.kirikiri.service.exception.NotFoundException; +import co.kirikiri.service.member.MemberService; import com.fasterxml.jackson.core.type.TypeReference; -import java.time.LocalDate; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -37,7 +36,7 @@ class MemberReadApiTest extends ControllerTestHelper { // given final MemberInformationResponse expected = new MemberInformationResponse(1L, "nickname", "serverFilePath", Gender.MALE.name(), - "identifier1", "010-1234-5678", LocalDate.now()); + "identifier1", "kirikiri1@email.com"); given(memberService.findMemberInformation(any())) .willReturn(expected); @@ -52,13 +51,12 @@ class MemberReadApiTest extends ControllerTestHelper { headerWithName(AUTHORIZATION).description("액세스 토큰") ), responseFields( - fieldWithPath("id").description("사용자 id (PK)"), + fieldWithPath("id").description("사용자 oauthId (PK)"), fieldWithPath("nickname").description("사용자 닉네임"), fieldWithPath("profileImageUrl").description("사용자 이미지 Url"), fieldWithPath("gender").description("사용자 성별"), fieldWithPath("identifier").description("사용자 아이디"), - fieldWithPath("phoneNumber").description("사용자 전화번호"), - fieldWithPath("birthday").description("사용자 생년월일") + fieldWithPath("email").description("사용자 이메일") ))) .andReturn(); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/controller/RoadmapCreateApiTest.java b/backend/kirikiri/src/test/java/co/kirikiri/controller/RoadmapCreateApiTest.java index e81153962..04f4a8d19 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/controller/RoadmapCreateApiTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/controller/RoadmapCreateApiTest.java @@ -25,18 +25,20 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import co.kirikiri.controller.helper.ControllerTestHelper; -import co.kirikiri.exception.AuthenticationException; -import co.kirikiri.exception.BadRequestException; -import co.kirikiri.exception.ForbiddenException; -import co.kirikiri.exception.NotFoundException; -import co.kirikiri.service.RoadmapCreateService; -import co.kirikiri.service.RoadmapReadService; import co.kirikiri.service.dto.ErrorResponse; +import co.kirikiri.service.dto.roadmap.request.RoadmapCategorySaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapDifficultyType; import co.kirikiri.service.dto.roadmap.request.RoadmapNodeSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapReviewSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapTagSaveRequest; +import co.kirikiri.service.exception.AuthenticationException; +import co.kirikiri.service.exception.BadRequestException; +import co.kirikiri.service.exception.ConflictException; +import co.kirikiri.service.exception.ForbiddenException; +import co.kirikiri.service.exception.NotFoundException; +import co.kirikiri.service.roadmap.RoadmapCreateService; +import co.kirikiri.service.roadmap.RoadmapReadService; import com.fasterxml.jackson.core.type.TypeReference; import java.util.ArrayList; import java.util.List; @@ -722,6 +724,106 @@ class RoadmapCreateApiTest extends ControllerTestHelper { .isEqualTo(expected); } + @Test + void 정상적으로_로드맵_카테고리를_생성한다() throws Exception { + // given + final RoadmapCategorySaveRequest request = new RoadmapCategorySaveRequest("카테고리 이름"); + doNothing().when(roadmapCreateService) + .createRoadmapCategory(request); + + final String jsonRequest = objectMapper.writeValueAsString(request); + + // when + mockMvc.perform(post(API_PREFIX + "/roadmaps/categories") + .header(AUTHORIZATION, String.format(BEARER_TOKEN_FORMAT, "test-token")) + .content(jsonRequest) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .contextPath(API_PREFIX)) + .andExpect(status().isCreated()) + .andDo(documentationResultHandler.document( + requestHeaders( + headerWithName(AUTHORIZATION).description("액세스 토큰")), + requestFields( + fieldWithPath("name").description("카테고리 이름") + .attributes(new Attribute(RESTRICT, "- 길이 : 1 ~ 10"))))); + } + + @Test + void 로드맵_카테고리_생성_시_카테고리_이름이_빈값일_경우() throws Exception { + // given + final RoadmapCategorySaveRequest request = new RoadmapCategorySaveRequest(""); + doNothing().when(roadmapCreateService) + .createRoadmapCategory(request); + + final String jsonRequest = objectMapper.writeValueAsString(request); + + // when + mockMvc.perform(post(API_PREFIX + "/roadmaps/categories") + .header(AUTHORIZATION, String.format(BEARER_TOKEN_FORMAT, "test-token")) + .content(jsonRequest) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .contextPath(API_PREFIX)) + .andExpect(status().isBadRequest()) + .andDo(documentationResultHandler.document( + requestHeaders( + headerWithName(AUTHORIZATION).description("액세스 토큰")), + requestFields( + fieldWithPath("name").description("카테고리 이름") + .attributes(new Attribute(RESTRICT, "- 길이 : 1 ~ 10"))))); + } + + @Test + void 로드맵_카테고리_생성_시_카테고리_이름이_10자_초과일_경우() throws Exception { + // given + final RoadmapCategorySaveRequest request = new RoadmapCategorySaveRequest("10자가 초과되는 카테고리 이름입니다."); + doThrow(new BadRequestException("카테고리 이름은 1자 이상 10자 이하입니다.")).when(roadmapCreateService) + .createRoadmapCategory(request); + + final String jsonRequest = objectMapper.writeValueAsString(request); + + // when + mockMvc.perform(post(API_PREFIX + "/roadmaps/categories") + .header(AUTHORIZATION, String.format(BEARER_TOKEN_FORMAT, "test-token")) + .content(jsonRequest) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .contextPath(API_PREFIX)) + .andExpect(status().isBadRequest()) + .andDo(documentationResultHandler.document( + requestHeaders( + headerWithName(AUTHORIZATION).description("액세스 토큰")), + requestFields( + fieldWithPath("name").description("카테고리 이름") + .attributes(new Attribute(RESTRICT, "- 길이 : 1 ~ 10"))), + responseFields( + fieldWithPath("message").description("예외 메시지")))); + } + + @Test + void 로드맵_카테고리_생성_시_카테고리_이름이_중복될_경우() throws Exception { + // given + final RoadmapCategorySaveRequest request = new RoadmapCategorySaveRequest("여행"); + doThrow(new ConflictException("이미 존재하는 이름의 카테고리입니다.")).when(roadmapCreateService) + .createRoadmapCategory(request); + + final String jsonRequest = objectMapper.writeValueAsString(request); + + // when + mockMvc.perform(post(API_PREFIX + "/roadmaps/categories") + .header(AUTHORIZATION, String.format(BEARER_TOKEN_FORMAT, "test-token")) + .content(jsonRequest) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .contextPath(API_PREFIX)) + .andExpect(status().isConflict()) + .andDo(documentationResultHandler.document( + requestHeaders( + headerWithName(AUTHORIZATION).description("액세스 토큰")), + requestFields( + fieldWithPath("name").description("카테고리 이름") + .attributes(new Attribute(RESTRICT, "- 길이 : 1 ~ 10"))), + responseFields( + fieldWithPath("message").description("예외 메시지")))); + } + private RoadmapSaveRequest 로드맵_생성_요청을_생성한다(final Long categoryId, final String roadmapTitle, final String roadmapIntroduction, final String roadmapContent, final RoadmapDifficultyType roadmapDifficulty, diff --git a/backend/kirikiri/src/test/java/co/kirikiri/controller/RoadmapReadApiTest.java b/backend/kirikiri/src/test/java/co/kirikiri/controller/RoadmapReadApiTest.java index b9a736f56..ceda742a1 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/controller/RoadmapReadApiTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/controller/RoadmapReadApiTest.java @@ -17,10 +17,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import co.kirikiri.controller.helper.ControllerTestHelper; +import co.kirikiri.domain.goalroom.GoalRoomStatus; import co.kirikiri.domain.roadmap.RoadmapDifficulty; -import co.kirikiri.exception.NotFoundException; -import co.kirikiri.service.RoadmapCreateService; -import co.kirikiri.service.RoadmapReadService; import co.kirikiri.service.dto.CustomScrollRequest; import co.kirikiri.service.dto.ErrorResponse; import co.kirikiri.service.dto.member.response.MemberResponse; @@ -37,6 +35,9 @@ import co.kirikiri.service.dto.roadmap.response.RoadmapResponse; import co.kirikiri.service.dto.roadmap.response.RoadmapReviewResponse; import co.kirikiri.service.dto.roadmap.response.RoadmapTagResponse; +import co.kirikiri.service.exception.NotFoundException; +import co.kirikiri.service.roadmap.RoadmapCreateService; +import co.kirikiri.service.roadmap.RoadmapReadService; import com.fasterxml.jackson.core.type.TypeReference; import java.time.LocalDate; import java.time.LocalDateTime; @@ -471,6 +472,7 @@ class RoadmapReadApiTest extends ControllerTestHelper { responseFields( fieldWithPath("responses[0].goalRoomId").description("골룸 아이디"), fieldWithPath("responses[0].name").description("골룸 이름"), + fieldWithPath("responses[0].status").description("골룸 상태"), fieldWithPath("responses[0].currentMemberCount").description("현재 골룸에 참여한 인원 수"), fieldWithPath("responses[0].limitedMemberCount").description( "골룸에 참여할 수 있는 제한 인원 수"), @@ -686,11 +688,13 @@ class RoadmapReadApiTest extends ControllerTestHelper { } private RoadmapGoalRoomResponses 골룸_응답들을_생성한다() { - final RoadmapGoalRoomResponse roadmapGoalRoomResponse1 = new RoadmapGoalRoomResponse(1L, "골룸 이름1", 3, 6, + final RoadmapGoalRoomResponse roadmapGoalRoomResponse1 = new RoadmapGoalRoomResponse(1L, "골룸 이름1", + GoalRoomStatus.RECRUITING, 3, 6, LocalDateTime.of(2023, 7, 20, 13, 0, 0), LocalDate.now(), LocalDate.now().plusDays(100), new MemberResponse(1L, "황시진", "default-member-image")); - final RoadmapGoalRoomResponse roadmapGoalRoomResponse2 = new RoadmapGoalRoomResponse(2L, "골룸 이름2", 4, 10, + final RoadmapGoalRoomResponse roadmapGoalRoomResponse2 = new RoadmapGoalRoomResponse(2L, "골룸 이름2", + GoalRoomStatus.RECRUITING, 4, 10, LocalDateTime.of(2023, 7, 10, 13, 0, 0), LocalDate.now(), LocalDate.now().plusDays(100), new MemberResponse(2L, "시진이", "default-member-image")); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/controller/helper/ControllerTestHelper.java b/backend/kirikiri/src/test/java/co/kirikiri/controller/helper/ControllerTestHelper.java index e48b28631..7fcf69214 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/controller/helper/ControllerTestHelper.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/controller/helper/ControllerTestHelper.java @@ -5,10 +5,10 @@ import co.kirikiri.common.interceptor.AuthInterceptor; import co.kirikiri.common.resolver.MemberIdentifierArgumentResolver; -import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.restdocs.payload.FieldDescriptor; +import java.util.List; public class ControllerTestHelper extends RestDocsHelper { diff --git a/backend/kirikiri/src/test/java/co/kirikiri/controller/helper/RestDocsHelper.java b/backend/kirikiri/src/test/java/co/kirikiri/controller/helper/RestDocsHelper.java index a79420ff8..f977002c7 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/controller/helper/RestDocsHelper.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/controller/helper/RestDocsHelper.java @@ -5,7 +5,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.UnsupportedEncodingException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -22,6 +21,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.filter.CharacterEncodingFilter; +import java.io.UnsupportedEncodingException; @ActiveProfiles("test") @Import(TestObjectMapperConfig.class) diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/auth/vo/EncryptedTokenTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/auth/vo/EncryptedTokenTest.java deleted file mode 100644 index aaef1b68e..000000000 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/auth/vo/EncryptedTokenTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package co.kirikiri.domain.auth.vo; - -import static org.assertj.core.api.Assertions.assertThat; - -import co.kirikiri.domain.auth.EncryptedToken; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -class EncryptedTokenTest { - - @ParameterizedTest - @ValueSource(strings = {"a", "abc", "", "token", "abcdefghijklmnopqrstuvwxyz"}) - void 정상적으로_토큰을_암호화한다(final String value) { - //given - //when - final EncryptedToken encryptedToken = new EncryptedToken(value); - - //then - assertThat(encryptedToken.getValue()).isNotEqualTo(value); - } -} diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomMemberTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomMemberTest.java index 22164903d..ba9af7109 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomMemberTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomMemberTest.java @@ -7,8 +7,8 @@ import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Nickname; import co.kirikiri.domain.member.vo.Password; -import java.time.LocalDateTime; import org.junit.jupiter.api.Test; +import java.time.LocalDateTime; class GoalRoomMemberTest { @@ -57,10 +57,10 @@ class GoalRoomMemberTest { void 입력받은_멤버가_자신과_다른_멤버이면_false를_반환한다() { // given final Member member1 = new Member(1L, new Identifier("identifier1"), - new EncryptedPassword(new Password("password1!")), + null, new EncryptedPassword(new Password("password1!")), new Nickname("name1"), null, null); final Member member2 = new Member(2L, new Identifier("identifier2"), - new EncryptedPassword(new Password("password2!")), + null, new EncryptedPassword(new Password("password2!")), new Nickname("name2"), null, null); final GoalRoomMember goalRoomMember = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.now(), null, diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomMembersTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomMembersTest.java index 086c665e9..eb9dbc68f 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomMembersTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomMembersTest.java @@ -7,17 +7,17 @@ import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Nickname; import co.kirikiri.domain.member.vo.Password; +import org.junit.jupiter.api.Test; import java.time.LocalDateTime; import java.util.List; -import org.junit.jupiter.api.Test; class GoalRoomMembersTest { private static final Member MEMBER1 = new Member(1L, new Identifier("identifier1"), - new EncryptedPassword(new Password("password1!")), + null, new EncryptedPassword(new Password("password1!")), new Nickname("name1"), null, null); private static final Member MEMBER2 = new Member(2L, new Identifier("identifier2"), - new EncryptedPassword(new Password("password2!")), + null, new EncryptedPassword(new Password("password2!")), new Nickname("name2"), null, null); @Test diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomPendingMemberTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomPendingMemberTest.java index 08ed3d818..78a675c65 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomPendingMemberTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomPendingMemberTest.java @@ -12,9 +12,8 @@ import co.kirikiri.domain.member.vo.Nickname; import co.kirikiri.domain.member.vo.Password; import co.kirikiri.domain.roadmap.RoadmapContent; -import java.time.LocalDate; -import java.time.LocalDateTime; import org.junit.jupiter.api.Test; +import java.time.LocalDateTime; class GoalRoomPendingMemberTest { @@ -23,7 +22,7 @@ class GoalRoomPendingMemberTest { // given final Member member = new Member(new Identifier("identifier"), new EncryptedPassword(new Password("password1")), new Nickname("nickname"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(2023, 7, 20), "010-1111-1111")); + new MemberProfile(Gender.FEMALE, "kirikiri1@email.com")); final GoalRoom goalRoom = new GoalRoom(new GoalRoomName("goalroom"), new LimitedMemberCount(10), new RoadmapContent("content"), member); @@ -40,7 +39,7 @@ class GoalRoomPendingMemberTest { // given final Member member = new Member(new Identifier("identifier"), new EncryptedPassword(new Password("password1")), new Nickname("nickname"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(2023, 7, 20), "010-1111-1111")); + new MemberProfile(Gender.FEMALE, "kirikiri1@email.com")); final GoalRoom goalRoom = new GoalRoom(new GoalRoomName("goalroom"), new LimitedMemberCount(10), new RoadmapContent("content"), member); @@ -73,10 +72,10 @@ class GoalRoomPendingMemberTest { void 입력받은_멤버가_자신과_다른_멤버이면_false를_반환한다() { // given final Member member1 = new Member(1L, new Identifier("identifier1"), - new EncryptedPassword(new Password("password1!")), + null, new EncryptedPassword(new Password("password1!")), new Nickname("name1"), null, null); final Member member2 = new Member(2L, new Identifier("identifier2"), - new EncryptedPassword(new Password("password2!")), + null, new EncryptedPassword(new Password("password2!")), new Nickname("name2"), null, null); final GoalRoomPendingMember goalRoomPendingMember = new GoalRoomPendingMember(GoalRoomRole.LEADER, diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomPendingMembersTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomPendingMembersTest.java index eaa84e5c0..bcb18de45 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomPendingMembersTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomPendingMembersTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import co.kirikiri.domain.exception.UnexpectedDomainException; import co.kirikiri.domain.goalroom.vo.GoalRoomName; import co.kirikiri.domain.goalroom.vo.LimitedMemberCount; import co.kirikiri.domain.member.EncryptedPassword; @@ -11,7 +12,6 @@ import co.kirikiri.domain.member.vo.Nickname; import co.kirikiri.domain.member.vo.Password; import co.kirikiri.domain.roadmap.RoadmapContent; -import co.kirikiri.exception.NotFoundException; import java.time.LocalDateTime; import java.util.List; import org.junit.jupiter.api.Test; @@ -19,10 +19,10 @@ class GoalRoomPendingMembersTest { private static final Member MEMBER1 = new Member(1L, new Identifier("identifier1"), - new EncryptedPassword(new Password("password1!")), + null, new EncryptedPassword(new Password("password1!")), new Nickname("name1"), null, null); private static final Member MEMBER2 = new Member(2L, new Identifier("identifier2"), - new EncryptedPassword(new Password("password2!")), + null, new EncryptedPassword(new Password("password2!")), new Nickname("name2"), null, null); @Test @@ -55,18 +55,16 @@ class GoalRoomPendingMembersTest { // then assertThatThrownBy(() -> assertThat(goalRoomPendingMembers.findGoalRoomLeader())) - .isInstanceOf(NotFoundException.class); + .isInstanceOf(UnexpectedDomainException.class); } @Test void 입력받은_사용자를_골룸_사용자_중에서_찾는다() { // given final GoalRoomPendingMember goalRoomPendingMember1 = new GoalRoomPendingMember(GoalRoomRole.LEADER, - LocalDateTime.now(), null, - MEMBER1); + LocalDateTime.now(), null, MEMBER1); final GoalRoomPendingMember goalRoomPendingMember2 = new GoalRoomPendingMember(GoalRoomRole.FOLLOWER, - LocalDateTime.now(), null, - MEMBER2); + LocalDateTime.now(), null, MEMBER2); final GoalRoomPendingMembers goalRoomPendingMembers = new GoalRoomPendingMembers( List.of(goalRoomPendingMember1, goalRoomPendingMember2)); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNodeTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNodeTest.java index 5ac81ced1..51a8d6208 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNodeTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNodeTest.java @@ -4,9 +4,9 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import co.kirikiri.domain.goalroom.vo.Period; import co.kirikiri.domain.roadmap.RoadmapNode; -import co.kirikiri.exception.BadRequestException; import java.time.LocalDate; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -37,7 +37,7 @@ class GoalRoomRoadmapNodeTest { //then assertThatThrownBy(() -> new GoalRoomRoadmapNode(new Period(startDate, endDate), checkCount, new RoadmapNode("title", "content"))) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(GoalRoomException.class); } @ParameterizedTest @@ -51,7 +51,7 @@ class GoalRoomRoadmapNodeTest { //then assertThatThrownBy(() -> new GoalRoomRoadmapNode(new Period(startDate, endDate), checkCount, new RoadmapNode("title", "content"))) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(GoalRoomException.class); } @ParameterizedTest @@ -66,7 +66,7 @@ class GoalRoomRoadmapNodeTest { //then assertThatThrownBy(() -> new GoalRoomRoadmapNode(new Period(startDate, endDate), checkCount, new RoadmapNode("title", "content"))) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(GoalRoomException.class); } @ParameterizedTest @@ -81,7 +81,7 @@ class GoalRoomRoadmapNodeTest { //then assertThatThrownBy(() -> new GoalRoomRoadmapNode(new Period(startDate, endDate), checkCount, new RoadmapNode("title", "content"))) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(GoalRoomException.class); } @ParameterizedTest diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNodesTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNodesTest.java index b1de7bb22..3743814ba 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNodesTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomRoadmapNodesTest.java @@ -5,9 +5,9 @@ import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import co.kirikiri.domain.goalroom.vo.Period; import co.kirikiri.domain.roadmap.RoadmapNode; -import co.kirikiri.exception.BadRequestException; import java.time.LocalDate; import java.util.ArrayList; import java.util.Collections; @@ -60,7 +60,7 @@ class GoalRoomRoadmapNodesTest { //when //then assertThatThrownBy(() -> new GoalRoomRoadmapNodes(List.of(firstGoalRoomRoadmapNode, secondGoalRoomRoadmapNode))) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(GoalRoomException.class); } @Test diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomTest.java index 2fbafd1af..8459bd4d1 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomTest.java @@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import co.kirikiri.domain.goalroom.vo.GoalRoomName; import co.kirikiri.domain.goalroom.vo.LimitedMemberCount; import co.kirikiri.domain.goalroom.vo.Period; @@ -22,7 +23,6 @@ import co.kirikiri.domain.roadmap.RoadmapNode; import co.kirikiri.domain.roadmap.RoadmapNodeImages; import co.kirikiri.domain.roadmap.RoadmapNodes; -import co.kirikiri.exception.BadRequestException; import java.time.LocalDate; import java.util.Collections; import java.util.List; @@ -45,9 +45,8 @@ static void setUp() { final Password password = new Password("password1!"); final EncryptedPassword encryptedPassword = new EncryptedPassword(password); final Nickname nickname = new Nickname("nickname"); - final String phoneNumber = "010-1234-5678"; - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.now(), phoneNumber); - member = new Member(1L, identifier, encryptedPassword, nickname, null, memberProfile); + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, "kirikiri1@email.com"); + member = new Member(1L, identifier, null, encryptedPassword, nickname, null, memberProfile); } @Test @@ -74,13 +73,13 @@ static void setUp() { final GoalRoom goalRoom = new GoalRoom(new GoalRoomName("goalroom"), new LimitedMemberCount(10), new RoadmapContent("content"), member); final Member member1 = new Member(2L, new Identifier("identifier2"), - new EncryptedPassword(new Password("password1")), new Nickname("닉네임2"), + null, new EncryptedPassword(new Password("password1")), new Nickname("닉네임2"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(2023, 7, 20), "010-1111-1111")); + new MemberProfile(Gender.FEMALE, "kirikiri1@email.com")); final Member member2 = new Member(3L, new Identifier("identifier3"), - new EncryptedPassword(new Password("password1")), new Nickname("닉네임3"), + null, new EncryptedPassword(new Password("password1")), new Nickname("닉네임3"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(2023, 7, 20), "010-1111-1111")); + new MemberProfile(Gender.FEMALE, "kirikiri1@email.com")); // when goalRoom.join(member1); @@ -115,7 +114,7 @@ static void setUp() { //when, then assertThatThrownBy(() -> goalRoom.join(member)) - .isInstanceOf(BadRequestException.class) + .isInstanceOf(GoalRoomException.class) .hasMessage("모집 중이지 않은 골룸에는 참여할 수 없습니다."); } @@ -127,7 +126,7 @@ static void setUp() { //when,then assertThatThrownBy(() -> goalRoom.join(member)) - .isInstanceOf(BadRequestException.class) + .isInstanceOf(GoalRoomException.class) .hasMessage("제한 인원이 꽉 찬 골룸에는 참여할 수 없습니다."); } @@ -139,7 +138,7 @@ static void setUp() { //when,then assertThatThrownBy(() -> goalRoom.join(member)) - .isInstanceOf(BadRequestException.class) + .isInstanceOf(GoalRoomException.class) .hasMessage("이미 참여한 골룸에는 참여할 수 없습니다."); } @@ -224,7 +223,7 @@ static void setUp() { // when // then assertThatThrownBy(() -> goalRoom.leave(notJoinMember)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(GoalRoomException.class); } @Test @@ -245,17 +244,14 @@ static void setUp() { } private Member 크리에이터를_생성한다() { - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.of(1990, 1, 1), - "010-1234-5678"); + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, "kirikiri1@email.com"); return new Member(new Identifier("cokirikiri"), new EncryptedPassword(new Password("password1!")), new Nickname("코끼리"), null, memberProfile); } private Member 사용자를_생성한다(final Long id, final String identifier, final String nickname) { - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, - LocalDate.of(1995, 9, 30), "010-1234-5678"); - - return new Member(id, new Identifier(identifier), new EncryptedPassword(new Password("password1!")), + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, "kirikiri1@email.com"); + return new Member(id, new Identifier(identifier), null, new EncryptedPassword(new Password("password1!")), new Nickname(nickname), null, memberProfile); } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomToDoTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomToDoTest.java index f1261acd2..16b3a5dce 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomToDoTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomToDoTest.java @@ -3,9 +3,9 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import co.kirikiri.domain.goalroom.vo.GoalRoomTodoContent; import co.kirikiri.domain.goalroom.vo.Period; -import co.kirikiri.exception.BadRequestException; import java.time.LocalDate; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -34,7 +34,7 @@ class GoalRoomToDoTest { //when //then assertThatThrownBy(() -> new GoalRoomToDo(new GoalRoomTodoContent("content"), new Period(startDate, endDate))) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(GoalRoomException.class); } @ParameterizedTest @@ -47,6 +47,6 @@ class GoalRoomToDoTest { //when //then assertThatThrownBy(() -> new GoalRoomToDo(new GoalRoomTodoContent("content"), new Period(startDate, endDate))) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(GoalRoomException.class); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomToDosTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomToDosTest.java index 699b2bb13..3de322e61 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomToDosTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/GoalRoomToDosTest.java @@ -4,9 +4,9 @@ import co.kirikiri.domain.goalroom.vo.GoalRoomTodoContent; import co.kirikiri.domain.goalroom.vo.Period; +import org.junit.jupiter.api.Test; import java.time.LocalDate; import java.util.List; -import org.junit.jupiter.api.Test; class GoalRoomToDosTest { diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/vo/GoalRoomNameTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/vo/GoalRoomNameTest.java index ce8928f3f..b1eafe64e 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/vo/GoalRoomNameTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/vo/GoalRoomNameTest.java @@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -29,6 +29,6 @@ class GoalRoomNameTest { //when //then assertThatThrownBy(() -> new GoalRoomName(value)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(GoalRoomException.class); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/vo/GoalRoomTodoContentTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/vo/GoalRoomTodoContentTest.java index 31c2e5e77..ef200e17c 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/vo/GoalRoomTodoContentTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/vo/GoalRoomTodoContentTest.java @@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -29,6 +29,6 @@ class GoalRoomTodoContentTest { //when //then assertThatThrownBy(() -> new GoalRoomTodoContent(value)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(GoalRoomException.class); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/vo/LimitedMemberCountTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/vo/LimitedMemberCountTest.java index 310413d9c..66445598a 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/vo/LimitedMemberCountTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/goalroom/vo/LimitedMemberCountTest.java @@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -25,6 +25,6 @@ class LimitedMemberCountTest { //when //then assertThatThrownBy(() -> new LimitedMemberCount(value)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(GoalRoomException.class); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/member/vo/IdentifierTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/member/vo/IdentifierTest.java index 5ca7148bc..2555e7155 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/member/vo/IdentifierTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/member/vo/IdentifierTest.java @@ -3,14 +3,14 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.member.exception.MemberException; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; class IdentifierTest { @ParameterizedTest - @ValueSource(strings = {"ab12", "abcdefghijklmnopqrst"}) + @ValueSource(strings = {"ab12", "abcdefghijklmnopqrst1abcdefghijklmnopqrs"}) void 정상적으로_아이디를_생성한다(final String identifier) { //given //when @@ -19,32 +19,12 @@ class IdentifierTest { } @ParameterizedTest - @ValueSource(strings = {"abc", "abcdefghijklmnopqrst1"}) - void 아이디_길이가_4미만_20초과일_경우_예외를_던진다(final String identifier) { + @ValueSource(strings = {"abc", "abcdefghijklmnopqrst1abcdefghijklmnopqrst"}) + void 아이디_길이가_4미만_40초과일_경우_예외를_던진다(final String identifier) { //given //when //then assertThatThrownBy(() -> new Identifier(identifier)) - .isInstanceOf(BadRequestException.class); - } - - @ParameterizedTest - @ValueSource(strings = {"Abcd", "ABCd", "abcdefG", "abcDefgHi", "abcdefghijklmnopqrsT"}) - void 아이디에_대문자가_있을_경우(final String identifier) { - //given - //when - //then - assertThatThrownBy(() -> new Identifier(identifier)) - .isInstanceOf(BadRequestException.class); - } - - @ParameterizedTest - @ValueSource(strings = {"abc~", "~!@#$%^&*()", "abcdef!"}) - void 아이디에_특수문자가_있을_경우(final String identifier) { - //given - //when - //then - assertThatThrownBy(() -> new Identifier(identifier)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(MemberException.class); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/member/vo/NicknameTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/member/vo/NicknameTest.java index a3f4dca46..80876918e 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/member/vo/NicknameTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/member/vo/NicknameTest.java @@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.member.exception.MemberException; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -19,12 +19,12 @@ class NicknameTest { } @ParameterizedTest - @ValueSource(strings = {"a", "abcdefghe"}) + @ValueSource(strings = {"a", "123456789012345678901"}) void 닉네임_길이가_틀릴_경우_예외를_던진다(final String nickname) { //given //when //then assertThatThrownBy(() -> new Nickname(nickname)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(MemberException.class); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/member/vo/PasswordTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/member/vo/PasswordTest.java index 83c8ffee4..a0fe0d3cb 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/member/vo/PasswordTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/member/vo/PasswordTest.java @@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.member.exception.MemberException; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -25,7 +25,7 @@ class PasswordTest { //when //then assertThatThrownBy(() -> new Password(password)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(MemberException.class); } @ParameterizedTest @@ -35,7 +35,7 @@ class PasswordTest { //when //then assertThatThrownBy(() -> new Password(password)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(MemberException.class); } @ParameterizedTest @@ -45,7 +45,7 @@ class PasswordTest { //when //then assertThatThrownBy(() -> new Password(password)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(MemberException.class); } @ParameterizedTest @@ -55,7 +55,7 @@ class PasswordTest { //when //then assertThatThrownBy(() -> new Password(password)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(MemberException.class); } @ParameterizedTest @@ -65,7 +65,7 @@ class PasswordTest { //when //then assertThatThrownBy(() -> new Password(password)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(MemberException.class); } @ParameterizedTest @@ -75,6 +75,6 @@ class PasswordTest { //when //then assertThatThrownBy(() -> new Password(password)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(MemberException.class); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapCategoryTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapCategoryTest.java new file mode 100644 index 000000000..726de9855 --- /dev/null +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapCategoryTest.java @@ -0,0 +1,43 @@ +package co.kirikiri.domain.roadmap; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import co.kirikiri.domain.roadmap.exception.RoadmapException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class RoadmapCategoryTest { + + @ParameterizedTest + @ValueSource(strings = {"글", "여행", "1234567890", " 1234567890 "}) + void 정상적으로_로드맵_카테고리를_생성한다(final String name) { + //given + //when + //then + assertDoesNotThrow(() -> new RoadmapCategory(name)); + } + + @Test + void 카테고리_생성시_공백이_들어올_경우_예외를_던진다() { + //given + final String space = ""; + + //when + //then + assertThatThrownBy(() -> new RoadmapCategory(space)) + .isInstanceOf(RoadmapException.class); + } + + @Test + void 카테고리_생성시_10글자_초과일_경우_예외를_던진다() { + //given + final String space = "12345678901"; + + //when + //then + assertThatThrownBy(() -> new RoadmapCategory(space)) + .isInstanceOf(RoadmapException.class); + } +} diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapContentTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapContentTest.java index 18d578d63..4a663ac40 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapContentTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapContentTest.java @@ -13,8 +13,7 @@ import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Nickname; import co.kirikiri.domain.member.vo.Password; -import co.kirikiri.exception.BadRequestException; -import java.time.LocalDate; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import java.util.List; import org.junit.jupiter.api.Test; @@ -27,7 +26,7 @@ class RoadmapContentTest { // expect assertThatThrownBy(() -> new RoadmapContent(content)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } @Test @@ -75,7 +74,7 @@ class RoadmapContentTest { void 로드맵_본문의_로드맵인_경우_false를_반환한다() { // given final RoadmapContent content = new RoadmapContent("content"); - final MemberProfile profile = new MemberProfile(Gender.FEMALE, LocalDate.of(1999, 6, 8), "01011112222"); + final MemberProfile profile = new MemberProfile(Gender.FEMALE, "kirikiri1@email.com"); final Member creator = new Member(new Identifier("creator"), new EncryptedPassword(new Password("password1")), new Nickname("nickname"), null, profile); final RoadmapCategory category = new RoadmapCategory(1L, "여가"); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapContentsTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapContentsTest.java index 2cc6762a0..a9e9113f9 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapContentsTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapContentsTest.java @@ -2,8 +2,8 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.util.List; import org.junit.jupiter.api.Test; +import java.util.List; class RoadmapContentsTest { diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapNodeImagesTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapNodeImagesTest.java index 9d54048de..d5aab01ae 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapNodeImagesTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapNodeImagesTest.java @@ -4,7 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import co.kirikiri.domain.ImageContentType; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import java.util.List; import org.junit.jupiter.api.Test; @@ -37,7 +37,7 @@ class RoadmapNodeImagesTest { //then assertThatThrownBy( () -> new RoadmapNodeImages(List.of(roadmapNodeImage1, roadmapNodeImage2, roadmapNodeImage3))) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } @Test @@ -55,7 +55,7 @@ class RoadmapNodeImagesTest { //when //then assertThatThrownBy(() -> roadmapNodeImages.add(roadmapNodeImage3)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } @@ -77,7 +77,7 @@ class RoadmapNodeImagesTest { //then assertThatThrownBy( () -> roadmapNodeImages.addAll(new RoadmapNodeImages(List.of(roadmapNodeImage3, roadmapNodeImage4)))) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapNodeTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapNodeTest.java index 9b5f86d70..97ae660fc 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapNodeTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapNodeTest.java @@ -2,7 +2,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -16,7 +16,7 @@ class RoadmapNodeTest { // expect assertThatThrownBy(() -> new RoadmapNode(title, "로드맵 설명")) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } @ParameterizedTest @@ -27,6 +27,6 @@ class RoadmapNodeTest { // expect assertThatThrownBy(() -> new RoadmapNode("로드맵 제목", content)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapNodesTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapNodesTest.java index 5dc3092c6..e8c06eecc 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapNodesTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapNodesTest.java @@ -3,8 +3,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; -import java.util.List; import org.junit.jupiter.api.Test; +import java.util.List; class RoadmapNodesTest { diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapReviewTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapReviewTest.java index e56c2f614..0e7dcd492 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapReviewTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapReviewTest.java @@ -11,8 +11,7 @@ import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Nickname; import co.kirikiri.domain.member.vo.Password; -import co.kirikiri.exception.BadRequestException; -import java.time.LocalDate; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -24,7 +23,7 @@ class RoadmapReviewTest { void 별점이_0부터_5사이의_소수점이_5로_끝나는_값이면서_내용이_1000자_이내라면_정상적으로_생성된다(final Double rate) { // given final String content = "a".repeat(1000); - final MemberProfile profile = new MemberProfile(Gender.FEMALE, LocalDate.of(1999, 6, 8), "01011112222"); + final MemberProfile profile = new MemberProfile(Gender.FEMALE, "kirikiri1@email.com"); final Member member = new Member(new Identifier("creator"), new EncryptedPassword(new Password("password1")), new Nickname("nickname"), null, profile); @@ -39,25 +38,25 @@ class RoadmapReviewTest { void 리뷰_내용이_1000자를_넘으면_예외가_발생한다() { // given final String content = "a".repeat(1001); - final MemberProfile profile = new MemberProfile(Gender.FEMALE, LocalDate.of(1999, 6, 8), "01011112222"); + final MemberProfile profile = new MemberProfile(Gender.FEMALE, "kirikiri1@email.com"); final Member member = new Member(new Identifier("creator"), new EncryptedPassword(new Password("password1")), new Nickname("nickname"), null, profile); // expected assertThatThrownBy(() -> new RoadmapReview(content, null, member)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } @ParameterizedTest @ValueSource(doubles = {-1, -1.5, 5.5, 1.2, 3.7, 4.55}) void 리뷰_별점이_0과_5사이의_소수점_5_단위의_값이_아니면_예외가_발생한다(final double rate) { // given - final MemberProfile profile = new MemberProfile(Gender.FEMALE, LocalDate.of(1999, 6, 8), "01011112222"); + final MemberProfile profile = new MemberProfile(Gender.FEMALE, "kirikiri1@email.com"); final Member member = new Member(new Identifier("creator"), new EncryptedPassword(new Password("password1")), new Nickname("nickname"), null, profile); // expected assertThatThrownBy(() -> new RoadmapReview("리뷰", rate, member)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapTagsTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapTagsTest.java index faf5f614a..76ba65ba5 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapTagsTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapTagsTest.java @@ -4,8 +4,8 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import co.kirikiri.domain.roadmap.vo.RoadmapTagName; -import co.kirikiri.exception.BadRequestException; import java.util.List; import org.junit.jupiter.api.Test; @@ -42,7 +42,7 @@ class RoadmapTagsTest { // expected assertThatThrownBy(() -> new RoadmapTags(values)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } @Test @@ -54,6 +54,6 @@ class RoadmapTagsTest { // expected assertThatThrownBy(() -> new RoadmapTags(values)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapTest.java index d436e79b9..cea624848 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/RoadmapTest.java @@ -12,8 +12,7 @@ import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Nickname; import co.kirikiri.domain.member.vo.Password; -import co.kirikiri.exception.BadRequestException; -import java.time.LocalDate; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -54,7 +53,7 @@ class RoadmapTest { // expect assertThatThrownBy(() -> new Roadmap(title, "로드맵 소개글", 30, DIFFICULT, creator, category)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } @ParameterizedTest @@ -65,7 +64,7 @@ class RoadmapTest { // expect assertThatThrownBy(() -> new Roadmap("로드맵 제목", introduction, 30, DIFFICULT, creator, category)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } @ParameterizedTest @@ -73,11 +72,11 @@ class RoadmapTest { void 로드맵_추천_소요_기간이_0보다_작고_1000보다_크면_예외가_발생한다(final int requiredPeriod) { // expect assertThatThrownBy(() -> new Roadmap("로드맵 제목", "로드맵 소개글", requiredPeriod, DIFFICULT, creator, category)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } private Member 크리에이터를_생성한다() { - final MemberProfile profile = new MemberProfile(Gender.FEMALE, LocalDate.of(1999, 6, 8), "01011112222"); + final MemberProfile profile = new MemberProfile(Gender.FEMALE, "kirikiri1@email.com"); return new Member(new Identifier("creator"), new EncryptedPassword(new Password("password1")), new Nickname("nickname"), null, profile); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/vo/RoadmapTagNameTest.java b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/vo/RoadmapTagNameTest.java index dec613138..d563697df 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/vo/RoadmapTagNameTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/domain/roadmap/vo/RoadmapTagNameTest.java @@ -4,7 +4,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.domain.roadmap.exception.RoadmapException; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; @@ -30,7 +30,7 @@ class RoadmapTagNameTest { // expected assertThatThrownBy(() -> new RoadmapTagName(name)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(RoadmapException.class); } @ParameterizedTest diff --git a/backend/kirikiri/src/test/java/co/kirikiri/infra/AmazonS3FileServiceTest.java b/backend/kirikiri/src/test/java/co/kirikiri/infra/AmazonS3FileServiceTest.java index d91d1b747..602e83e4d 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/infra/AmazonS3FileServiceTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/infra/AmazonS3FileServiceTest.java @@ -7,12 +7,15 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; -import co.kirikiri.exception.ServerException; import co.kirikiri.service.dto.FileInformation; +import co.kirikiri.service.exception.ServerException; import com.amazonaws.AmazonServiceException; import com.amazonaws.Protocol; import com.amazonaws.SdkClientException; import com.amazonaws.services.s3.AmazonS3; +import java.io.FileInputStream; +import java.net.MalformedURLException; +import java.net.URL; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -20,9 +23,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.core.env.Environment; import org.springframework.http.HttpMethod; -import java.io.FileInputStream; -import java.net.MalformedURLException; -import java.net.URL; @ExtendWith(MockitoExtension.class) class AmazonS3FileServiceTest { @@ -35,6 +35,9 @@ class AmazonS3FileServiceTest { @Mock private Environment environment; + @Mock + private CloudFrontService cloudFrontService; + @InjectMocks private AmazonS3FileService amazonS3FileService; @@ -86,7 +89,21 @@ class AmazonS3FileServiceTest { } @Test - void 정상적으로_파일_URL을_생성한다() throws MalformedURLException { + void 정상적으로_파일_GET_URL을_생성한다() throws MalformedURLException { + //given + final URL url = new URL(Protocol.HTTP.toString(), "host", 80, "file"); + when(cloudFrontService.generateGetUrl(anyString())) + .thenReturn(url); + + //when + final URL result = amazonS3FileService.generateUrl("path", HttpMethod.GET); + + //then + assertThat(result).isEqualTo(url); + } + + @Test + void 정상적으로_파일_POST_URL을_생성한다() throws MalformedURLException { //given final URL url = new URL(Protocol.HTTP.toString(), "host", 80, "file"); when(environment.getProperty(anyString())) @@ -97,7 +114,25 @@ class AmazonS3FileServiceTest { .thenReturn(url); //when - final URL result = amazonS3FileService.generateUrl("path", HttpMethod.GET); + final URL result = amazonS3FileService.generateUrl("path", HttpMethod.POST); + + //then + assertThat(result).isEqualTo(url); + } + + @Test + void 정상적으로_파일_DELETE_URL을_생성한다() throws MalformedURLException { + //given + final URL url = new URL(Protocol.HTTP.toString(), "host", 80, "file"); + when(environment.getProperty(anyString())) + .thenReturn("bucket"); + when(environment.getProperty(anyString())) + .thenReturn("60000"); + when(amazonS3.generatePresignedUrl(any())) + .thenReturn(url); + + //when + final URL result = amazonS3FileService.generateUrl("path", HttpMethod.DELETE); //then assertThat(result).isEqualTo(url); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/infra/CloudFrontServiceTest.java b/backend/kirikiri/src/test/java/co/kirikiri/infra/CloudFrontServiceTest.java new file mode 100644 index 000000000..1b56ff0d4 --- /dev/null +++ b/backend/kirikiri/src/test/java/co/kirikiri/infra/CloudFrontServiceTest.java @@ -0,0 +1,52 @@ +package co.kirikiri.infra; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.when; + +import co.kirikiri.service.exception.ServerException; +import java.net.MalformedURLException; +import java.net.URL; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.core.env.Environment; + +@ExtendWith(MockitoExtension.class) +class CloudFrontServiceTest { + + @Mock + private Environment environment; + + @InjectMocks + private CloudFrontService cloudFrontService; + + @Test + void 정상적으로_GET_URL을_생성한다() throws MalformedURLException { + //given + when(environment.getProperty("cloud.aws.cloud-front.distribution-domain")) + .thenReturn("https://test.com"); + final String path = "/test/path/originalFilename.png"; + + //when + final URL url = cloudFrontService.generateGetUrl(path); + + //then + assertThat(url).isEqualTo(new URL("https://test.com" + path)); + } + + @Test + void cloudFront_배포_도메인에_프로토콜이_정의되지_않은_경우_예외를_던진다() { + //given + when(environment.getProperty("cloud.aws.cloud-front.distribution-domain")) + .thenReturn("test.com"); + final String path = "/test/path/originalFilename.png"; + + //when + //then + assertThatThrownBy(() -> cloudFrontService.generateGetUrl(path)) + .isInstanceOf(ServerException.class); + } +} diff --git a/backend/kirikiri/src/test/java/co/kirikiri/infra/NaverOauthNetworkServiceTest.java b/backend/kirikiri/src/test/java/co/kirikiri/infra/NaverOauthNetworkServiceTest.java new file mode 100644 index 000000000..bdcfe98c2 --- /dev/null +++ b/backend/kirikiri/src/test/java/co/kirikiri/infra/NaverOauthNetworkServiceTest.java @@ -0,0 +1,82 @@ +package co.kirikiri.infra; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +import co.kirikiri.service.dto.auth.NaverOauthTokenDto; +import co.kirikiri.service.dto.auth.response.AuthenticationResponse; +import java.util.Map; +import java.util.Optional; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +@ExtendWith(MockitoExtension.class) +class NaverOauthNetworkServiceTest { + + @Mock + private RestTemplate restTemplate; + + @Mock + private Environment environment; + + @InjectMocks + private NaverOauthNetworkService naverOauthNetworkService; + + @Test + void 정상적으로_네이버_OAuth_토큰을_요청한다() { + // given + final ResponseEntity 예상하는_응답 = ResponseEntity.of( + Optional.of(new NaverOauthTokenDto("access_token", "refresh_token", "token_type", 3600))); + + when(environment.getProperty("oauth.naver.token-url")) + .thenReturn("https://nid.naver.com/oauth2.0/token?"); + when(environment.getProperty("oauth.naver.client-id")) + .thenReturn("client_id"); + when(environment.getProperty("oauth.naver.client-secret")) + .thenReturn("client_secret"); + when(restTemplate.getForEntity(anyString(), eq(NaverOauthTokenDto.class))) + .thenReturn(예상하는_응답); + + // when + final ResponseEntity 응답 = naverOauthNetworkService.requestToken( + NaverOauthTokenDto.class, Map.of( + "code", "code", + "state", "state", + "grant_type", "authorization_code" + )); + + // then + assertThat(응답.getBody()) + .isEqualTo(예상하는_응답.getBody()); + } + + @Test + void 정상적으로_네이버_사용자_프로필_정보를_요청한다() { + // given + final ResponseEntity 예상하는_응답 = ResponseEntity.of( + Optional.of(new AuthenticationResponse("refresh_token", "access_token"))); + + when(environment.getProperty("oauth.naver.member-info-url")) + .thenReturn("https://openapi.naver.com/v1/nid/me"); + when(restTemplate.exchange(anyString(), any(), any(), eq(AuthenticationResponse.class))) + .thenReturn(예상하는_응답); + + // when + final ResponseEntity 응답 = naverOauthNetworkService.requestMemberInfo( + AuthenticationResponse.class, Map.of(HttpHeaders.AUTHORIZATION, "token")); + + // then + assertThat(응답.getBody()) + .isEqualTo(예상하는_응답.getBody()); + } +} diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/AuthenticationIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/AuthenticationIntegrationTest.java index e0680efb2..efc6e01a2 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/AuthenticationIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/AuthenticationIntegrationTest.java @@ -90,7 +90,7 @@ class AuthenticationIntegrationTest extends InitIntegrationTest { } @Test - void 정상적으로_토큰_재발행을_힌다() { + void 정상적으로_토큰_재발행을_한다() { //given final ReissueTokenRequest 토큰_재발행_요청 = new ReissueTokenRequest(기본_재발행_토큰); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/GoalRoomCreateIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/GoalRoomCreateIntegrationTest.java index a04844699..b1f922460 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/GoalRoomCreateIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/GoalRoomCreateIntegrationTest.java @@ -22,6 +22,7 @@ import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_이름; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_제한_인원; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_투두_컨텐츠; +import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_EMAIL; import static co.kirikiri.integration.fixture.MemberAPIFixture.요청을_받는_사용자_자신의_정보_조회_요청; import static co.kirikiri.integration.fixture.MemberAPIFixture.회원가입; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵_생성; @@ -50,8 +51,6 @@ import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import java.io.IOException; -import java.time.LocalDate; -import java.time.Month; import java.time.temporal.ChronoUnit; import java.util.Collections; import java.util.List; @@ -68,11 +67,10 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); //when final ExtractableResponse 골룸_생성_응답 = 골룸_생성(골룸_생성_요청, 기본_로그인_토큰); @@ -88,11 +86,10 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 로드맵_아이디가_빈값인_골룸_생성_요청 = new GoalRoomCreateRequest(null, 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); //when final ExtractableResponse 골룸_생성_응답 = 골룸_생성(로드맵_아이디가_빈값인_골룸_생성_요청, 기본_로그인_토큰); @@ -113,10 +110,9 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); - final GoalRoomCreateRequest 골룸_이름이_빈값인_골룸_생성_요청 = new GoalRoomCreateRequest(1L, null, 정상적인_골룸_제한_인원, 골룸_투두_요청, + final GoalRoomCreateRequest 골룸_이름이_빈값인_골룸_생성_요청 = new GoalRoomCreateRequest(1L, null, 정상적인_골룸_제한_인원, 골룸_노드_별_기간_요청); //when @@ -138,10 +134,9 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); - final GoalRoomCreateRequest 골룸_제한_인원이_빈값인_골룸_생성_요청 = new GoalRoomCreateRequest(1L, 정상적인_골룸_이름, null, 골룸_투두_요청, + final GoalRoomCreateRequest 골룸_제한_인원이_빈값인_골룸_생성_요청 = new GoalRoomCreateRequest(1L, 정상적인_골룸_이름, null, 골룸_노드_별_기간_요청); //when @@ -164,11 +159,10 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); final String 적절하지_않은_길이의_골룸_이름 = "a".repeat(41); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(기본_로드맵_아이디, 적절하지_않은_길이의_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); //when final ExtractableResponse 골룸_생성_응답 = 골룸_생성(골룸_생성_요청, 기본_로그인_토큰); @@ -186,10 +180,9 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = Collections.emptyList(); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(기본_로드맵_아이디, 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); //when final ExtractableResponse 골룸_생성_응답 = 골룸_생성(골룸_생성_요청, 기본_로그인_토큰); @@ -207,13 +200,12 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final int 초과된_제한인원 = 30; final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 초과된_제한인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); //when final ExtractableResponse 골룸_생성_응답 = 골룸_생성(골룸_생성_요청, 기본_로그인_토큰); @@ -231,16 +223,15 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -275,15 +266,14 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); - final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(기본_로드맵_아이디, 정상적인_골룸_이름, 1, 골룸_투두_요청, + final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(기본_로드맵_아이디, 정상적인_골룸_이름, 1, 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -300,49 +290,16 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { ); } - @Test - void 모집_중이지_않은_골룸에_참가_요청을_보내면_예외가_발생한다() throws IOException { - //given - final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); - final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); - final List 골룸_노드_별_기간_요청 = List.of( - new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); - final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(기본_로드맵_아이디, 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); - final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); - 골룸을_시작한다(기본_로그인_토큰, 골룸_아이디); - - final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); - final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); - 회원가입(팔로워_회원_가입_요청); - final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); - - //when - final ExtractableResponse 참가_요청에_대한_응답 = 골룸_참가_요청(골룸_아이디, 팔로워_액세스_토큰); - - //then - final String 예외_메시지 = 참가_요청에_대한_응답.asString(); - - assertAll( - () -> assertThat(참가_요청에_대한_응답.statusCode()).isEqualTo(HttpStatus.BAD_REQUEST.value()), - () -> assertThat(예외_메시지).contains("모집 중이지 않은 골룸에는 참여할 수 없습니다.") - ); - } - @Test void 인증_피드_등록을_요청한다() throws IOException { //given final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(기본_로드맵_아이디, 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); 골룸을_시작한다(기본_로그인_토큰, 골룸_아이디); @@ -354,11 +311,7 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final ExtractableResponse 인증_피드_등록_응답 = 인증_피드_등록(골룸_아이디, 가짜_이미지_객체, 인증_피드_등록_요청, 기본_로그인_토큰); //then - assertAll( - () -> assertThat(인증_피드_등록_응답.statusCode()).isEqualTo(HttpStatus.CREATED.value()), - () -> assertThat(인증_피드_등록_응답.response().header("Location")) - .contains("originalFileName.jpeg") - ); + assertThat(인증_피드_등록_응답.statusCode()).isEqualTo(HttpStatus.CREATED.value()); } @Test @@ -366,11 +319,10 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(기본_로드맵_아이디, 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); 골룸을_시작한다(기본_로그인_토큰, 골룸_아이디); @@ -395,11 +347,10 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(기본_로드맵_아이디, 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); 골룸을_시작한다(기본_로그인_토큰, 골룸_아이디); @@ -425,11 +376,10 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(기본_로드맵_아이디, 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); 골룸을_시작한다(기본_로그인_토큰, 골룸_아이디); @@ -460,11 +410,10 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 1, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(기본_로드맵_아이디, 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); 골룸을_시작한다(기본_로그인_토큰, 골룸_아이디); @@ -491,11 +440,10 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(기본_로드맵_아이디, 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); //when @@ -537,7 +485,7 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); final MemberJoinRequest 팔로워_회원가입_요청 = new MemberJoinRequest("identifier2", "password12!@#$%", "follower", - "010-2345-6789", GenderType.MALE, LocalDate.of(2023, Month.JULY, 12)); + GenderType.MALE, DEFAULT_EMAIL); 회원가입(팔로워_회원가입_요청); final String 팔로워_로그인_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(new LoginRequest(팔로워_회원가입_요청.identifier(), 팔로워_회원가입_요청.password())).accessToken()); @@ -647,7 +595,7 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 투두_아이디 = 골룸_투두리스트_추가후_아이디를_반환한다(기본_로그인_토큰, 골룸_아이디); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -669,16 +617,15 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -698,16 +645,15 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -757,17 +703,15 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); final Long 팔로워_아이디 = 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -789,16 +733,15 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); final Long 팔로워_아이디 = 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -825,11 +768,10 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); 골룸을_시작한다(기본_로그인_토큰, 골룸_아이디); @@ -851,22 +793,21 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); final MemberJoinRequest 팔로워1_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follow1", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follow1", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워1_로그인_요청 = new LoginRequest(팔로워1_회원_가입_요청.identifier(), 팔로워1_회원_가입_요청.password()); 회원가입(팔로워1_회원_가입_요청); final String 팔로워1_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워1_로그인_요청).accessToken()); final MemberJoinRequest 팔로워2_회원_가입_요청 = new MemberJoinRequest("identifier3", "paswword2@", - "follow2", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follow2", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워2_로그인_요청 = new LoginRequest(팔로워2_회원_가입_요청.identifier(), 팔로워2_회원_가입_요청.password()); 회원가입(팔로워2_회원_가입_요청); final String 팔로워2_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워2_로그인_요청).accessToken()); @@ -894,16 +835,15 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); final MemberJoinRequest 팔로워1_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follow1", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follow1", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워1_로그인_요청 = new LoginRequest(팔로워1_회원_가입_요청.identifier(), 팔로워1_회원_가입_요청.password()); 회원가입(팔로워1_회원_가입_요청); final String 팔로워1_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워1_로그인_요청).accessToken()); @@ -911,7 +851,7 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { }); final MemberJoinRequest 팔로워2_회원_가입_요청 = new MemberJoinRequest("identifier3", "paswword2@", - "follow2", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follow2", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워2_로그인_요청 = new LoginRequest(팔로워2_회원_가입_요청.identifier(), 팔로워2_회원_가입_요청.password()); 회원가입(팔로워2_회원_가입_요청); final String 팔로워2_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워2_로그인_요청).accessToken()); @@ -938,16 +878,15 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -969,16 +908,15 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -1003,11 +941,10 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); @@ -1030,11 +967,10 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); 골룸을_시작한다(기본_로그인_토큰, 골룸_아이디); @@ -1060,11 +996,10 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); @@ -1091,16 +1026,15 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); final MemberJoinRequest 다른_사용자_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); 회원가입(다른_사용자_회원_가입_요청); final LoginRequest 다른_사용자_로그인_요청 = new LoginRequest(다른_사용자_회원_가입_요청.identifier(), 다른_사용자_회원_가입_요청.password()); final String 다른_사용자_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(다른_사용자_로그인_요청).accessToken()); @@ -1122,12 +1056,11 @@ class GoalRoomCreateIntegrationTest extends InitIntegrationTest { final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 십일_후, 이십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), (int) ChronoUnit.DAYS.between(십일_후, 이십일_후), 십일_후, 이십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); // when diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/GoalRoomReadIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/GoalRoomReadIntegrationTest.java index def79455d..bed2603b5 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/GoalRoomReadIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/GoalRoomReadIntegrationTest.java @@ -26,6 +26,7 @@ import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_노드_인증_횟수; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_이름; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_제한_인원; +import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_EMAIL; import static co.kirikiri.integration.fixture.MemberAPIFixture.회원가입; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵_생성; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵을_아이디로_조회하고_응답객체를_반환한다; @@ -45,9 +46,9 @@ import co.kirikiri.service.dto.goalroom.response.GoalRoomCheckFeedResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomMemberResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomResponse; +import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodeDetailResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodeResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodesResponse; -import co.kirikiri.service.dto.goalroom.response.GoalRoomToDoCheckResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomTodoResponse; import co.kirikiri.service.dto.member.request.GenderType; import co.kirikiri.service.dto.member.request.MemberJoinRequest; @@ -125,8 +126,6 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { // then assertThat(골룸_투두리스트_응답값.get(0).startDate()) - .isEqualTo(오늘); - assertThat(골룸_투두리스트_응답값.get(1).startDate()) .isEqualTo(이십일_후); } @@ -155,7 +154,7 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { 골룸_투두리스트_추가(기본_로그인_토큰, 기본_골룸_아이디, 골룸_투두_생성_요청); final MemberJoinRequest 다른_사용자_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 다른_사용자_로그인_요청 = new LoginRequest(다른_사용자_회원_가입_요청.identifier(), 다른_사용자_회원_가입_요청.password()); 회원가입(다른_사용자_회원_가입_요청); final String 다른_사용자_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(다른_사용자_로그인_요청).accessToken()); @@ -182,7 +181,7 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { final Long 기본_골룸_아이디 = 기본_골룸_생성(기본_로그인_토큰, 로드맵_응답); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -205,8 +204,7 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { new GoalRoomRoadmapNodesResponse(false, false, List.of(new GoalRoomRoadmapNodeResponse(로드맵_응답.content().nodes().get(0).id(), "roadmap 1st week", 오늘, 십일_후, 정상적인_골룸_노드_인증_횟수))), - List.of(new GoalRoomTodoResponse(1L, "GOAL_ROOM_TO_DO_CONTENT", 오늘, 십일_후, - new GoalRoomToDoCheckResponse(false))), + List.of(), List.of(new CheckFeedResponse(2L, "default-image-path", "image description", LocalDate.now()), new CheckFeedResponse(1L, "default-image-path", "image description", LocalDate.now()))); @@ -272,11 +270,10 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { final Long 두번째_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 두번째_로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(두번째_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest("Content", 십일_후, 이십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(두번째_로드맵_응답.content().nodes().get(0).id(), 10, 십일_후, 이십일_후)); final GoalRoomCreateRequest 두번째_골룸_생성_요청 = new GoalRoomCreateRequest(두번째_로드맵_응답.content().id(), 정상적인_골룸_이름, - 20, 골룸_투두_요청, 골룸_노드_별_기간_요청); + 20, 골룸_노드_별_기간_요청); final Long 두번째_골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(두번째_골룸_생성_요청, 기본_로그인_토큰); @@ -303,11 +300,10 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { final Long 두번째_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 두번째_로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(두번째_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest("Content", 십일_후, 이십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(두번째_로드맵_응답.content().nodes().get(0).id(), 10, 십일_후, 이십일_후)); final GoalRoomCreateRequest 두번째_골룸_생성_요청 = new GoalRoomCreateRequest(두번째_로드맵_응답.content().id(), 정상적인_골룸_이름, - 20, 골룸_투두_요청, 골룸_노드_별_기간_요청); + 20, 골룸_노드_별_기간_요청); final Long 두번째_골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(두번째_골룸_생성_요청, 기본_로그인_토큰); @@ -335,7 +331,7 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { 골룸을_시작한다(기본_로그인_토큰, 기본_골룸_아이디); // when - final List 골룸_노드_응답값 = 골룸_노드_조회(기본_골룸_아이디, 기본_로그인_토큰) + final List 골룸_노드_응답값 = 골룸_노드_조회(기본_골룸_아이디, 기본_로그인_토큰) .as(new TypeRef<>() { }); @@ -365,7 +361,7 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { final Long 기본_골룸_아이디 = 기본_골룸_생성(기본_로그인_토큰, 로드맵_응답); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 다른_사용자_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -386,7 +382,7 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { void 골룸의_인증피드를_전체_조회한다() throws IOException { // given final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -435,7 +431,7 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { void 골룸의_인증피드를_전체_조회시_골룸에_참여하지_않은_사용자면_예외가_발생한다() throws IOException { // given final MemberJoinRequest 다른_회원_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 다른_회원_로그인_요청 = new LoginRequest(다른_회원_회원_가입_요청.identifier(), 다른_회원_회원_가입_요청.password()); 회원가입(다른_회원_회원_가입_요청); final String 다른_회원_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(다른_회원_로그인_요청).accessToken()); @@ -466,9 +462,9 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { void 골룸의_사용자_정보를_달성률순으로_전체_조회한다() throws IOException { // given final MemberJoinRequest 팔로워1_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follow1", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follow1", GenderType.FEMALE, DEFAULT_EMAIL); final MemberJoinRequest 팔로워2_회원_가입_요청 = new MemberJoinRequest("identifier3", "paswword2@", - "follow2", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follow2", GenderType.FEMALE, DEFAULT_EMAIL); final Long 팔로워1_아이디 = 회원가입(팔로워1_회원_가입_요청); final Long 팔로워2_아이디 = 회원가입(팔로워2_회원_가입_요청); @@ -508,9 +504,9 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { void 모집중인_골룸의_사용자_정보를_참가한_최신순으로_전체_조회한다() throws IOException { // given final MemberJoinRequest 팔로워1_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follow1", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follow1", GenderType.FEMALE, DEFAULT_EMAIL); final MemberJoinRequest 팔로워2_회원_가입_요청 = new MemberJoinRequest("identifier3", "paswword2@", - "follow2", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follow2", GenderType.FEMALE, DEFAULT_EMAIL); final Long 팔로워1_아이디 = 회원가입(팔로워1_회원_가입_요청); final Long 팔로워2_아이디 = 회원가입(팔로워2_회원_가입_요청); @@ -543,9 +539,9 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { void 모집중인_골룸의_사용자_정보_조회시_정렬기준을_입력하지_않으면_참여한지_오래된순으로_정렬한다() throws IOException { // given final MemberJoinRequest 팔로워1_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follow1", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follow1", GenderType.FEMALE, DEFAULT_EMAIL); final MemberJoinRequest 팔로워2_회원_가입_요청 = new MemberJoinRequest("identifier3", "paswword2@", - "follow2", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follow2", GenderType.FEMALE, DEFAULT_EMAIL); final Long 팔로워1_아이디 = 회원가입(팔로워1_회원_가입_요청); final Long 팔로워2_아이디 = 회원가입(팔로워2_회원_가입_요청); @@ -586,6 +582,40 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { assertThat(예외_응답.message()).isEqualTo("존재하지 않는 골룸입니다. goalRoomId = 1"); } + @Test + void 로드맵의_골룸_목록을_최신순으로_조회한다() throws IOException { + // given + final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); + final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); + + final Long 기본_골룸_아이디 = 기본_골룸_생성(기본_로그인_토큰, 로드맵_응답); + + final List 모집_중인_골룸_노드_별_기간_요청 = List.of( + new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 10, 십일_후, 이십일_후)); + final GoalRoomCreateRequest 두번째_골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.content().id(), 정상적인_골룸_이름, + 20, 모집_중인_골룸_노드_별_기간_요청); + + final Long 두번째_골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(두번째_골룸_생성_요청, 기본_로그인_토큰); + + final List 진행_중인_골룸_노드_별_기간_요청 = List.of( + new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 10, 오늘, 이십일_후)); + final GoalRoomCreateRequest 세번째_골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.content().id(), 정상적인_골룸_이름, + 20, 진행_중인_골룸_노드_별_기간_요청); + + final Long 세번째_골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(세번째_골룸_생성_요청, 기본_로그인_토큰); + + // when + final RoadmapGoalRoomResponses 로드맵_아이디로_골룸_목록_조회_응답1 = 로드맵_아이디로_골룸_목록_조회(기본_로그인_토큰, 기본_로드맵_아이디, + RoadmapGoalRoomsOrderType.LATEST.name(), 10).as( + new TypeRef<>() { + }); + + // then + assertThat(로드맵_아이디로_골룸_목록_조회_응답1.responses().get(0).goalRoomId()).isEqualTo(세번째_골룸_아이디); + assertThat(로드맵_아이디로_골룸_목록_조회_응답1.responses().get(1).goalRoomId()).isEqualTo(두번째_골룸_아이디); + assertThat(로드맵_아이디로_골룸_목록_조회_응답1.responses().get(2).goalRoomId()).isEqualTo(기본_골룸_아이디); + } + @Test void 로드맵의_골룸_목록을_마감임박순으로_조회한다() throws IOException { // given @@ -594,11 +624,10 @@ class GoalRoomReadIntegrationTest extends InitIntegrationTest { final Long 기본_골룸_아이디 = 기본_골룸_생성(기본_로그인_토큰, 로드맵_응답); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest("Content", 십일_후, 이십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 10, 십일_후, 이십일_후)); final GoalRoomCreateRequest 두번째_골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.content().id(), 정상적인_골룸_이름, - 20, 골룸_투두_요청, 골룸_노드_별_기간_요청); + 20, 골룸_노드_별_기간_요청); final Long 두번째_골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(두번째_골룸_생성_요청, 기본_로그인_토큰); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/GoalRoomSchedulerIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/GoalRoomSchedulerIntegrationTest.java index d6db4ce0b..f4f5e9399 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/GoalRoomSchedulerIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/GoalRoomSchedulerIntegrationTest.java @@ -14,7 +14,7 @@ import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_노드_인증_횟수; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_이름; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_제한_인원; -import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_투두_컨텐츠; +import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_EMAIL; import static co.kirikiri.integration.fixture.MemberAPIFixture.회원가입; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵_생성; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵을_아이디로_조회하고_응답객체를_반환한다; @@ -26,17 +26,15 @@ import co.kirikiri.integration.helper.InitIntegrationTest; import co.kirikiri.persistence.goalroom.GoalRoomMemberRepository; import co.kirikiri.persistence.goalroom.GoalRoomPendingMemberRepository; -import co.kirikiri.service.GoalRoomScheduler; import co.kirikiri.service.dto.auth.request.LoginRequest; import co.kirikiri.service.dto.goalroom.request.GoalRoomCreateRequest; import co.kirikiri.service.dto.goalroom.request.GoalRoomRoadmapNodeRequest; -import co.kirikiri.service.dto.goalroom.request.GoalRoomTodoRequest; import co.kirikiri.service.dto.member.request.GenderType; import co.kirikiri.service.dto.member.request.MemberJoinRequest; import co.kirikiri.service.dto.member.response.MemberGoalRoomResponse; import co.kirikiri.service.dto.roadmap.response.RoadmapResponse; +import co.kirikiri.service.scheduler.GoalRoomScheduler; import java.io.IOException; -import java.time.LocalDate; import java.util.List; import org.junit.jupiter.api.Test; @@ -64,7 +62,7 @@ public GoalRoomSchedulerIntegrationTest(final GoalRoomScheduler goalRoomSchedule final GoalRoom 골룸 = new GoalRoom(기본_골룸_아이디, null, null, null, null); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -81,6 +79,34 @@ public GoalRoomSchedulerIntegrationTest(final GoalRoomScheduler goalRoomSchedule ); } + @Test + void 자정에_시작_날짜가_오늘_이전이면서_모집_중인_골룸들도_시작된다() throws IOException { + // given + final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); + final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); + + final Long 기본_골룸_아이디 = 기본_골룸_생성(기본_로그인_토큰, 로드맵_응답); + final GoalRoom 골룸 = new GoalRoom(기본_골룸_아이디, null, null, null, null); + + final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", + "follower", GenderType.FEMALE, DEFAULT_EMAIL); + final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); + 회원가입(팔로워_회원_가입_요청); + final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); + + 골룸_참가_요청(기본_골룸_아이디, 팔로워_액세스_토큰); + testTransactionService.골룸의_시작날짜를_변경한다(기본_골룸_아이디, 오늘.minusDays(10)); + + // when + goalRoomScheduler.startGoalRooms(); + + // then + assertAll( + () -> assertThat(goalRoomPendingMemberRepository.findAllByGoalRoom(골룸)).isEmpty(), + () -> assertThat(goalRoomMemberRepository.findAllByGoalRoom(골룸)).hasSize(2) + ); + } + @Test void 골룸의_시작날짜가_오늘보다_이후이면_아무일도_일어나지_않는다() throws IOException { // given @@ -91,7 +117,7 @@ public GoalRoomSchedulerIntegrationTest(final GoalRoomScheduler goalRoomSchedule final GoalRoom 골룸 = new GoalRoom(기본_골룸_아이디, null, null, null, null); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -118,7 +144,7 @@ public GoalRoomSchedulerIntegrationTest(final GoalRoomScheduler goalRoomSchedule final Long 기본_골룸_아이디 = 기본_골룸_생성(기본_로그인_토큰, 로드맵_응답); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = 로그인(팔로워_로그인_요청).accessToken(); @@ -144,7 +170,7 @@ public GoalRoomSchedulerIntegrationTest(final GoalRoomScheduler goalRoomSchedule final Long 기본_골룸_아이디 = 기본_골룸_생성(기본_로그인_토큰, 로드맵_응답); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = 로그인(팔로워_로그인_요청).accessToken(); @@ -169,7 +195,7 @@ public GoalRoomSchedulerIntegrationTest(final GoalRoomScheduler goalRoomSchedule final Long 기본_골룸_아이디 = 십일_후에_시작하는_골룸_생성(기본_로그인_토큰, 로드맵_응답); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = 로그인(팔로워_로그인_요청).accessToken(); @@ -195,7 +221,7 @@ public GoalRoomSchedulerIntegrationTest(final GoalRoomScheduler goalRoomSchedule final Long 기본_골룸_아이디 = 기본_골룸_생성(기본_로그인_토큰, 로드맵_응답); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = 로그인(팔로워_로그인_요청).accessToken(); @@ -210,12 +236,10 @@ public GoalRoomSchedulerIntegrationTest(final GoalRoomScheduler goalRoomSchedule } private Long 십일_후에_시작하는_골룸_생성(final String 액세스_토큰, final RoadmapResponse 로드맵_응답) { - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 십일_후, 이십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 십일_후, 이십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.content().id(), 정상적인_골룸_이름, - 정상적인_골룸_제한_인원, 골룸_투두_요청, - 골룸_노드_별_기간_요청); + 정상적인_골룸_제한_인원, 골룸_노드_별_기간_요청); final String Location_헤더 = 골룸_생성(골룸_생성_요청, 액세스_토큰).response().header(LOCATION); return Long.parseLong(Location_헤더.substring(16)); } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/MemberCreateIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/MemberCreateIntegrationTest.java index 955714a8b..9d58ca281 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/MemberCreateIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/MemberCreateIntegrationTest.java @@ -1,5 +1,6 @@ package co.kirikiri.integration; +import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_EMAIL; import static co.kirikiri.integration.fixture.MemberAPIFixture.요청을_받는_회원가입; import static org.assertj.core.api.Assertions.assertThat; @@ -10,8 +11,6 @@ import io.restassured.common.mapper.TypeRef; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; -import java.time.LocalDate; -import java.time.Month; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -22,8 +21,7 @@ class MemberCreateIntegrationTest extends InitIntegrationTest { @Test void 정상적으로_회원가입을_성공한다() { //given - final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", "password12!@#$%", "hello", "010-1234-5678", - GenderType.MALE, LocalDate.of(2023, Month.JULY, 12)); + final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", "password12!@#$%", "hello", GenderType.MALE, DEFAULT_EMAIL); //when final ExtractableResponse 회원가입_응답 = 요청을_받는_회원가입(회원가입_요청); @@ -33,11 +31,10 @@ class MemberCreateIntegrationTest extends InitIntegrationTest { } @ParameterizedTest - @ValueSource(strings = {"abc", "abcdefghijklmnopqrstu"}) + @ValueSource(strings = {"abc", "abcdefghijklmnopqrstuabcdefghijklmnopqrst"}) void 아이디_길이가_틀린_경우_회원가입에_실패한다(final String 회원_아이디) { //given - final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest(회원_아이디, "password12!", "nickname", "010-1234-5678", - GenderType.MALE, LocalDate.of(2023, Month.JULY, 12)); + final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest(회원_아이디, "password12!", "nickname", GenderType.MALE, DEFAULT_EMAIL); //when final ExtractableResponse 회원가입_응답 = 요청을_받는_회원가입(회원가입_요청); @@ -53,23 +50,21 @@ class MemberCreateIntegrationTest extends InitIntegrationTest { @ValueSource(strings = {"Abcd", "abcdefghijklmnopqrsT", "가나다라"}) void 아이디에_허용되지_않은_문자가_들어온_경우_회원가입에_실패한다(final String 회원_아이디) { //given - final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest(회원_아이디, "password12!", "nickname", "010-1234-5678", - GenderType.MALE, LocalDate.of(2023, Month.JULY, 12)); + final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest(회원_아이디, "password12!", "nickname", GenderType.MALE, DEFAULT_EMAIL); //when final ExtractableResponse 회원가입_응답 = 요청을_받는_회원가입(회원가입_요청); //then - final ErrorResponse 에러_메세지 = 회원가입_응답.as(ErrorResponse.class); + final ErrorResponse[] 에러_메세지 = 회원가입_응답.as(ErrorResponse[].class); assertThat(회원가입_응답.statusCode()).isEqualTo(HttpStatus.BAD_REQUEST.value()); - assertThat(에러_메세지.message()).isEqualTo("제약 조건에 맞지 않는 아이디입니다."); + assertThat(에러_메세지[0].message()).isEqualTo("형식에 맞지 않는 아이디입니다."); } @Test void 아이디가_중복된_경우_회원가입에_실패한다() { //given - final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", "password12!", "hello", "010-1234-5678", - GenderType.MALE, LocalDate.of(2023, Month.JULY, 12)); + final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", "password12!", "hello", GenderType.MALE, DEFAULT_EMAIL); 요청을_받는_회원가입(회원가입_요청); //when @@ -85,8 +80,7 @@ class MemberCreateIntegrationTest extends InitIntegrationTest { @ValueSource(strings = {"abcde1!", "abcdefghijklmn12"}) void 비밀번호_길이가_틀린_경우_회원가입에_실패한다(final String password) { //given - final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", password, "nickname", "010-1234-5678", - GenderType.MALE, LocalDate.of(2023, Month.JULY, 12)); + final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", password, "nickname", GenderType.MALE, DEFAULT_EMAIL); //when final ExtractableResponse 회원가입_응답 = 요청을_받는_회원가입(회원가입_요청); @@ -101,8 +95,7 @@ class MemberCreateIntegrationTest extends InitIntegrationTest { @ValueSource(strings = {"abcdef1/", "abcdefghij1₩", "abcdefgH1!"}) void 비밀번호에_허용되지_않은_문자가_들어온_경우_회원가입에_실패한다(final String password) { //given - final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", password, "nickname", "010-1234-5678", - GenderType.MALE, LocalDate.of(2023, Month.JULY, 12)); + final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", password, "nickname", GenderType.MALE, DEFAULT_EMAIL); //when final ExtractableResponse 회원가입_응답 = 요청을_받는_회원가입(회원가입_요청); @@ -117,8 +110,7 @@ class MemberCreateIntegrationTest extends InitIntegrationTest { @ValueSource(strings = {"abcdefgh", "abcdefghijkl"}) void 비밀번호에_영소문자만_들어온_경우_회원가입에_실패한다(final String password) { //given - final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", password, "nickname", "010-1234-5678", - GenderType.MALE, LocalDate.of(2023, Month.JULY, 12)); + final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", password, "nickname", GenderType.MALE, DEFAULT_EMAIL); //when final ExtractableResponse 회원가입_응답 = 요청을_받는_회원가입(회원가입_요청); @@ -133,8 +125,8 @@ class MemberCreateIntegrationTest extends InitIntegrationTest { @ValueSource(strings = {"12345678", "12345678910"}) void 비밀번호에_숫자만_들어온_경우_회원가입에_실패한다(final String password) { //given - final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", password, "nickname", "010-1234-5678", - GenderType.MALE, LocalDate.of(2023, Month.JULY, 12)); + final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", password, "nickname", + GenderType.MALE, DEFAULT_EMAIL); //when final ExtractableResponse 회원가입_응답 = 요청을_받는_회원가입(회원가입_요청); @@ -146,11 +138,10 @@ class MemberCreateIntegrationTest extends InitIntegrationTest { } @ParameterizedTest - @ValueSource(strings = {"a", "abcdefghi"}) + @ValueSource(strings = {"a", "123456789012345678901"}) void 닉네임_길이가_틀린_경우_회원가입에_실패한다(final String nickname) { //given - final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", "password12!@#$%", nickname, "010-1234-5678", - GenderType.MALE, LocalDate.of(2023, Month.JULY, 12)); + final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest("ab12", "password12!@#$%", nickname, GenderType.MALE, DEFAULT_EMAIL); //when final ExtractableResponse 회원가입_응답 = 요청을_받는_회원가입(회원가입_요청); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/MemberReadIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/MemberReadIntegrationTest.java index f45524206..d86c9a31e 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/MemberReadIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/MemberReadIntegrationTest.java @@ -1,10 +1,9 @@ package co.kirikiri.integration; -import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_BIRTHDAY; +import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_EMAIL; import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_GENDER_TYPE; import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_IDENTIFIER; import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_NICKNAME; -import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_PHONE_NUMBER; import static co.kirikiri.integration.fixture.MemberAPIFixture.요청을_받는_사용자_자신의_정보_조회_요청; import static co.kirikiri.integration.fixture.MemberAPIFixture.요청을_받는_특정_사용자의_정보_조회; import static co.kirikiri.integration.fixture.MemberAPIFixture.회원가입; @@ -36,7 +35,7 @@ class MemberReadIntegrationTest extends InitIntegrationTest { new TypeReference<>() { }); final MemberInformationResponse 예상하는_응답값 = new MemberInformationResponse(기본_회원_아이디, DEFAULT_NICKNAME, null, - DEFAULT_GENDER_TYPE.name(), DEFAULT_IDENTIFIER, DEFAULT_PHONE_NUMBER, DEFAULT_BIRTHDAY); + DEFAULT_GENDER_TYPE.name(), DEFAULT_IDENTIFIER, DEFAULT_EMAIL); assertThat(사용자_자신의_정보_조회_응답_바디).usingRecursiveComparison() .ignoringFields("profileImageUrl") @@ -47,7 +46,7 @@ class MemberReadIntegrationTest extends InitIntegrationTest { void 특정_사용자의_정보를_성공적으로_조회한다() throws JsonProcessingException { // given final MemberJoinRequest 다른_회원의_가입_요청 = new MemberJoinRequest("identifier2", "password2!", - "hello", DEFAULT_PHONE_NUMBER, DEFAULT_GENDER_TYPE, DEFAULT_BIRTHDAY); + "hello", DEFAULT_GENDER_TYPE, DEFAULT_EMAIL); final Long 다른_회원_아이디 = 회원가입(다른_회원의_가입_요청); // when diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapCreateIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapCreateIntegrationTest.java index 237e00877..32e6b9023 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapCreateIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapCreateIntegrationTest.java @@ -4,9 +4,11 @@ import static co.kirikiri.integration.fixture.CommonFixture.BEARER_TOKEN_FORMAT; import static co.kirikiri.integration.fixture.CommonFixture.아이디를_반환한다; import static co.kirikiri.integration.fixture.CommonFixture.응답_상태_코드_검증; +import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_EMAIL; import static co.kirikiri.integration.fixture.MemberAPIFixture.회원가입; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵_삭제; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵_생성; +import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵_카테고리를_생성한다; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.요청을_받는_이미지가_포함된_로드맵_생성; import static org.assertj.core.api.Assertions.assertThat; @@ -15,6 +17,7 @@ import co.kirikiri.service.dto.auth.request.LoginRequest; import co.kirikiri.service.dto.member.request.GenderType; import co.kirikiri.service.dto.member.request.MemberJoinRequest; +import co.kirikiri.service.dto.roadmap.request.RoadmapCategorySaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapDifficultyType; import co.kirikiri.service.dto.roadmap.request.RoadmapNodeSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapSaveRequest; @@ -22,14 +25,13 @@ import io.restassured.common.mapper.TypeRef; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; -import java.io.IOException; -import java.time.LocalDate; -import java.util.Collections; -import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.http.HttpStatus; +import java.io.IOException; +import java.util.Collections; +import java.util.List; class RoadmapCreateIntegrationTest extends InitIntegrationTest { @@ -244,7 +246,6 @@ class RoadmapCreateIntegrationTest extends InitIntegrationTest { final String 로드맵_노드_설명 = "a".repeat(2001); final List 로드맵_노드들 = List.of( new RoadmapNodeSaveRequest("로드맵 노드 제목", 로드맵_노드_설명, Collections.emptyList())); - testTransactionService.로드맵_카테고리를_저장한다("여행"); final RoadmapSaveRequest 로드맵_생성_요청값 = new RoadmapSaveRequest(기본_카테고리.getId(), "로드맵 제목", "로드맵 소개글", "로드맵 본문", RoadmapDifficultyType.DIFFICULT, 30, 로드맵_노드들, List.of(new RoadmapTagSaveRequest("태그1"))); @@ -354,8 +355,8 @@ class RoadmapCreateIntegrationTest extends InitIntegrationTest { // given final Long 로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); - 회원가입(new MemberJoinRequest("identifier2", "password2!", "name2", "010-1111-2222", GenderType.FEMALE, - LocalDate.now())); + 회원가입(new MemberJoinRequest("identifier2", "password2!", "name2", + GenderType.FEMALE, DEFAULT_EMAIL)); final String 다른_사용자_로그인_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(new LoginRequest("identifier2", "password2!")).accessToken()); @@ -368,4 +369,62 @@ class RoadmapCreateIntegrationTest extends InitIntegrationTest { assertThat(에러_메세지.message()).isEqualTo("해당 로드맵을 생성한 사용자가 아닙니다."); } + + @Test + void 정상적으로_카테고리를_생성한다() { + //given + final RoadmapCategorySaveRequest 로드맵_카테고리_생성_요청 = new RoadmapCategorySaveRequest("운동"); + + //when + final ExtractableResponse 로드맵_카테고리_생성_응답 = 로드맵_카테고리를_생성한다(기본_로그인_토큰, 로드맵_카테고리_생성_요청); + + //then + 응답_상태_코드_검증(로드맵_카테고리_생성_응답, HttpStatus.CREATED); + } + + @Test + void 카테고리_생성_시_10글자_초과_이름이_들어올_경우() { + //given + final RoadmapCategorySaveRequest 로드맵_카테고리_생성_요청 = new RoadmapCategorySaveRequest("10자 초과되는 카테고리 이름"); + + //when + final ExtractableResponse 로드맵_카테고리_생성_응답 = 로드맵_카테고리를_생성한다(기본_로그인_토큰, 로드맵_카테고리_생성_요청); + + //then + final ErrorResponse 에러_메세지 = 로드맵_카테고리_생성_응답.as(ErrorResponse.class); + + 응답_상태_코드_검증(로드맵_카테고리_생성_응답, HttpStatus.BAD_REQUEST); + assertThat(에러_메세지.message()).isEqualTo("카테고리 이름은 1자 이상 10자 이하입니다."); + } + + @Test + void 카테고리_생성_시_공백이_들어올_경우() { + //given + final RoadmapCategorySaveRequest 로드맵_카테고리_생성_요청 = new RoadmapCategorySaveRequest(""); + + //when + final ExtractableResponse 로드맵_카테고리_생성_응답 = 로드맵_카테고리를_생성한다(기본_로그인_토큰, 로드맵_카테고리_생성_요청); + + //then + final ErrorResponse[] 에러_메세지 = 로드맵_카테고리_생성_응답.as(ErrorResponse[].class); + + 응답_상태_코드_검증(로드맵_카테고리_생성_응답, HttpStatus.BAD_REQUEST); + assertThat(에러_메세지[0].message()).isEqualTo("카테고리 이름은 빈 값일 수 없습니다."); + } + + @Test + void 카테고리_생성_시_이미_있는_이름인_경우() { + //given + final RoadmapCategorySaveRequest 로드맵_카테고리_생성_요청 = new RoadmapCategorySaveRequest("운동"); + 로드맵_카테고리를_생성한다(기본_로그인_토큰, 로드맵_카테고리_생성_요청); + + //when + final ExtractableResponse 로드맵_카테고리_생성_응답 = 로드맵_카테고리를_생성한다(기본_로그인_토큰, 로드맵_카테고리_생성_요청); + + //then + final ErrorResponse 에러_메세지 = 로드맵_카테고리_생성_응답.as(ErrorResponse.class); + + 응답_상태_코드_검증(로드맵_카테고리_생성_응답, HttpStatus.CONFLICT); + assertThat(에러_메세지.message()).isEqualTo("이미 존재하는 이름의 카테고리입니다."); + } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReadIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReadIntegrationTest.java index e6230bd21..e51683df5 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReadIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReadIntegrationTest.java @@ -8,6 +8,8 @@ import static co.kirikiri.integration.fixture.RoadmapAPIFixture.사이즈_없이_로드맵을_조회한다; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.사이즈별로_로드맵을_조회한다; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.정렬된_카테고리별_로드맵_리스트_조회; +import static co.kirikiri.integration.fixture.RoadmapAPIFixture.카테고리_생성; +import static co.kirikiri.integration.fixture.RoadmapAPIFixture.카테고리들_생성; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; @@ -21,15 +23,16 @@ import co.kirikiri.service.dto.roadmap.request.RoadmapTagSaveRequest; import co.kirikiri.service.dto.roadmap.response.MemberRoadmapResponses; import co.kirikiri.service.dto.roadmap.response.RoadmapCategoryResponse; +import co.kirikiri.service.dto.roadmap.response.RoadmapForListResponse; import co.kirikiri.service.dto.roadmap.response.RoadmapForListResponses; import co.kirikiri.service.dto.roadmap.response.RoadmapResponse; import io.restassured.common.mapper.TypeRef; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; -import java.io.IOException; -import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; +import java.io.IOException; +import java.util.List; class RoadmapReadIntegrationTest extends InitIntegrationTest { @@ -84,7 +87,7 @@ class RoadmapReadIntegrationTest extends InitIntegrationTest { List.of(new RoadmapNodeSaveRequest("다른 로드맵 1주차", "다른 로드맵 1주차 내용", null)), List.of(new RoadmapTagSaveRequest("다른 태그1"))); final Long 두번째_로드맵_아이디 = 로드맵_생성(두번째_로드맵_생성_요청, 기본_로그인_토큰); - final RoadmapCategory 다른_카테고리 = testTransactionService.로드맵_카테고리를_저장한다("여가"); + final RoadmapCategory 다른_카테고리 = 카테고리_생성(기본_로그인_토큰, "여가"); final RoadmapSaveRequest 세번째_로드맵_생성_요청 = new RoadmapSaveRequest(다른_카테고리.getId(), "thrid roadmap", "다른 로드맵 소개글", "다른 로드맵 본문", RoadmapDifficultyType.DIFFICULT, 30, List.of(new RoadmapNodeSaveRequest("다른 로드맵 1주차", "다른 로드맵 1주차 내용", null)), @@ -104,6 +107,33 @@ class RoadmapReadIntegrationTest extends InitIntegrationTest { assertThat(로드맵_리스트_응답.responses().get(2).roadmapId()).isEqualTo(기본_로드맵_아이디); } + @Test + void 로드맵_태그가_여러개일_경우_로드맵을_조회한다() throws IOException { + // given + for (int i = 0; i < 10; i++) { + final RoadmapSaveRequest 두번째_로드맵_생성_요청 = new RoadmapSaveRequest(기본_카테고리.getId(), "roadmap" + i, + "다른 로드맵 소개글", "다른 로드맵 본문", RoadmapDifficultyType.DIFFICULT, 30, + List.of(new RoadmapNodeSaveRequest("다른 로드맵 1주차", "다른 로드맵 1주차 내용", null)), + List.of(new RoadmapTagSaveRequest("다른 태그1"), + new RoadmapTagSaveRequest("다른 태그2"), + new RoadmapTagSaveRequest("다른 태그3"))); + 로드맵_생성(두번째_로드맵_생성_요청, 기본_로그인_토큰); + } + + // when + final RoadmapForListResponses 로드맵_리스트_응답 = 사이즈별로_로드맵을_조회한다(10) + .response() + .as(new TypeRef<>() { + }); + + // then + assertThat(로드맵_리스트_응답.hasNext()).isFalse(); + assertThat(로드맵_리스트_응답.responses().size()).isEqualTo(10); + for (final RoadmapForListResponse response : 로드맵_리스트_응답.responses()) { + assertThat(response.tags().size()).isEqualTo(3); + } + } + @Test void 로드맵_조회시_사이즈_조건을_주지_않으면_예외가_발생한다() { // when @@ -120,7 +150,7 @@ class RoadmapReadIntegrationTest extends InitIntegrationTest { @Test void 로드맵_카테고리_리스트를_조회한다() { // given - final List 로드맵_카테고리_리스트 = testTransactionService.모든_로드맵_카테고리를_저장한다("IT", "여가", "운동", "시험", + final List 로드맵_카테고리_리스트 = 카테고리들_생성(기본_로그인_토큰, "IT", "여가", "운동", "시험", "게임"); // when @@ -130,10 +160,8 @@ class RoadmapReadIntegrationTest extends InitIntegrationTest { }); // then - assertThat(로드맵_카테고리_응답_리스트.get(0).id()).isEqualTo(1L); assertThat(로드맵_카테고리_응답_리스트.get(0).name()).isEqualTo("여행"); for (int index = 1; index < 로드맵_카테고리_응답_리스트.size(); index++) { - assertThat(로드맵_카테고리_응답_리스트.get(index).id()).isEqualTo(로드맵_카테고리_리스트.get(index - 1).getId()); assertThat(로드맵_카테고리_응답_리스트.get(index).name()).isEqualTo(로드맵_카테고리_리스트.get(index - 1).getName()); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReadOrderIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReadOrderIntegrationTest.java index 67c414c4a..ddd207f71 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReadOrderIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReadOrderIntegrationTest.java @@ -8,7 +8,6 @@ import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_노드_인증_횟수; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_이름; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_제한_인원; -import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_투두_컨텐츠; import static co.kirikiri.integration.fixture.MemberAPIFixture.사용자를_추가하고_토큰을_조회한다; import static co.kirikiri.integration.fixture.MemberAPIFixture.요청을_받는_사용자_자신의_정보_조회_요청; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵_생성; @@ -16,6 +15,7 @@ import static co.kirikiri.integration.fixture.RoadmapAPIFixture.리뷰를_생성한다; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.정렬된_로드맵_리스트_조회; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.정렬된_카테고리별_로드맵_리스트_조회; +import static co.kirikiri.integration.fixture.RoadmapAPIFixture.카테고리_생성; import static org.assertj.core.api.Assertions.assertThat; import co.kirikiri.domain.goalroom.GoalRoom; @@ -24,7 +24,6 @@ import co.kirikiri.persistence.dto.RoadmapOrderType; import co.kirikiri.service.dto.goalroom.request.GoalRoomCreateRequest; import co.kirikiri.service.dto.goalroom.request.GoalRoomRoadmapNodeRequest; -import co.kirikiri.service.dto.goalroom.request.GoalRoomTodoRequest; import co.kirikiri.service.dto.member.response.MemberInformationResponse; import co.kirikiri.service.dto.roadmap.request.RoadmapDifficultyType; import co.kirikiri.service.dto.roadmap.request.RoadmapNodeSaveRequest; @@ -55,8 +54,8 @@ class RoadmapReadOrderIntegrationTest extends InitIntegrationTest { final Long 두번째_로드맵_아이디 = 로드맵_생성(두번째_로드맵_생성_요청, 기본_로그인_토큰); // 다른 카테고리의 세 번째 로드맵 생성 - final RoadmapCategory 다른_카테고리 = testTransactionService.로드맵_카테고리를_저장한다("여가"); - final RoadmapSaveRequest 세번째_로드맵_생성_요청 = new RoadmapSaveRequest(다른_카테고리.getId(), "third roadmap", "다른 로드맵 소개글", + final RoadmapCategory 다른_카테고리 = 카테고리_생성(기본_로그인_토큰, "여가"); + final RoadmapSaveRequest 세번째_로드맵_생성_요청 = new RoadmapSaveRequest(2L, "third roadmap", "다른 로드맵 소개글", "다른 로드맵 본문", RoadmapDifficultyType.DIFFICULT, 30, List.of(new RoadmapNodeSaveRequest("다른 로드맵 1주차", "다른 로드맵 1주차 내용", null)), List.of(new RoadmapTagSaveRequest("다른 태그1"))); @@ -107,7 +106,7 @@ class RoadmapReadOrderIntegrationTest extends InitIntegrationTest { 리뷰를_생성한다(팔로워_액세스_토큰2, 두번째_로드맵_아이디, 두번째_로드맵_리뷰_생성_요청); // 다른 카테고리의 세 번째 로드맵 생성 - final RoadmapCategory 다른_카테고리 = testTransactionService.로드맵_카테고리를_저장한다("여가"); + final RoadmapCategory 다른_카테고리 = 카테고리_생성(기본_로그인_토큰, "여가"); final RoadmapSaveRequest 세번째_로드맵_생성_요청 = new RoadmapSaveRequest(다른_카테고리.getId(), "third roadmap", "다른 로드맵 소개글", "다른 로드맵 본문", RoadmapDifficultyType.DIFFICULT, 30, List.of(new RoadmapNodeSaveRequest("다른 로드맵 1주차", "다른 로드맵 1주차 내용", null)), @@ -146,7 +145,7 @@ class RoadmapReadOrderIntegrationTest extends InitIntegrationTest { 로드맵에_대한_골룸을_생성한다(두번째_로드맵_응답); // 다른 카테고리의 세 번째 로드맵 생성 - final RoadmapCategory 다른_카테고리 = testTransactionService.로드맵_카테고리를_저장한다("여가"); + final RoadmapCategory 다른_카테고리 = 카테고리_생성(기본_로그인_토큰, "여가"); final RoadmapSaveRequest 세번째_로드맵_생성_요청 = new RoadmapSaveRequest(다른_카테고리.getId(), "third roadmap", "다른 로드맵 소개글", "다른 로드맵 본문", RoadmapDifficultyType.DIFFICULT, 30, List.of(new RoadmapNodeSaveRequest("다른 로드맵 1주차", "다른 로드맵 1주차 내용", null)), @@ -188,7 +187,7 @@ class RoadmapReadOrderIntegrationTest extends InitIntegrationTest { 골룸을_시작한다(기본_로그인_토큰, 두번째_로드맵의_골룸_아이디); // 다른 카테고리의 세 번째 로드맵 생성 - final RoadmapCategory 다른_카테고리 = testTransactionService.로드맵_카테고리를_저장한다("여가"); + final RoadmapCategory 다른_카테고리 = 카테고리_생성(기본_로그인_토큰, "여가"); final RoadmapSaveRequest 세번째_로드맵_생성_요청 = new RoadmapSaveRequest(다른_카테고리.getId(), "third roadmap", "다른 로드맵 소개글", "다른 로드맵 본문", RoadmapDifficultyType.DIFFICULT, 30, List.of(new RoadmapNodeSaveRequest("다른 로드맵 1주차", "다른 로드맵 1주차 내용", null)), @@ -222,7 +221,7 @@ class RoadmapReadOrderIntegrationTest extends InitIntegrationTest { final Long 두번째_로드맵_아이디 = 로드맵_생성(두번째_로드맵_생성_요청, 기본_로그인_토큰); // 세 번째 로드맵 생성 - final RoadmapCategory 다른_카테고리 = testTransactionService.로드맵_카테고리를_저장한다("여가"); + final RoadmapCategory 다른_카테고리 = 카테고리_생성(기본_로그인_토큰, "여가"); final RoadmapSaveRequest 세번째_로드맵_생성_요청 = new RoadmapSaveRequest(다른_카테고리.getId(), "third roadmap", "다른 로드맵 소개글", "다른 로드맵 본문", RoadmapDifficultyType.DIFFICULT, 30, List.of(new RoadmapNodeSaveRequest("다른 로드맵 1주차", "다른 로드맵 1주차 내용", null)), @@ -275,7 +274,7 @@ class RoadmapReadOrderIntegrationTest extends InitIntegrationTest { 리뷰를_생성한다(팔로워_액세스_토큰2, 두번째_로드맵_아이디, 두번째_로드맵_리뷰_생성_요청); // 세 번째 로드맵 생성 - final RoadmapCategory 다른_카테고리 = testTransactionService.로드맵_카테고리를_저장한다("여가"); + final RoadmapCategory 다른_카테고리 = 카테고리_생성(기본_로그인_토큰, "여가"); final RoadmapSaveRequest 세번째_로드맵_생성_요청 = new RoadmapSaveRequest(다른_카테고리.getId(), "third roadmap", "다른 로드맵 소개글", "다른 로드맵 본문", RoadmapDifficultyType.DIFFICULT, 30, List.of(new RoadmapNodeSaveRequest("다른 로드맵 1주차", "다른 로드맵 1주차 내용", null)), @@ -323,7 +322,7 @@ class RoadmapReadOrderIntegrationTest extends InitIntegrationTest { 로드맵에_대한_골룸을_생성한다(두번째_로드맵_응답); // 세 번째 로드맵 생성 - final RoadmapCategory 다른_카테고리 = testTransactionService.로드맵_카테고리를_저장한다("여가"); + final RoadmapCategory 다른_카테고리 = 카테고리_생성(기본_로그인_토큰, "여가"); final RoadmapSaveRequest 세번째_로드맵_생성_요청 = new RoadmapSaveRequest(다른_카테고리.getId(), "third roadmap", "다른 로드맵 소개글", "다른 로드맵 본문", RoadmapDifficultyType.DIFFICULT, 30, List.of(new RoadmapNodeSaveRequest("다른 로드맵 1주차", "다른 로드맵 1주차 내용", null)), @@ -370,7 +369,7 @@ class RoadmapReadOrderIntegrationTest extends InitIntegrationTest { final Long 두번째_로드맵_아이디 = 로드맵_생성(두번째_로드맵_생성_요청, 기본_로그인_토큰); // 세 번째 로드맵 생성 - final RoadmapCategory 다른_카테고리 = testTransactionService.로드맵_카테고리를_저장한다("여가"); + final RoadmapCategory 다른_카테고리 = 카테고리_생성(기본_로그인_토큰, "여가"); final RoadmapSaveRequest 세번째_로드맵_생성_요청 = new RoadmapSaveRequest(다른_카테고리.getId(), "third roadmap", "다른 로드맵 소개글", "다른 로드맵 본문", RoadmapDifficultyType.DIFFICULT, 30, List.of(new RoadmapNodeSaveRequest("다른 로드맵 1주차", "다른 로드맵 1주차 내용", null)), @@ -398,11 +397,10 @@ class RoadmapReadOrderIntegrationTest extends InitIntegrationTest { } private Long 로드맵에_대한_골룸을_생성한다(final RoadmapResponse 로드맵_응답) { - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); return 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReviewCreateIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReviewCreateIntegrationTest.java index 6d88168b1..3f5784e8a 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReviewCreateIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReviewCreateIntegrationTest.java @@ -9,6 +9,7 @@ import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_이름; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_제한_인원; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_투두_컨텐츠; +import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_EMAIL; import static co.kirikiri.integration.fixture.MemberAPIFixture.요청을_받는_사용자_자신의_정보_조회_요청; import static co.kirikiri.integration.fixture.MemberAPIFixture.회원가입; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵_생성; @@ -22,7 +23,6 @@ import co.kirikiri.service.dto.auth.request.LoginRequest; import co.kirikiri.service.dto.goalroom.request.GoalRoomCreateRequest; import co.kirikiri.service.dto.goalroom.request.GoalRoomRoadmapNodeRequest; -import co.kirikiri.service.dto.goalroom.request.GoalRoomTodoRequest; import co.kirikiri.service.dto.member.request.GenderType; import co.kirikiri.service.dto.member.request.MemberJoinRequest; import co.kirikiri.service.dto.member.response.MemberInformationResponse; @@ -31,11 +31,10 @@ import io.restassured.common.mapper.TypeRef; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; -import java.io.IOException; -import java.time.LocalDate; -import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; +import java.io.IOException; +import java.util.List; class RoadmapReviewCreateIntegrationTest extends InitIntegrationTest { @@ -46,7 +45,7 @@ class RoadmapReviewCreateIntegrationTest extends InitIntegrationTest { final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(로드맵_아이디); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -75,7 +74,7 @@ class RoadmapReviewCreateIntegrationTest extends InitIntegrationTest { final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(로드맵_아이디); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -106,7 +105,7 @@ class RoadmapReviewCreateIntegrationTest extends InitIntegrationTest { final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(로드맵_아이디); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -136,7 +135,7 @@ class RoadmapReviewCreateIntegrationTest extends InitIntegrationTest { final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(로드맵_아이디); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -164,7 +163,7 @@ class RoadmapReviewCreateIntegrationTest extends InitIntegrationTest { void 로드맵_리뷰_생성시_존재하지_않은_로드맵이면_예외가_발생한다() { // given final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -187,16 +186,15 @@ class RoadmapReviewCreateIntegrationTest extends InitIntegrationTest { final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(로드맵_아이디); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); final RoadmapReviewSaveRequest 로드맵_리뷰_생성_요청 = new RoadmapReviewSaveRequest("리뷰 내용", 5.0); @@ -217,7 +215,7 @@ class RoadmapReviewCreateIntegrationTest extends InitIntegrationTest { final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(로드맵_아이디); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); @@ -248,7 +246,7 @@ class RoadmapReviewCreateIntegrationTest extends InitIntegrationTest { final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(로드맵_아이디); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "follower", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follower", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); final Long 팔로워_아이디 = 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReviewReadIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReviewReadIntegrationTest.java index 63250b791..ba7dd7fea 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReviewReadIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapReviewReadIntegrationTest.java @@ -2,6 +2,7 @@ import static co.kirikiri.integration.fixture.AuthenticationAPIFixture.로그인; import static co.kirikiri.integration.fixture.CommonFixture.BEARER_TOKEN_FORMAT; +import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_EMAIL; import static co.kirikiri.integration.fixture.MemberAPIFixture.요청을_받는_사용자_자신의_정보_조회_요청; import static co.kirikiri.integration.fixture.MemberAPIFixture.회원가입; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵_리뷰를_조회한다; @@ -28,12 +29,11 @@ import io.restassured.common.mapper.TypeRef; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; import java.io.IOException; -import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; -import org.junit.jupiter.api.Test; -import org.springframework.http.HttpStatus; class RoadmapReviewReadIntegrationTest extends InitIntegrationTest { @@ -44,7 +44,7 @@ class RoadmapReviewReadIntegrationTest extends InitIntegrationTest { final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(로드맵_아이디); final MemberJoinRequest 리더_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "leader", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "leader", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 리더_로그인_요청 = new LoginRequest(리더_회원_가입_요청.identifier(), 리더_회원_가입_요청.password()); 회원가입(리더_회원_가입_요청); final String 리더_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(리더_로그인_요청).accessToken()); @@ -52,7 +52,7 @@ class RoadmapReviewReadIntegrationTest extends InitIntegrationTest { }); final MemberJoinRequest 팔로워1_회원_가입_요청 = new MemberJoinRequest("identifier3", "paswword2@", - "follow1", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follow1", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워1_로그인_요청 = new LoginRequest(팔로워1_회원_가입_요청.identifier(), 팔로워1_회원_가입_요청.password()); 회원가입(팔로워1_회원_가입_요청); final String 팔로워1_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워1_로그인_요청).accessToken()); @@ -60,7 +60,7 @@ class RoadmapReviewReadIntegrationTest extends InitIntegrationTest { }); final MemberJoinRequest 팔로워2_회원_가입_요청 = new MemberJoinRequest("identifier4", "paswword2@", - "follow2", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follow2", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워2_로그인_요청 = new LoginRequest(팔로워2_회원_가입_요청.identifier(), 팔로워2_회원_가입_요청.password()); 회원가입(팔로워2_회원_가입_요청); final String 팔로워2_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워2_로그인_요청).accessToken()); @@ -120,7 +120,7 @@ class RoadmapReviewReadIntegrationTest extends InitIntegrationTest { final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(로드맵_아이디); final MemberJoinRequest 리더_회원_가입_요청 = new MemberJoinRequest("identifier2", "paswword2@", - "leader", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "leader", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 리더_로그인_요청 = new LoginRequest(리더_회원_가입_요청.identifier(), 리더_회원_가입_요청.password()); 회원가입(리더_회원_가입_요청); final String 리더_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(리더_로그인_요청).accessToken()); @@ -128,7 +128,7 @@ class RoadmapReviewReadIntegrationTest extends InitIntegrationTest { }); final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest("identifier3", "paswword2@", - "follow1", "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + "follow1", GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); final String 팔로워_액세스_토큰 = String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapSchedulerIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapSchedulerIntegrationTest.java index 406714c21..a5a3e83f4 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapSchedulerIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapSchedulerIntegrationTest.java @@ -6,7 +6,6 @@ import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_노드_인증_횟수; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_이름; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_제한_인원; -import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_투두_컨텐츠; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵_삭제; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵_생성; import static co.kirikiri.integration.fixture.RoadmapAPIFixture.로드맵을_아이디로_조회하고_응답객체를_반환한다; @@ -15,17 +14,16 @@ import co.kirikiri.domain.goalroom.GoalRoomStatus; import co.kirikiri.integration.helper.InitIntegrationTest; import co.kirikiri.persistence.roadmap.RoadmapRepository; -import co.kirikiri.service.RoadmapScheduler; +import co.kirikiri.service.scheduler.RoadmapScheduler; import co.kirikiri.service.dto.goalroom.request.GoalRoomCreateRequest; import co.kirikiri.service.dto.goalroom.request.GoalRoomRoadmapNodeRequest; -import co.kirikiri.service.dto.goalroom.request.GoalRoomTodoRequest; import co.kirikiri.service.dto.roadmap.response.RoadmapResponse; +import org.junit.jupiter.api.Test; import java.io.IOException; import java.time.LocalDate; import java.util.List; -import org.junit.jupiter.api.Test; -public class RoadmapSchedulerIntegrationTest extends InitIntegrationTest { +class RoadmapSchedulerIntegrationTest extends InitIntegrationTest { private static final LocalDate 현재부터_3개월_1일_전 = 오늘.minusMonths(3).minusDays(1); @@ -44,19 +42,17 @@ public RoadmapSchedulerIntegrationTest(final RoadmapScheduler roadmapScheduler, final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디1 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); - final GoalRoomTodoRequest 골룸_투두_요청2 = new GoalRoomTodoRequest("골룸 투두", 오늘, 십일_후); final List 골룸_노드_별_기간_요청2 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청2 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청2, 골룸_노드_별_기간_요청2); + 골룸_노드_별_기간_요청2); final Long 골룸_아이디2 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청2, 기본_로그인_토큰); @@ -78,19 +74,17 @@ public RoadmapSchedulerIntegrationTest(final RoadmapScheduler roadmapScheduler, final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디1 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); - final GoalRoomTodoRequest 골룸_투두_요청2 = new GoalRoomTodoRequest("골룸 투두", 오늘, 십일_후); final List 골룸_노드_별_기간_요청2 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청2 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청2, 골룸_노드_별_기간_요청2); + 골룸_노드_별_기간_요청2); final Long 골룸_아이디2 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청2, 기본_로그인_토큰); @@ -111,19 +105,17 @@ public RoadmapSchedulerIntegrationTest(final RoadmapScheduler roadmapScheduler, final Long 기본_로드맵_아이디 = 로드맵_생성(기본_로드맵_생성_요청, 기본_로그인_토큰); final RoadmapResponse 로드맵_응답 = 로드맵을_아이디로_조회하고_응답객체를_반환한다(기본_로드맵_아이디); - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디1 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); - final GoalRoomTodoRequest 골룸_투두_요청2 = new GoalRoomTodoRequest("골룸 투두", 오늘, 십일_후); final List 골룸_노드_별_기간_요청2 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청2 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청2, 골룸_노드_별_기간_요청2); + 골룸_노드_별_기간_요청2); final Long 골룸_아이디2 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청2, 기본_로그인_토큰); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapSearchIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapSearchIntegrationTest.java index 9d9218533..0f763186e 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapSearchIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/RoadmapSearchIntegrationTest.java @@ -15,9 +15,9 @@ import co.kirikiri.service.dto.roadmap.request.RoadmapTagSaveRequest; import co.kirikiri.service.dto.roadmap.response.RoadmapForListResponses; import io.restassured.common.mapper.TypeRef; +import org.junit.jupiter.api.Test; import java.io.IOException; import java.util.List; -import org.junit.jupiter.api.Test; class RoadmapSearchIntegrationTest extends InitIntegrationTest { diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/fixture/GoalRoomAPIFixture.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/fixture/GoalRoomAPIFixture.java index 87c56b030..500761b69 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/fixture/GoalRoomAPIFixture.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/fixture/GoalRoomAPIFixture.java @@ -15,14 +15,14 @@ import io.restassured.http.Header; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; import java.io.IOException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.List; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.mock.web.MockMultipartFile; public class GoalRoomAPIFixture { @@ -53,11 +53,10 @@ public class GoalRoomAPIFixture { } public static Long 기본_골룸_생성(final String 액세스_토큰, final RoadmapResponse 로드맵_응답) { - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.content().id(), 정상적인_골룸_이름, - 정상적인_골룸_제한_인원, 골룸_투두_요청, 골룸_노드_별_기간_요청); + 정상적인_골룸_제한_인원, 골룸_노드_별_기간_요청); final String Location_헤더 = 골룸_생성(골룸_생성_요청, 액세스_토큰).response().header(LOCATION); return Long.parseLong(Location_헤더.substring(16)); } @@ -100,11 +99,10 @@ public class GoalRoomAPIFixture { } public static Long 정상적인_골룸_생성(final String 액세스_토큰, final Long 로드맵_아이디, final Long 로드맵_노드_아이디) { - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_노드_아이디, 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_아이디, 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final ExtractableResponse 골룸_생성_응답 = 골룸_생성(골룸_생성_요청, 액세스_토큰); final String Location_헤더 = 골룸_생성_응답.response().header("Location"); return Long.parseLong(Location_헤더.substring(16)); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/fixture/MemberAPIFixture.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/fixture/MemberAPIFixture.java index 1bb9e43f2..5cec01f3c 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/fixture/MemberAPIFixture.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/fixture/MemberAPIFixture.java @@ -11,8 +11,6 @@ import co.kirikiri.service.dto.member.request.MemberJoinRequest; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; -import java.time.LocalDate; -import java.time.Month; import org.springframework.http.MediaType; public class MemberAPIFixture { @@ -20,9 +18,8 @@ public class MemberAPIFixture { public static final String DEFAULT_IDENTIFIER = "identifier1"; public static final String DEFAULT_PASSWORD = "password1!"; public static final String DEFAULT_NICKNAME = "nickname"; - public static final String DEFAULT_PHONE_NUMBER = "010-1234-5678"; - public static final LocalDate DEFAULT_BIRTHDAY = LocalDate.of(2023, Month.JULY, 12); public static final GenderType DEFAULT_GENDER_TYPE = GenderType.MALE; + public static final String DEFAULT_EMAIL = "kirikiri1@email.com"; public static ExtractableResponse 요청을_받는_회원가입(final MemberJoinRequest 회원가입_요청) { return given().log().all() @@ -43,7 +40,7 @@ public class MemberAPIFixture { public static Long 기본_회원가입() { final MemberJoinRequest 회원가입_요청 = new MemberJoinRequest(DEFAULT_IDENTIFIER, DEFAULT_PASSWORD, DEFAULT_NICKNAME, - DEFAULT_PHONE_NUMBER, DEFAULT_GENDER_TYPE, DEFAULT_BIRTHDAY); + DEFAULT_GENDER_TYPE, DEFAULT_EMAIL); return 회원가입(회원가입_요청); } @@ -71,7 +68,7 @@ public class MemberAPIFixture { public static String 사용자를_추가하고_토큰을_조회한다(final String 아이디, final String 닉네임) { final MemberJoinRequest 팔로워_회원_가입_요청 = new MemberJoinRequest(아이디, "paswword2@", - 닉네임, "010-1234-1234", GenderType.FEMALE, LocalDate.of(1999, 9, 9)); + 닉네임, GenderType.FEMALE, DEFAULT_EMAIL); final LoginRequest 팔로워_로그인_요청 = new LoginRequest(팔로워_회원_가입_요청.identifier(), 팔로워_회원_가입_요청.password()); 회원가입(팔로워_회원_가입_요청); return String.format(BEARER_TOKEN_FORMAT, 로그인(팔로워_로그인_요청).accessToken()); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/fixture/RoadmapAPIFixture.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/fixture/RoadmapAPIFixture.java index ab718d8aa..0acc14aae 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/fixture/RoadmapAPIFixture.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/fixture/RoadmapAPIFixture.java @@ -4,8 +4,10 @@ import static co.kirikiri.integration.fixture.CommonFixture.AUTHORIZATION; import static io.restassured.RestAssured.given; +import co.kirikiri.domain.roadmap.RoadmapCategory; import co.kirikiri.persistence.dto.RoadmapOrderType; import co.kirikiri.service.dto.CustomScrollRequest; +import co.kirikiri.service.dto.roadmap.request.RoadmapCategorySaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapNodeSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapReviewSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapSaveRequest; @@ -15,10 +17,12 @@ import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import io.restassured.specification.RequestSpecification; -import java.io.IOException; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; public class RoadmapAPIFixture { @@ -210,4 +214,30 @@ private static RequestSpecification makeRequestSpecification(final RoadmapSaveRe .then().log().all() .extract(); } + + public static ExtractableResponse 로드맵_카테고리를_생성한다(final String 로그인_토큰_정보, final RoadmapCategorySaveRequest 카테고리_생성_요청) { + return given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when() + .header(AUTHORIZATION, 로그인_토큰_정보) + .body(카테고리_생성_요청) + .post("/api/roadmaps/categories") + .then() + .log().all() + .extract(); + } + + public static RoadmapCategory 카테고리_생성(final String 로그인_토큰_정보, final String 카테고리_이름) { + 로드맵_카테고리를_생성한다(로그인_토큰_정보, new RoadmapCategorySaveRequest(카테고리_이름)); + return new RoadmapCategory(1L, 카테고리_이름); + } + + public static List 카테고리들_생성(final String 로그인_토큰_정보, final String... 카테고리_이름들) { + final List 카테고리들 = new ArrayList<>(); + for (final String 카테고리_이름 : 카테고리_이름들) { + final RoadmapCategory 카테고리 = 카테고리_생성(로그인_토큰_정보, 카테고리_이름); + 카테고리들.add(카테고리); + } + return 카테고리들; + } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/DatabaseCleaner.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/DatabaseCleaner.java index 6a89e221d..4bcfe3b86 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/DatabaseCleaner.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/DatabaseCleaner.java @@ -2,17 +2,17 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; +import org.hibernate.Session; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Component; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.transaction.annotation.Transactional; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; -import org.hibernate.Session; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.stereotype.Component; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.transaction.annotation.Transactional; @Component @ActiveProfiles("test") diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/InitIntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/InitIntegrationTest.java index aede0b1f6..28b448b74 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/InitIntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/InitIntegrationTest.java @@ -3,14 +3,15 @@ import static co.kirikiri.integration.fixture.AuthenticationAPIFixture.기본_로그인; import static co.kirikiri.integration.fixture.CommonFixture.BEARER_TOKEN_FORMAT; import static co.kirikiri.integration.fixture.MemberAPIFixture.기본_회원가입; +import static co.kirikiri.integration.fixture.RoadmapAPIFixture.카테고리_생성; import co.kirikiri.domain.roadmap.RoadmapCategory; import co.kirikiri.service.dto.roadmap.request.RoadmapDifficultyType; import co.kirikiri.service.dto.roadmap.request.RoadmapNodeSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapTagSaveRequest; -import java.util.List; import org.junit.jupiter.api.BeforeEach; +import java.util.List; public class InitIntegrationTest extends IntegrationTest { @@ -25,7 +26,7 @@ void init() { 기본_회원_아이디 = 기본_회원가입(); 기본_로그인_토큰 = String.format(BEARER_TOKEN_FORMAT, 기본_로그인().accessToken()); 기본_재발행_토큰 = 기본_로그인().refreshToken(); - 기본_카테고리 = testTransactionService.로드맵_카테고리를_저장한다("여행"); + 기본_카테고리 = 카테고리_생성(기본_로그인_토큰, "여행"); 기본_로드맵_생성_요청 = new RoadmapSaveRequest(기본_카테고리.getId(), "로드맵 제목", "로드맵 소개글", "로드맵 본문", RoadmapDifficultyType.DIFFICULT, 30, List.of(new RoadmapNodeSaveRequest("roadmap 1st week", "로드맵 1주차 내용", null)), diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/IntegrationTest.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/IntegrationTest.java index 63d9c360f..4ce173e30 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/IntegrationTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/IntegrationTest.java @@ -20,9 +20,6 @@ @Import(TestConfig.class) public class IntegrationTest { -// @Value("${server.servlet.contextPath}") -// protected String API_PREFIX; - @LocalServerPort private int port; diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/TestConfig.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/TestConfig.java index a8800178c..8f62a2887 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/TestConfig.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/TestConfig.java @@ -1,8 +1,8 @@ package co.kirikiri.integration.helper; +import co.kirikiri.persistence.auth.RefreshTokenRepository; import co.kirikiri.persistence.goalroom.GoalRoomMemberRepository; import co.kirikiri.persistence.goalroom.GoalRoomRepository; -import co.kirikiri.persistence.roadmap.RoadmapCategoryRepository; import co.kirikiri.service.FileService; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; @@ -10,14 +10,11 @@ @TestConfiguration public class TestConfig { - private final RoadmapCategoryRepository roadmapCategoryRepository; private final GoalRoomRepository goalRoomRepository; private final GoalRoomMemberRepository goalRoomMemberRepository; - public TestConfig(final RoadmapCategoryRepository roadmapCategoryRepository, - final GoalRoomRepository goalRoomRepository, + public TestConfig(final GoalRoomRepository goalRoomRepository, final GoalRoomMemberRepository goalRoomMemberRepository) { - this.roadmapCategoryRepository = roadmapCategoryRepository; this.goalRoomRepository = goalRoomRepository; this.goalRoomMemberRepository = goalRoomMemberRepository; } @@ -29,6 +26,11 @@ public FileService fileService() { @Bean public TestTransactionService testTransactionService() { - return new TestTransactionService(roadmapCategoryRepository, goalRoomRepository, goalRoomMemberRepository); + return new TestTransactionService(goalRoomRepository, goalRoomMemberRepository); + } + + @Bean + public RefreshTokenRepository refreshTokenRepository() { + return new TestRefreshTokenRepository(); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/TestRefreshTokenRepository.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/TestRefreshTokenRepository.java new file mode 100644 index 000000000..94f9344a0 --- /dev/null +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/TestRefreshTokenRepository.java @@ -0,0 +1,18 @@ +package co.kirikiri.integration.helper; + +import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_IDENTIFIER; + +import co.kirikiri.persistence.auth.RefreshTokenRepository; +import java.util.Optional; + +public class TestRefreshTokenRepository implements RefreshTokenRepository { + + @Override + public void save(final String refreshToken, final String memberIdentifier) { + } + + @Override + public Optional findMemberIdentifierByRefreshToken(final String refreshToken) { + return Optional.of(DEFAULT_IDENTIFIER); + } +} diff --git a/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/TestTransactionService.java b/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/TestTransactionService.java index 967dc41a0..accf118e2 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/TestTransactionService.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/integration/helper/TestTransactionService.java @@ -6,7 +6,6 @@ import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_노드_인증_횟수; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_이름; import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_제한_인원; -import static co.kirikiri.integration.fixture.GoalRoomAPIFixture.정상적인_골룸_투두_컨텐츠; import static co.kirikiri.integration.fixture.MemberAPIFixture.DEFAULT_PASSWORD; import static co.kirikiri.integration.helper.InitIntegrationTest.기본_로그인_토큰; @@ -21,13 +20,10 @@ import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Nickname; import co.kirikiri.domain.member.vo.Password; -import co.kirikiri.domain.roadmap.RoadmapCategory; import co.kirikiri.persistence.goalroom.GoalRoomMemberRepository; import co.kirikiri.persistence.goalroom.GoalRoomRepository; -import co.kirikiri.persistence.roadmap.RoadmapCategoryRepository; import co.kirikiri.service.dto.goalroom.request.GoalRoomCreateRequest; import co.kirikiri.service.dto.goalroom.request.GoalRoomRoadmapNodeRequest; -import co.kirikiri.service.dto.goalroom.request.GoalRoomTodoRequest; import co.kirikiri.service.dto.member.response.MemberInformationResponse; import co.kirikiri.service.dto.roadmap.response.RoadmapResponse; import jakarta.persistence.EntityManager; @@ -44,33 +40,15 @@ public class TestTransactionService { @PersistenceContext private EntityManager em; - private final RoadmapCategoryRepository roadmapCategoryRepository; private final GoalRoomRepository goalRoomRepository; private final GoalRoomMemberRepository goalRoomMemberRepository; - public TestTransactionService(final RoadmapCategoryRepository roadmapCategoryRepository, - final GoalRoomRepository goalRoomRepository, + public TestTransactionService(final GoalRoomRepository goalRoomRepository, final GoalRoomMemberRepository goalRoomMemberRepository) { - this.roadmapCategoryRepository = roadmapCategoryRepository; this.goalRoomRepository = goalRoomRepository; this.goalRoomMemberRepository = goalRoomMemberRepository; } - public List 모든_로드맵_카테고리를_저장한다(final String... 카테고리_이름_목록) { - final List roadmapCategories = new ArrayList<>(); - for (final String 카테고리_이름 : 카테고리_이름_목록) { - final RoadmapCategory 로드맵_카테고리 = 로드맵_카테고리를_저장한다(카테고리_이름); - roadmapCategories.add(new RoadmapCategory(로드맵_카테고리.getId(), 카테고리_이름)); - } - roadmapCategoryRepository.saveAll(roadmapCategories); - return roadmapCategories; - } - - public RoadmapCategory 로드맵_카테고리를_저장한다(final String 카테고리_이름) { - final RoadmapCategory 로드맵_카테고리 = new RoadmapCategory(카테고리_이름); - return roadmapCategoryRepository.save(로드맵_카테고리); - } - public GoalRoom 골룸을_완료시킨다(final Long 골룸_아이디) { final GoalRoom 골룸 = goalRoomRepository.findById(골룸_아이디).get(); 골룸.complete(); @@ -78,11 +56,10 @@ public TestTransactionService(final RoadmapCategoryRepository roadmapCategoryRep } public GoalRoom 완료한_골룸을_생성한다(final RoadmapResponse 로드맵_응답) { - final GoalRoomTodoRequest 골룸_투두_요청 = new GoalRoomTodoRequest(정상적인_골룸_투두_컨텐츠, 오늘, 십일_후); final List 골룸_노드_별_기간_요청 = List.of( new GoalRoomRoadmapNodeRequest(로드맵_응답.content().nodes().get(0).id(), 정상적인_골룸_노드_인증_횟수, 오늘, 십일_후)); final GoalRoomCreateRequest 골룸_생성_요청 = new GoalRoomCreateRequest(로드맵_응답.roadmapId(), 정상적인_골룸_이름, 정상적인_골룸_제한_인원, - 골룸_투두_요청, 골룸_노드_별_기간_요청); + 골룸_노드_별_기간_요청); final Long 골룸_아이디 = 골룸을_생성하고_아이디를_반환한다(골룸_생성_요청, 기본_로그인_토큰); return 골룸을_완료시킨다(골룸_아이디); } @@ -105,14 +82,13 @@ public TestTransactionService(final RoadmapCategoryRepository roadmapCategoryRep } private Member 사용자_정보에서_사용자를_생성한다(final MemberInformationResponse 사용자_정보) { - final MemberProfile memberProfile = new MemberProfile(Gender.valueOf(사용자_정보.gender()), 사용자_정보.birthday(), - 사용자_정보.phoneNumber()); - return new Member(사용자_정보.id(), new Identifier(사용자_정보.identifier()), new EncryptedPassword(new Password( + final MemberProfile memberProfile = new MemberProfile(Gender.valueOf(사용자_정보.gender()), 사용자_정보.email()); + return new Member(사용자_정보.id(), new Identifier(사용자_정보.identifier()), null, new EncryptedPassword(new Password( DEFAULT_PASSWORD)), new Nickname(사용자_정보.nickname()), null, memberProfile); } public void 골룸_멤버를_저장한다(final List 골룸_멤버_리스트) { - goalRoomMemberRepository.saveAll(골룸_멤버_리스트); + goalRoomMemberRepository.saveAllInBatch(골룸_멤버_리스트); } public void 골룸의_상태와_종료날짜를_변경한다(final Long 골룸_아이디, final GoalRoomStatus 골룸_상태, final LocalDate 변경할_종료날짜) { diff --git a/backend/kirikiri/src/test/java/co/kirikiri/persistence/auth/RefreshTokenRepositoryTest.java b/backend/kirikiri/src/test/java/co/kirikiri/persistence/auth/RefreshTokenRepositoryTest.java index 7a3cc0cb6..d31e6d075 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/persistence/auth/RefreshTokenRepositoryTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/persistence/auth/RefreshTokenRepositoryTest.java @@ -1,9 +1,9 @@ package co.kirikiri.persistence.auth; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.mockito.Mockito.when; -import co.kirikiri.domain.auth.EncryptedToken; -import co.kirikiri.domain.auth.RefreshToken; import co.kirikiri.domain.member.EncryptedPassword; import co.kirikiri.domain.member.Gender; import co.kirikiri.domain.member.Member; @@ -11,56 +11,87 @@ import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Nickname; import co.kirikiri.domain.member.vo.Password; -import co.kirikiri.persistence.helper.RepositoryTest; -import co.kirikiri.persistence.member.MemberRepository; -import java.time.LocalDate; -import java.time.LocalDateTime; import java.util.Optional; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; -@RepositoryTest +@ExtendWith(MockitoExtension.class) class RefreshTokenRepositoryTest { + private static final Long refreshTokenValidityInSeconds = 3600000L; + private static Member member; - private final RefreshTokenRepository refreshTokenRepository; - private final MemberRepository memberRepository; + @Mock + private RedisTemplate redisTemplate; + + @Mock + private ValueOperations valueOperations; + + private RefreshTokenRepositoryImpl refreshTokenRepository; - public RefreshTokenRepositoryTest(final RefreshTokenRepository refreshTokenRepository, - final MemberRepository memberRepository) { - this.refreshTokenRepository = refreshTokenRepository; - this.memberRepository = memberRepository; + @BeforeEach + void init() { + when(redisTemplate.opsForValue()) + .thenReturn(valueOperations); + refreshTokenRepository = new RefreshTokenRepositoryImpl(redisTemplate, refreshTokenValidityInSeconds); } + @BeforeAll static void setUp() { final Identifier identifier = new Identifier("identifier1"); final Password password = new Password("password1!"); final EncryptedPassword encryptedPassword = new EncryptedPassword(password); final Nickname nickname = new Nickname("nickname"); - final String phoneNumber = "010-1234-5678"; - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.now(), phoneNumber); + final String email = "kirikiri1@email.com"; + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, email); member = new Member(identifier, encryptedPassword, nickname, null, memberProfile); } @Test - void 정상적으로_취소되지_않은_리프레시_토큰을_찾아온다() { + void 정상적으로_리프레시_토큰을_저장한다() { //given - final EncryptedToken encryptedToken = new EncryptedToken("refreshToken"); - final LocalDateTime now = LocalDateTime.now(); - final RefreshToken refreshToken = new RefreshToken(encryptedToken, now, member); - memberRepository.save(member); - refreshTokenRepository.save(refreshToken); + final String refreshToken = "refreshToken"; + final String memberIdentifier = member.getIdentifier().getValue(); //when - final Optional optionalRefreshToken = refreshTokenRepository.findByTokenAndIsRevokedFalse( - encryptedToken); + //then + assertDoesNotThrow(() -> refreshTokenRepository.save(refreshToken, memberIdentifier)); + } + + @Test + void 정상적으로_리프레시_토큰을_찾아온다() { + //given + final String refreshToken = "refreshToken"; + final String memberIdentifier = member.getIdentifier().getValue(); + + when(valueOperations.get(refreshToken)) + .thenReturn(memberIdentifier); + //when + final String findMemberIdentifier = refreshTokenRepository.findMemberIdentifierByRefreshToken(refreshToken) + .get(); + + //then + assertThat(findMemberIdentifier).isEqualTo(memberIdentifier); + } + + @Test + void 리프레시_토큰을_찾을때_없는경우_빈값을_보낸다() { + //given + final String refreshToken = "refreshToken"; + + //when + final Optional memberIdentifier = refreshTokenRepository.findMemberIdentifierByRefreshToken( + refreshToken); //then - assertThat(optionalRefreshToken).isNotEmpty(); - final RefreshToken result = optionalRefreshToken.get(); - assertThat(result.getToken()).usingRecursiveComparison() - .isEqualTo(encryptedToken); + assertThat(memberIdentifier).isEmpty(); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/persistence/dto/RoadmapSearchTagNameTest.java b/backend/kirikiri/src/test/java/co/kirikiri/persistence/dto/RoadmapSearchTagNameTest.java index fb9553bf2..23459fce2 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/persistence/dto/RoadmapSearchTagNameTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/persistence/dto/RoadmapSearchTagNameTest.java @@ -4,7 +4,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.service.exception.BadRequestException; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; diff --git a/backend/kirikiri/src/test/java/co/kirikiri/persistence/dto/RoadmapSearchTitleTest.java b/backend/kirikiri/src/test/java/co/kirikiri/persistence/dto/RoadmapSearchTitleTest.java index 3b1fc8512..add4ecca9 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/persistence/dto/RoadmapSearchTitleTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/persistence/dto/RoadmapSearchTitleTest.java @@ -4,7 +4,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import co.kirikiri.exception.BadRequestException; +import co.kirikiri.service.exception.BadRequestException; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; diff --git a/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/CheckFeedRepositoryTest.java b/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/CheckFeedRepositoryTest.java index ba07f357b..f4eb535ee 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/CheckFeedRepositoryTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/CheckFeedRepositoryTest.java @@ -86,7 +86,7 @@ public CheckFeedRepositoryTest(final MemberRepository memberRepository, final GoalRoomMember leader = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.now(), goalRoom, creator); final GoalRoomMember joinedMember = new GoalRoomMember(GoalRoomRole.FOLLOWER, LocalDateTime.now(), goalRoom, member); - goalRoomMemberRepository.saveAll(List.of(leader, joinedMember)); + goalRoomMemberRepository.saveAllInBatch(List.of(leader, joinedMember)); final GoalRoomRoadmapNode goalRoomRoadmapNode = goalRoom.getGoalRoomRoadmapNodes().getValues().get(0); 인증_피드를_저장한다(goalRoomRoadmapNode, joinedMember); @@ -120,7 +120,7 @@ public CheckFeedRepositoryTest(final MemberRepository memberRepository, final GoalRoomMember leader = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.now(), goalRoom, creator); final GoalRoomMember joinedMember = new GoalRoomMember(GoalRoomRole.FOLLOWER, LocalDateTime.now(), goalRoom, member); - goalRoomMemberRepository.saveAll(List.of(leader, joinedMember)); + goalRoomMemberRepository.saveAllInBatch(List.of(leader, joinedMember)); final GoalRoomRoadmapNode goalRoomRoadmapNode = goalRoom.getGoalRoomRoadmapNodes().getValues().get(0); 인증_피드를_저장한다(goalRoomRoadmapNode, joinedMember); @@ -151,7 +151,7 @@ public CheckFeedRepositoryTest(final MemberRepository memberRepository, final GoalRoomMember leader = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.now(), goalRoom, creator); final GoalRoomMember joinedMember = new GoalRoomMember(GoalRoomRole.FOLLOWER, LocalDateTime.now(), goalRoom, member); - goalRoomMemberRepository.saveAll(List.of(leader, joinedMember)); + goalRoomMemberRepository.saveAllInBatch(List.of(leader, joinedMember)); final GoalRoomRoadmapNode goalRoomRoadmapNode1 = goalRoom.getGoalRoomRoadmapNodes().getValues().get(0); final GoalRoomRoadmapNode goalRoomRoadmapNode2 = goalRoom.getGoalRoomRoadmapNodes().getValues().get(1); @@ -188,7 +188,7 @@ public CheckFeedRepositoryTest(final MemberRepository memberRepository, member); final GoalRoomMember otherLeader = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.now(), goalRoom2, creator); - goalRoomMemberRepository.saveAll(List.of(leader, joinedMember)); + goalRoomMemberRepository.saveAllInBatch(List.of(leader, joinedMember)); final GoalRoomRoadmapNode goalRoomRoadmapNode1 = goalRoom1.getGoalRoomRoadmapNodes().getValues().get(0); final GoalRoomRoadmapNode goalRoomRoadmapNode2 = goalRoom1.getGoalRoomRoadmapNodes().getValues().get(1); @@ -226,7 +226,7 @@ public CheckFeedRepositoryTest(final MemberRepository memberRepository, final GoalRoomMember leader = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.now(), goalRoom, creator); final GoalRoomMember joinedMember = new GoalRoomMember(GoalRoomRole.FOLLOWER, LocalDateTime.now(), goalRoom, member); - goalRoomMemberRepository.saveAll(List.of(leader, joinedMember)); + goalRoomMemberRepository.saveAllInBatch(List.of(leader, joinedMember)); final GoalRoomRoadmapNode goalRoomRoadmapNode1 = goalRoom.getGoalRoomRoadmapNodes().getValues().get(0); final GoalRoomRoadmapNode goalRoomRoadmapNode2 = goalRoom.getGoalRoomRoadmapNodes().getValues().get(1); @@ -269,7 +269,7 @@ public CheckFeedRepositoryTest(final MemberRepository memberRepository, final GoalRoomMember leader = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.now(), goalRoom, creator); final GoalRoomMember joinedMember = new GoalRoomMember(GoalRoomRole.FOLLOWER, LocalDateTime.now(), goalRoom, member); - goalRoomMemberRepository.saveAll(List.of(leader, joinedMember)); + goalRoomMemberRepository.saveAllInBatch(List.of(leader, joinedMember)); final GoalRoomRoadmapNode goalRoomRoadmapNode1 = goalRoom.getGoalRoomRoadmapNodes().getValues().get(0); final GoalRoomRoadmapNode goalRoomRoadmapNode2 = goalRoom.getGoalRoomRoadmapNodes().getValues().get(1); @@ -303,7 +303,7 @@ public CheckFeedRepositoryTest(final MemberRepository memberRepository, final GoalRoomMember leader = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.now(), goalRoom, creator); final GoalRoomMember joinedMember = new GoalRoomMember(GoalRoomRole.FOLLOWER, LocalDateTime.now(), goalRoom, member); - goalRoomMemberRepository.saveAll(List.of(leader, joinedMember)); + goalRoomMemberRepository.saveAllInBatch(List.of(leader, joinedMember)); final GoalRoomRoadmapNode goalRoomRoadmapNode1 = goalRoom.getGoalRoomRoadmapNodes().getValues().get(0); final GoalRoomRoadmapNode goalRoomRoadmapNode2 = goalRoom.getGoalRoomRoadmapNodes().getValues().get(1); @@ -348,7 +348,7 @@ public CheckFeedRepositoryTest(final MemberRepository memberRepository, final GoalRoomMember leader = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.now(), goalRoom, creator); final GoalRoomMember joinedMember = new GoalRoomMember(GoalRoomRole.FOLLOWER, LocalDateTime.now(), goalRoom, member); - goalRoomMemberRepository.saveAll(List.of(leader, joinedMember)); + goalRoomMemberRepository.saveAllInBatch(List.of(leader, joinedMember)); final GoalRoomRoadmapNode goalRoomRoadmapNode1 = goalRoom.getGoalRoomRoadmapNodes().getValues().get(0); final GoalRoomRoadmapNode goalRoomRoadmapNode2 = goalRoom.getGoalRoomRoadmapNodes().getValues().get(1); @@ -407,7 +407,7 @@ public CheckFeedRepositoryTest(final MemberRepository memberRepository, final GoalRoomMember leader = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.now(), goalRoom, creator); final GoalRoomMember joinedMember = new GoalRoomMember(GoalRoomRole.FOLLOWER, LocalDateTime.now(), goalRoom, member); - goalRoomMemberRepository.saveAll(List.of(leader, joinedMember)); + goalRoomMemberRepository.saveAllInBatch(List.of(leader, joinedMember)); final GoalRoomRoadmapNode goalRoomRoadmapNode1 = goalRoom.getGoalRoomRoadmapNodes().getValues().get(0); final GoalRoomRoadmapNode goalRoomRoadmapNode2 = goalRoom.getGoalRoomRoadmapNodes().getValues().get(1); @@ -436,8 +436,7 @@ public CheckFeedRepositoryTest(final MemberRepository memberRepository, private Member 사용자를_저장한다(final String identifier, final String nickname) { final MemberImage memberImage = new MemberImage("originalFileName", "serverFilePath", ImageContentType.PNG); - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, - LocalDate.of(1990, 1, 1), "010-1234-5678"); + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, "kirikiri1@email.com"); final Member creator = new Member(new Identifier(identifier), new EncryptedPassword(new Password("password1!")), new Nickname(nickname), memberImage, memberProfile); return memberRepository.save(creator); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomMemberRepositoryTest.java b/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomMemberRepositoryTest.java index ca306c9a7..5fed7fa95 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomMemberRepositoryTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomMemberRepositoryTest.java @@ -129,9 +129,9 @@ public GoalRoomMemberRepositoryTest(final MemberRepository memberRepository, final GoalRoom goalRoom = 골룸을_생성한다(targetRoadmapContent, creator); final GoalRoom savedGoalRoom = goalRoomRepository.save(goalRoom); - final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "010-1111-1111"); - final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "010-1111-1112"); - final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "010-1111-1113"); + final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "kirikiri1@email.com"); + final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "kirikiri1@email.com"); + final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "kirikiri1@email.com"); final GoalRoomMember goalRoomMember1 = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.of(2023, 7, 19, 12, 0, 0), savedGoalRoom, member1); @@ -164,9 +164,9 @@ public GoalRoomMemberRepositoryTest(final MemberRepository memberRepository, final GoalRoom goalRoom = 골룸을_생성한다(targetRoadmapContent, creator); final GoalRoom savedGoalRoom = goalRoomRepository.save(goalRoom); - final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "010-1111-1111"); - final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "010-1111-1112"); - final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "010-1111-1113"); + final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "kirikiri1@email.com"); + final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "kirikiri1@email.com"); + final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "kirikiri1@email.com"); final GoalRoomMember goalRoomMember1 = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.of(2023, 7, 19, 12, 0, 0), savedGoalRoom, member1); @@ -199,9 +199,9 @@ public GoalRoomMemberRepositoryTest(final MemberRepository memberRepository, final GoalRoom goalRoom = 골룸을_생성한다(targetRoadmapContent, creator); final GoalRoom savedGoalRoom = goalRoomRepository.save(goalRoom); - final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "010-1111-1111"); - final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "010-1111-1112"); - final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "010-1111-1113"); + final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "kirikiri1@email.com"); + final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "kirikiri1@email.com"); + final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "kirikiri1@email.com"); final GoalRoomMember goalRoomMember1 = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.of(2023, 7, 19, 12, 0, 0), savedGoalRoom, member1); @@ -235,9 +235,9 @@ public GoalRoomMemberRepositoryTest(final MemberRepository memberRepository, final GoalRoom goalRoom = 골룸을_생성한다(targetRoadmapContent, creator); final GoalRoom savedGoalRoom = goalRoomRepository.save(goalRoom); - final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "010-1111-1111"); - final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "010-1111-1112"); - final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "010-1111-1113"); + final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "kirikiri1@email.com"); + final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "kirikiri1@email.com"); + final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "kirikiri1@email.com"); final GoalRoomMember goalRoomMember1 = new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.of(2023, 7, 19, 12, 0, 0), savedGoalRoom, member1); @@ -267,7 +267,7 @@ public GoalRoomMemberRepositoryTest(final MemberRepository memberRepository, @Test void 골룸_아이디와_사용자_아이디로_골룸_멤버를_조회한다() { // given - final Member creator = 사용자를_생성한다("identifier1", "password!1", "name1", "01011111111"); + final Member creator = 사용자를_생성한다("identifier1", "password!1", "name1", "kirikiri1@email.com"); final RoadmapCategory category = 카테고리를_저장한다("여가"); final Roadmap roadmap = 로드맵을_저장한다(creator, category); @@ -295,15 +295,15 @@ public GoalRoomMemberRepositoryTest(final MemberRepository memberRepository, private Member 크리에이터를_저장한다() { final MemberImage memberImage = new MemberImage("originalFileName", "serverFilePath", ImageContentType.JPG); - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.of(1990, 1, 1), "010-1234-5678"); - final Member creator = new Member(1L, new Identifier("cokirikiri"), + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, "kirikiri1@email.com"); + final Member creator = new Member(1L, new Identifier("cokirikiri"), null, new EncryptedPassword(new Password("password1!")), new Nickname("코끼리"), memberImage, memberProfile); return memberRepository.save(creator); } private Member 사용자를_생성한다(final String identifier, final String password, final String nickname, - final String phoneNumber) { - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.of(1990, 1, 1), phoneNumber); + final String email) { + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, email); final Member member = new Member(new Identifier(identifier), new EncryptedPassword(new Password(password)), new Nickname(nickname), new MemberImage("file-name", "file-path", ImageContentType.PNG), memberProfile); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomPendingMemberRepositoryTest.java b/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomPendingMemberRepositoryTest.java index 080c9dbdb..2febbb556 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomPendingMemberRepositoryTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomPendingMemberRepositoryTest.java @@ -33,12 +33,12 @@ import co.kirikiri.persistence.member.MemberRepository; import co.kirikiri.persistence.roadmap.RoadmapCategoryRepository; import co.kirikiri.persistence.roadmap.RoadmapRepository; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; @RepositoryTest class GoalRoomPendingMemberRepositoryTest { @@ -128,9 +128,9 @@ public GoalRoomPendingMemberRepositoryTest(final MemberRepository memberReposito final GoalRoom goalRoom = 골룸을_생성한다(targetRoadmapContent, creator); final GoalRoom savedGoalRoom = goalRoomRepository.save(goalRoom); - final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "010-1111-1111"); - final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "010-1111-1112"); - final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "010-1111-1113"); + final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "kirikiri1@email.com"); + final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "kirikiri1@email.com"); + final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "kirikiri1@email.com"); final GoalRoomPendingMember goalRoomPendingMember = new GoalRoomPendingMember(GoalRoomRole.LEADER, LocalDateTime.now(), savedGoalRoom, creator); @@ -168,7 +168,7 @@ public GoalRoomPendingMemberRepositoryTest(final MemberRepository memberReposito final GoalRoom goalRoom = 골룸을_생성한다(targetRoadmapContent, creator); final GoalRoom savedGoalRoom = goalRoomRepository.save(goalRoom); - final Member follower = 사용자를_생성한다("identifier2", "password!2", "name", "010-1111-1111"); + final Member follower = 사용자를_생성한다("identifier2", "password!2", "name", "kirikiri1@email.com"); //when savedGoalRoom.join(follower); @@ -200,9 +200,9 @@ public GoalRoomPendingMemberRepositoryTest(final MemberRepository memberReposito final GoalRoom goalRoom = 골룸을_생성한다(targetRoadmapContent, creator); final GoalRoom savedGoalRoom = goalRoomRepository.save(goalRoom); - final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "010-1111-1111"); - final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "010-1111-1112"); - final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "010-1111-1113"); + final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "kirikiri1@email.com"); + final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "kirikiri1@email.com"); + final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "kirikiri1@email.com"); final GoalRoomPendingMember goalRoomPendingMember0 = goalRoom.getGoalRoomPendingMembers().getValues().get(0); final GoalRoomPendingMember goalRoomPendingMember1 = new GoalRoomPendingMember(GoalRoomRole.FOLLOWER, @@ -238,9 +238,9 @@ public GoalRoomPendingMemberRepositoryTest(final MemberRepository memberReposito final GoalRoom goalRoom = 골룸을_생성한다(targetRoadmapContent, creator); final GoalRoom savedGoalRoom = goalRoomRepository.save(goalRoom); - final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "010-1111-1111"); - final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "010-1111-1112"); - final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "010-1111-1113"); + final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "kirikiri1@email.com"); + final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "kirikiri1@email.com"); + final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "kirikiri1@email.com"); final GoalRoomPendingMember goalRoomPendingMember0 = goalRoom.getGoalRoomPendingMembers().getValues().get(0); final GoalRoomPendingMember goalRoomPendingMember1 = new GoalRoomPendingMember(GoalRoomRole.LEADER, @@ -280,9 +280,9 @@ public GoalRoomPendingMemberRepositoryTest(final MemberRepository memberReposito final GoalRoom goalRoom = 골룸을_생성한다(targetRoadmapContent, creator); final GoalRoom savedGoalRoom = goalRoomRepository.save(goalRoom); - final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "010-1111-1111"); - final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "010-1111-1112"); - final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "010-1111-1113"); + final Member member1 = 사용자를_생성한다("identifier1", "password2!", "name1", "kirikiri1@email.com"); + final Member member2 = 사용자를_생성한다("identifier2", "password3!", "name2", "kirikiri1@email.com"); + final Member member3 = 사용자를_생성한다("identifier3", "password4!", "name3", "kirikiri1@email.com"); final GoalRoomPendingMember goalRoomPendingMember0 = goalRoom.getGoalRoomPendingMembers().getValues().get(0); final GoalRoomPendingMember goalRoomPendingMember1 = new GoalRoomPendingMember(GoalRoomRole.LEADER, @@ -310,7 +310,7 @@ public GoalRoomPendingMemberRepositoryTest(final MemberRepository memberReposito } private Member 크리에이터를_저장한다() { - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.of(1990, 1, 1), "010-1234-5678"); + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, "kirikiri1@email.com"); final Member creator = new Member(new Identifier("cokirikiri"), new EncryptedPassword(new Password("password1!")), new Nickname("코끼리"), new MemberImage("originalFileName", "serverFilePath", ImageContentType.PNG), memberProfile); @@ -318,8 +318,8 @@ public GoalRoomPendingMemberRepositoryTest(final MemberRepository memberReposito } private Member 사용자를_생성한다(final String identifier, final String password, final String nickname, - final String phoneNumber) { - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.of(1990, 1, 1), phoneNumber); + final String email) { + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, email); final Member member = new Member(new Identifier(identifier), new EncryptedPassword(new Password(password)), new Nickname(nickname), new MemberImage("originalFileName", "serverFilePath", ImageContentType.PNG), memberProfile); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomRepositoryTest.java b/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomRepositoryTest.java index a70ced50d..38f6fb513 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomRepositoryTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomRepositoryTest.java @@ -30,9 +30,9 @@ import co.kirikiri.persistence.member.MemberRepository; import co.kirikiri.persistence.roadmap.RoadmapCategoryRepository; import co.kirikiri.persistence.roadmap.RoadmapRepository; +import org.junit.jupiter.api.Test; import java.time.LocalDate; import java.util.List; -import org.junit.jupiter.api.Test; @RepositoryTest class GoalRoomRepositoryTest { @@ -60,7 +60,7 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, @Test void 골룸_아이디로_골룸_정보를_조회한다() { //given - final Member creator = 사용자를_생성한다("name1", "01011111111", "identifier1", "password!1"); + final Member creator = 사용자를_생성한다("name1", "kirikiri@email.com", "identifier1", "password!1"); final RoadmapCategory category = 카테고리를_저장한다("여가"); final RoadmapNode roadmapNode1 = 로드맵_노드를_생성한다("로드맵 1주차", "로드맵 1주차 내용"); final RoadmapNode roadmapNode2 = 로드맵_노드를_생성한다("로드맵 2주차", "로드맵 2주차 내용"); @@ -71,7 +71,7 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, roadmapNode1); final GoalRoomRoadmapNode goalRoomRoadmapNode2 = 골룸_로드맵_노드를_생성한다(TODAY.plusDays(11), TODAY.plusDays(20), roadmapNode2); - final Member goalRoomPendingMember1 = 사용자를_생성한다("name2", "01011112222", "identifier2", "password!2"); + final Member goalRoomPendingMember1 = 사용자를_생성한다("name2", "kirikiri@email.com", "identifier2", "password!2"); final GoalRoom goalRoom = 골룸을_생성한다("goalroom1", 6, roadmapContent, new GoalRoomRoadmapNodes(List.of(goalRoomRoadmapNode1, goalRoomRoadmapNode2)), goalRoomPendingMember1); goalRoomRepository.save(goalRoom); @@ -90,7 +90,7 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, @Test void 골룸을_최신순으로_조회한다() { //given - final Member creator = 사용자를_생성한다("name1", "01011111111", "identifier1", "password!1"); + final Member creator = 사용자를_생성한다("name1", "kirikiri@email.com", "identifier1", "password!1"); final RoadmapCategory category = 카테고리를_저장한다("여가"); final RoadmapNode roadmapNode1 = 로드맵_노드를_생성한다("로드맵 1주차", "로드맵 1주차 내용"); final RoadmapNode roadmapNode2 = 로드맵_노드를_생성한다("로드맵 2주차", "로드맵 2주차 내용"); @@ -101,7 +101,7 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, roadmapNode1); final GoalRoomRoadmapNode goalRoomRoadmapNode2 = 골룸_로드맵_노드를_생성한다(TODAY.plusDays(11), TODAY.plusDays(20), roadmapNode2); - final Member goalRoomPendingMember1 = 사용자를_생성한다("name2", "01011112222", "identifier2", "password!2"); + final Member goalRoomPendingMember1 = 사용자를_생성한다("name2", "kirikiri@email.com", "identifier2", "password!2"); final GoalRoom goalRoom1 = 골룸을_생성한다("goalroom1", 6, roadmapContent, new GoalRoomRoadmapNodes(List.of(goalRoomRoadmapNode1, goalRoomRoadmapNode2)), goalRoomPendingMember1); goalRoomRepository.save(goalRoom1); @@ -110,15 +110,15 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, roadmapNode1); final GoalRoomRoadmapNode goalRoomRoadmapNode4 = 골룸_로드맵_노드를_생성한다(TODAY.plusDays(11), TODAY.plusDays(20), roadmapNode2); - final Member goalRoomPendingMember2 = 사용자를_생성한다("name3", "01011113333", "identifier3", "password!3"); + final Member goalRoomPendingMember2 = 사용자를_생성한다("name3", "kirikiri@email.com", "identifier3", "password!3"); final GoalRoom goalRoom2 = 골룸을_생성한다("goalroom2", 20, roadmapContent, new GoalRoomRoadmapNodes(List.of(goalRoomRoadmapNode3, goalRoomRoadmapNode4)), goalRoomPendingMember2); goalRoomRepository.save(goalRoom2); // when - final List goalRooms1 = goalRoomRepository.findGoalRoomsWithPendingMembersByRoadmapAndCond(roadmap, + final List goalRooms1 = goalRoomRepository.findGoalRoomsByRoadmapAndCond(roadmap, RoadmapGoalRoomsOrderType.LATEST, null, 1); - final List goalRooms2 = goalRoomRepository.findGoalRoomsWithPendingMembersByRoadmapAndCond(roadmap, + final List goalRooms2 = goalRoomRepository.findGoalRoomsByRoadmapAndCond(roadmap, RoadmapGoalRoomsOrderType.LATEST, goalRoom2.getId(), 10); assertThat(goalRooms1) @@ -130,7 +130,7 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, @Test void 골룸을_마감임박_순으로_조회한다() { //given - final Member creator = 사용자를_생성한다("name1", "01011111111", "identifier1", "password!1"); + final Member creator = 사용자를_생성한다("name1", "kirikiri@email.com", "identifier1", "password!1"); final RoadmapCategory category = 카테고리를_저장한다("여가"); final RoadmapNode roadmapNode1 = 로드맵_노드를_생성한다("로드맵 1주차", "로드맵 1주차 내용"); final RoadmapNode roadmapNode2 = 로드맵_노드를_생성한다("로드맵 2주차", "로드맵 2주차 내용"); @@ -140,7 +140,7 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, final GoalRoomRoadmapNode goalRoomRoadmapNode1 = 골룸_로드맵_노드를_생성한다(TODAY, TODAY.plusDays(10), roadmapNode1); final GoalRoomRoadmapNode goalRoomRoadmapNode2 = 골룸_로드맵_노드를_생성한다(TODAY.plusDays(11), TODAY.plusDays(20), roadmapNode2); - final Member goalRoomPendingMember1 = 사용자를_생성한다("name2", "01011112222", "identifier2", "password!2"); + final Member goalRoomPendingMember1 = 사용자를_생성한다("name2", "kirikiri@email.com", "identifier2", "password!2"); final GoalRoom goalRoom1 = 골룸을_생성한다("goalroom1", 6, roadmapContent, new GoalRoomRoadmapNodes(List.of(goalRoomRoadmapNode1, goalRoomRoadmapNode2)), goalRoomPendingMember1); goalRoomRepository.save(goalRoom1); @@ -149,15 +149,15 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, roadmapNode1); final GoalRoomRoadmapNode goalRoomRoadmapNode4 = 골룸_로드맵_노드를_생성한다(TODAY.plusDays(11), TODAY.plusDays(20), roadmapNode2); - final Member goalRoomPendingMember3 = 사용자를_생성한다("name4", "01011114444", "identifier4", "password!4"); + final Member goalRoomPendingMember3 = 사용자를_생성한다("name4", "kirikiri@email.com", "identifier4", "password!4"); final GoalRoom goalRoom2 = 골룸을_생성한다("goalroom2", 6, roadmapContent, new GoalRoomRoadmapNodes(List.of(goalRoomRoadmapNode3, goalRoomRoadmapNode4)), goalRoomPendingMember3); goalRoomRepository.save(goalRoom2); // when - final List goalRooms1 = goalRoomRepository.findGoalRoomsWithPendingMembersByRoadmapAndCond(roadmap, + final List goalRooms1 = goalRoomRepository.findGoalRoomsByRoadmapAndCond(roadmap, RoadmapGoalRoomsOrderType.CLOSE_TO_DEADLINE, null, 1); - final List goalRooms2 = goalRoomRepository.findGoalRoomsWithPendingMembersByRoadmapAndCond(roadmap, + final List goalRooms2 = goalRoomRepository.findGoalRoomsByRoadmapAndCond(roadmap, RoadmapGoalRoomsOrderType.CLOSE_TO_DEADLINE, goalRoom1.getId(), 10); // then @@ -193,7 +193,7 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, goalRoomRepository.save(goalRoom3); // when - final List findGoalRooms = goalRoomRepository.findAllByStartDate(LocalDate.now()); + final List findGoalRooms = goalRoomRepository.findAllRecruitingGoalRoomsByStartDateEarlierThan(LocalDate.now()); // then assertThat(findGoalRooms) @@ -204,7 +204,7 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, @Test void 투두리스트와_함께_골룸을_조회한다() { - final Member creator = 사용자를_생성한다("name1", "01011111111", "identifier1", "password!1"); + final Member creator = 사용자를_생성한다("name1", "kirikiri@email.com", "identifier1", "password!1"); final RoadmapCategory category = 카테고리를_저장한다("여가"); final RoadmapNode roadmapNode1 = 로드맵_노드를_생성한다("로드맵 1주차", "로드맵 1주차 내용"); final RoadmapNode roadmapNode2 = 로드맵_노드를_생성한다("로드맵 2주차", "로드맵 2주차 내용"); @@ -215,7 +215,7 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, roadmapNode1); final GoalRoomRoadmapNode goalRoomRoadmapNode2 = 골룸_로드맵_노드를_생성한다(TODAY.plusDays(11), TODAY.plusDays(20), roadmapNode2); - final Member goalRoomPendingMember = 사용자를_생성한다("name2", "01011112222", "identifier2", "password!2"); + final Member goalRoomPendingMember = 사용자를_생성한다("name2", "kirikiri@email.com", "identifier2", "password!2"); final GoalRoom goalRoom = 골룸을_생성한다("goalroom1", 6, roadmapContent, new GoalRoomRoadmapNodes(List.of(goalRoomRoadmapNode1, goalRoomRoadmapNode2)), goalRoomPendingMember); @@ -403,7 +403,7 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, @Test void 노드와_함께_골룸을_조회한다() { - final Member creator = 사용자를_생성한다("name1", "01011111111", "identifier1", "password!1"); + final Member creator = 사용자를_생성한다("name1", "kirikiri@email.com", "identifier1", "password!1"); final RoadmapCategory category = 카테고리를_저장한다("여가"); final RoadmapNode roadmapNode1 = 로드맵_노드를_생성한다("로드맵 1주차", "로드맵 1주차 내용"); final RoadmapNode roadmapNode2 = 로드맵_노드를_생성한다("로드맵 2주차", "로드맵 2주차 내용"); @@ -414,7 +414,7 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, roadmapNode1); final GoalRoomRoadmapNode goalRoomRoadmapNode2 = 골룸_로드맵_노드를_생성한다(TODAY.plusDays(11), TODAY.plusDays(20), roadmapNode2); - final Member goalRoomPendingMember = 사용자를_생성한다("name2", "01011112222", "identifier2", "password!2"); + final Member goalRoomPendingMember = 사용자를_생성한다("name2", "kirikiri@email.com", "identifier2", "password!2"); final GoalRoom goalRoom = 골룸을_생성한다("goalroom1", 6, roadmapContent, new GoalRoomRoadmapNodes(List.of(goalRoomRoadmapNode1, goalRoomRoadmapNode2)), goalRoomPendingMember); goalRoomRepository.save(goalRoom); @@ -464,7 +464,7 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, @Test void 로드맵으로_골룸을_조회한다() { // given - final Member creator = 사용자를_생성한다("name1", "01011111111", "identifier1", "password!1"); + final Member creator = 사용자를_생성한다("name1", "kirikiri@email.com", "identifier1", "password!1"); final RoadmapCategory category = 카테고리를_저장한다("여가"); final RoadmapNode roadmapNode1 = 로드맵_노드를_생성한다("로드맵 1주차", "로드맵 1주차 내용"); final RoadmapNode roadmapNode2 = 로드맵_노드를_생성한다("로드맵 2주차", "로드맵 2주차 내용"); @@ -478,7 +478,7 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, final RoadmapContent roadmapContent2 = 로드맵_본문을_생성한다(List.of(roadmapNode3, roadmapNode4)); 로드맵을_생성한다(creator, category, roadmapContent2); - final Member member = 사용자를_생성한다("name2", "01011112222", "identifier2", "password!2"); + final Member member = 사용자를_생성한다("name2", "kirikiri@email.com", "identifier2", "password!2"); final GoalRoomRoadmapNode goalRoomRoadmapNode1 = 골룸_로드맵_노드를_생성한다(TODAY, TEN_DAY_LATER, roadmapNode1); final GoalRoomRoadmapNode goalRoomRoadmapNode2 = 골룸_로드맵_노드를_생성한다(TWENTY_DAY_LAYER, THIRTY_DAY_LATER, @@ -503,18 +503,45 @@ public GoalRoomRepositoryTest(final MemberRepository memberRepository, assertThat(goalRooms).isEqualTo(List.of(goalRoom1, goalRoom2)); } + @Test + void 시작날짜가_오늘보다_작거나_같은_모집중인_골룸들을_조회한다() { + //given + final Member creator = 크리에이터를_저장한다(); + final RoadmapCategory category = 카테고리를_저장한다("게임"); + final RoadmapNode roadmapNode = 로드맵_노드를_생성한다("로드맵 1주차", "로드맵 1주차 내용"); + final RoadmapContent roadmapContent = 로드맵_본문을_생성한다(List.of(roadmapNode)); + 로드맵을_생성한다(creator, category, roadmapContent); + + final GoalRoomRoadmapNode todayGoalRoomRoadmapNode = 골룸_로드맵_노드를_생성한다(TODAY, TEN_DAY_LATER, + roadmapNode); + final GoalRoomRoadmapNode afterTodayGoalRoomRoadmapNode = 골룸_로드맵_노드를_생성한다(TEN_DAY_LATER, TWENTY_DAY_LAYER, + roadmapNode); + + final GoalRoom todayStartGoalRoom1 = 골룸을_생성한다("goalroom1", 20, roadmapContent, + new GoalRoomRoadmapNodes(List.of(todayGoalRoomRoadmapNode)), creator); + final GoalRoom futureStartGoalRoom = 골룸을_생성한다("goalroom2", 20, roadmapContent, + new GoalRoomRoadmapNodes(List.of(afterTodayGoalRoomRoadmapNode)), creator); + final GoalRoom todayStartGoalRoom2 = 골룸을_생성한다("goalroom3", 20, roadmapContent, + new GoalRoomRoadmapNodes(List.of(todayGoalRoomRoadmapNode)), creator); + goalRoomRepository.saveAll(List.of(todayStartGoalRoom1, futureStartGoalRoom, todayStartGoalRoom2)); + + // when + final List goalRooms = goalRoomRepository.findAllRecruitingGoalRoomsByStartDateEarlierThan(LocalDate.now()); + + // then + assertThat(goalRooms).isEqualTo(List.of(todayStartGoalRoom1, todayStartGoalRoom2)); + } + private Member 크리에이터를_저장한다() { - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, - LocalDate.of(1990, 1, 1), "010-1234-5678"); + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, "kirikiri1@email.com"); final Member creator = new Member(new Identifier("cokirikiri"), new EncryptedPassword(new Password("password1!")), new Nickname("코끼리"), null, memberProfile); return memberRepository.save(creator); } - private Member 사용자를_생성한다(final String nickname, final String phoneNumber, final String identifier, + private Member 사용자를_생성한다(final String nickname, final String email, final String identifier, final String password) { - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.of(1990, 1, 1), - phoneNumber); + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, email); final Member creator = new Member(new Identifier(identifier), new EncryptedPassword(new Password(password)), new Nickname(nickname), null, memberProfile); return memberRepository.save(creator); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomToDoCheckRepositoryTest.java b/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomToDoCheckRepositoryTest.java index c590e95d2..2d7ebd328 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomToDoCheckRepositoryTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/persistence/goalroom/GoalRoomToDoCheckRepositoryTest.java @@ -160,8 +160,7 @@ public GoalRoomToDoCheckRepositoryTest(final MemberRepository memberRepository, private Member 사용자를_생성한다(final String nickname, final String phoneNumber, final String identifier, final String password) { - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.of(1990, 1, 1), - phoneNumber); + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, "kirikiri1@email.com"); final Member creator = new Member(new Identifier(identifier), new EncryptedPassword(new Password(password)), new Nickname(nickname), null, memberProfile); return memberRepository.save(creator); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/persistence/helper/RepositoryTest.java b/backend/kirikiri/src/test/java/co/kirikiri/persistence/helper/RepositoryTest.java index 3705cb9da..5bfa474ac 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/persistence/helper/RepositoryTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/persistence/helper/RepositoryTest.java @@ -1,19 +1,16 @@ package co.kirikiri.persistence.helper; -import co.kirikiri.common.config.JpaConfig; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.TestConstructor; import org.springframework.test.context.TestConstructor.AutowireMode; @DataJpaTest @ActiveProfiles("test") -@Import({JpaConfig.class}) @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @TestConstructor(autowireMode = AutowireMode.ALL) diff --git a/backend/kirikiri/src/test/java/co/kirikiri/persistence/member/MemberRepositoryTest.java b/backend/kirikiri/src/test/java/co/kirikiri/persistence/member/MemberRepositoryTest.java index 7d8d88b8f..99052941c 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/persistence/member/MemberRepositoryTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/persistence/member/MemberRepositoryTest.java @@ -13,10 +13,9 @@ import co.kirikiri.domain.member.vo.Nickname; import co.kirikiri.domain.member.vo.Password; import co.kirikiri.persistence.helper.RepositoryTest; -import java.time.LocalDate; -import java.util.Optional; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import java.util.Optional; @RepositoryTest class MemberRepositoryTest { @@ -35,8 +34,7 @@ static void setUp() { final Password password = new Password("password1!"); final EncryptedPassword encryptedPassword = new EncryptedPassword(password); final Nickname nickname = new Nickname("nickname"); - final String phoneNumber = "010-1234-5678"; - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.now(), phoneNumber); + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, "kirikiri1@email.com"); final MemberImage memberImage = new MemberImage("originalFileName", "serverFilePath", ImageContentType.PNG); member = new Member(identifier, encryptedPassword, nickname, memberImage, memberProfile); } @@ -69,8 +67,7 @@ static void setUp() { assertAll( () -> assertThat(member.getIdentifier().getValue()).isEqualTo("identifier1"), () -> assertThat(memberProfile.getGender()).isEqualTo(Gender.MALE), - () -> assertThat(memberProfile.getPhoneNumber()).isEqualTo("010-1234-5678"), - () -> assertThat(memberProfile.getBirthday()).isEqualTo(LocalDate.now()), + () -> assertThat(memberProfile.getEmail()).isEqualTo("kirikiri1@email.com"), () -> assertThat(memberImage.getServerFilePath()).isEqualTo("serverFilePath") ); } @@ -90,8 +87,7 @@ static void setUp() { assertAll( () -> assertThat(member.getIdentifier().getValue()).isEqualTo("identifier1"), () -> assertThat(memberProfile.getGender()).isEqualTo(Gender.MALE), - () -> assertThat(memberProfile.getPhoneNumber()).isEqualTo("010-1234-5678"), - () -> assertThat(memberProfile.getBirthday()).isEqualTo(LocalDate.now()), + () -> assertThat(memberProfile.getEmail()).isEqualTo("kirikiri1@email.com"), () -> assertThat(memberImage.getServerFilePath()).isEqualTo("serverFilePath") ); } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/persistence/roadmap/RoadmapContentRepositoryTest.java b/backend/kirikiri/src/test/java/co/kirikiri/persistence/roadmap/RoadmapContentRepositoryTest.java index c102751c4..9f6ce6a34 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/persistence/roadmap/RoadmapContentRepositoryTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/persistence/roadmap/RoadmapContentRepositoryTest.java @@ -16,7 +16,6 @@ import co.kirikiri.domain.roadmap.RoadmapDifficulty; import co.kirikiri.persistence.helper.RepositoryTest; import co.kirikiri.persistence.member.MemberRepository; -import java.time.LocalDate; import org.junit.jupiter.api.Test; @RepositoryTest @@ -87,7 +86,7 @@ public RoadmapContentRepositoryTest(final MemberRepository memberRepository, } private Member 사용자를_생성한다() { - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.of(1995, 9, 30), "010-0000-0000"); + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, "kirikiri1@email.com"); final Member member = new Member(new Identifier("identifier1"), new EncryptedPassword(new Password("password1!")), new Nickname("썬샷"), null, memberProfile); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/persistence/roadmap/RoadmapRepositoryTest.java b/backend/kirikiri/src/test/java/co/kirikiri/persistence/roadmap/RoadmapRepositoryTest.java index 9ad5dfdb8..83ab3ff56 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/persistence/roadmap/RoadmapRepositoryTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/persistence/roadmap/RoadmapRepositoryTest.java @@ -249,13 +249,13 @@ public RoadmapRepositoryTest(final MemberRepository memberRepository, // gameRoadmap2 : 참가인원 1명 final List gameRoadmap2GoalRoomMembers = List.of( new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.now(), gameRoadmap2GoalRoom, creator)); - goalRoomMemberRepository.saveAll(gameRoadmap2GoalRoomMembers); + goalRoomMemberRepository.saveAllInBatch(gameRoadmap2GoalRoomMembers); // travelRoadmap : 참가인원 2명 final List travelRoadmapGoalRoomMembers = List.of( new GoalRoomMember(GoalRoomRole.LEADER, LocalDateTime.now(), travelRoadmapGoalRoom, creator), new GoalRoomMember(GoalRoomRole.FOLLOWER, LocalDateTime.now(), travelRoadmapGoalRoom, follower)); - goalRoomMemberRepository.saveAll(travelRoadmapGoalRoomMembers); + goalRoomMemberRepository.saveAllInBatch(travelRoadmapGoalRoomMembers); final RoadmapCategory category = null; final RoadmapOrderType orderType = RoadmapOrderType.PARTICIPANT_COUNT; @@ -546,7 +546,7 @@ public RoadmapRepositoryTest(final MemberRepository memberRepository, } private Member 사용자를_생성한다(final String identifier, final String nickname) { - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.of(1990, 1, 1), "010-1234-5678"); + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, "kirikiri1@email.com"); final MemberImage memberImage = new MemberImage("file-name", "file-path", ImageContentType.PNG); final Member creator = new Member(new Identifier(identifier), new EncryptedPassword(new Password("password1!")), new Nickname(nickname), memberImage, memberProfile); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/persistence/roadmap/RoadmapReviewRepositoryTest.java b/backend/kirikiri/src/test/java/co/kirikiri/persistence/roadmap/RoadmapReviewRepositoryTest.java index 9f62efcb4..099dd5fc9 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/persistence/roadmap/RoadmapReviewRepositoryTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/persistence/roadmap/RoadmapReviewRepositoryTest.java @@ -21,10 +21,9 @@ import co.kirikiri.domain.roadmap.RoadmapReview; import co.kirikiri.persistence.helper.RepositoryTest; import co.kirikiri.persistence.member.MemberRepository; -import java.time.LocalDate; +import org.junit.jupiter.api.Test; import java.util.List; import java.util.Optional; -import org.junit.jupiter.api.Test; @RepositoryTest class RoadmapReviewRepositoryTest { @@ -141,7 +140,7 @@ public RoadmapReviewRepositoryTest(final MemberRepository memberRepository, } private Member 사용자를_저장한다(final String name, final String identifier) { - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.of(1990, 1, 1), "010-1234-5678"); + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, "kirikiri1@email.com"); final MemberImage memberImage = new MemberImage("test-name", "test-path", ImageContentType.PNG); final Member creator = new Member(new Identifier(identifier), new EncryptedPassword(new Password("password1!")), new Nickname(name), memberImage, memberProfile); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/AuthServiceTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/AuthServiceTest.java index 4abad60b1..ddf3ec88a 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/service/AuthServiceTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/AuthServiceTest.java @@ -3,11 +3,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.BDDMockito.given; -import co.kirikiri.domain.auth.EncryptedToken; -import co.kirikiri.domain.auth.RefreshToken; import co.kirikiri.domain.member.EncryptedPassword; import co.kirikiri.domain.member.Gender; import co.kirikiri.domain.member.Member; @@ -15,14 +12,14 @@ import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Nickname; import co.kirikiri.domain.member.vo.Password; -import co.kirikiri.exception.AuthenticationException; import co.kirikiri.persistence.auth.RefreshTokenRepository; import co.kirikiri.persistence.member.MemberRepository; +import co.kirikiri.service.auth.AuthService; +import co.kirikiri.service.auth.TokenProvider; import co.kirikiri.service.dto.auth.request.LoginRequest; import co.kirikiri.service.dto.auth.request.ReissueTokenRequest; import co.kirikiri.service.dto.auth.response.AuthenticationResponse; -import java.time.LocalDate; -import java.time.LocalDateTime; +import co.kirikiri.service.exception.AuthenticationException; import java.util.Optional; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -54,8 +51,8 @@ static void setUp() { final Password password = new Password("password1!"); final EncryptedPassword encryptedPassword = new EncryptedPassword(password); final Nickname nickname = new Nickname("nickname"); - final String phoneNumber = "010-1234-5678"; - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.now(), phoneNumber); + final String email = "kirikiri1@email"; + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, email); member = new Member(identifier, encryptedPassword, nickname, null, memberProfile); } @@ -65,20 +62,20 @@ static void setUp() { final LoginRequest loginRequest = new LoginRequest("identifier1", "password1!"); final String accessToken = "accessToken"; final String refreshToken = "refreshToken"; + given(memberRepository.findByIdentifier(any())) .willReturn(Optional.of(member)); given(tokenProvider.createAccessToken(any(), any())) .willReturn(accessToken); given(tokenProvider.createRefreshToken(any(), any())) .willReturn(refreshToken); - given(tokenProvider.findTokenExpiredAt(anyString())) - .willReturn(LocalDateTime.now()); //when final AuthenticationResponse authenticationResponse = authService.login(loginRequest); //then - assertThat(authenticationResponse).isEqualTo(new AuthenticationResponse(refreshToken, accessToken)); + assertThat(authenticationResponse).isEqualTo( + new AuthenticationResponse(refreshToken, accessToken)); } @Test @@ -110,34 +107,33 @@ static void setUp() { @Test void 정상적으로_토큰을_재발행한다() { //given - final String rawAccessToken = "accessToken"; - final String rawRefreshToken = "refreshToken"; + final String accessToken = "accessToken"; + final String refreshToken = "refreshToken"; final ReissueTokenRequest reissueTokenRequest = new ReissueTokenRequest("refreshToken"); - final RefreshToken refreshToken = new RefreshToken(new EncryptedToken(rawRefreshToken), LocalDateTime.MAX, - member); + given(tokenProvider.isValidToken(any())) .willReturn(true); - given(refreshTokenRepository.findByTokenAndIsRevokedFalse(any())) - .willReturn(Optional.of(refreshToken)); given(tokenProvider.createAccessToken(any(), any())) - .willReturn(rawAccessToken); + .willReturn(accessToken); given(tokenProvider.createRefreshToken(any(), any())) - .willReturn(rawRefreshToken); - given(tokenProvider.findTokenExpiredAt(anyString())) - .willReturn(LocalDateTime.now()); + .willReturn(refreshToken); + given(memberRepository.findByIdentifier(any())) + .willReturn(Optional.of(member)); + given(refreshTokenRepository.findMemberIdentifierByRefreshToken(any())) + .willReturn(Optional.of(refreshToken)); //when final AuthenticationResponse authenticationResponse = authService.reissueToken(reissueTokenRequest); //then - assertThat(authenticationResponse).isEqualTo(new AuthenticationResponse(rawRefreshToken, rawAccessToken)); + assertThat(authenticationResponse).isEqualTo(new AuthenticationResponse(refreshToken, accessToken)); } @Test void 리프레시_토큰이_유효하지_않을_경우_예외를_던진다() { //given - final String rawRefreshToken = "refreshToken"; - final ReissueTokenRequest reissueTokenRequest = new ReissueTokenRequest(rawRefreshToken); + final String refreshToken = "refreshToken"; + final ReissueTokenRequest reissueTokenRequest = new ReissueTokenRequest(refreshToken); given(tokenProvider.isValidToken(any())) .willReturn(false); @@ -148,13 +144,13 @@ static void setUp() { } @Test - void 리프레시_토큰이_존재하지_않을_경우_예외를_던진다() { + void 리프레시_토큰이_만료_됐을_경우_예외를_던진다() { //given - final String rawRefreshToken = "refreshToken"; - final ReissueTokenRequest reissueTokenRequest = new ReissueTokenRequest(rawRefreshToken); + final String refreshToken = "refreshToken"; + final ReissueTokenRequest reissueTokenRequest = new ReissueTokenRequest(refreshToken); given(tokenProvider.isValidToken(any())) .willReturn(true); - given(refreshTokenRepository.findByTokenAndIsRevokedFalse(any())) + given(refreshTokenRepository.findMemberIdentifierByRefreshToken(any())) .willReturn(Optional.empty()); //when @@ -164,16 +160,16 @@ static void setUp() { } @Test - void 리프레시_토큰이_만료_됐을_경우_예외를_던진다() { + void 리프레시_토큰으로_조회한_회원이_존재하지_않는_경우_예외를_던진다() { //given - final String rawRefreshToken = "refreshToken"; - final ReissueTokenRequest reissueTokenRequest = new ReissueTokenRequest(rawRefreshToken); - final RefreshToken refreshToken = new RefreshToken(new EncryptedToken(rawRefreshToken), LocalDateTime.MIN, - member); + final String refreshToken = "refreshToken"; + final ReissueTokenRequest reissueTokenRequest = new ReissueTokenRequest(refreshToken); given(tokenProvider.isValidToken(any())) .willReturn(true); - given(refreshTokenRepository.findByTokenAndIsRevokedFalse(any())) - .willReturn(Optional.of(refreshToken)); + given(refreshTokenRepository.findMemberIdentifierByRefreshToken(any())) + .willReturn(Optional.of(member.getIdentifier().getValue())); + given(memberRepository.findByIdentifier(any())) + .willReturn(Optional.empty()); //when //then diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/CacheKeyGeneratorTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/CacheKeyGeneratorTest.java new file mode 100644 index 000000000..08fea3baf --- /dev/null +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/CacheKeyGeneratorTest.java @@ -0,0 +1,31 @@ +package co.kirikiri.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.lang.reflect.Method; +import org.junit.jupiter.api.Test; + +class CacheKeyGeneratorTest { + + private final CacheKeyGenerator cacheKeyGenerator = new CacheKeyGenerator(); + + @Test + void 정상적으로_키를_생성한다() throws NoSuchMethodException { + //given + final Class targetClass = Object.class; + final Method method = targetClass.getMethod("toString"); + final Object[] params = new Object[]{"param1", null, 123}; + + //when + final String key = (String) cacheKeyGenerator.generate(targetClass, method, params); + + //then + assertThat(key).contains("Class", "toString"); + for (final Object param : params) { + if (param == null) { + continue; + } + assertThat(key).contains(String.valueOf(param.hashCode())); + } + } +} diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/GoalRoomCreateServiceTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/GoalRoomCreateServiceTest.java index 51ee3cd17..b409f8ddb 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/service/GoalRoomCreateServiceTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/GoalRoomCreateServiceTest.java @@ -14,6 +14,7 @@ import static org.mockito.Mockito.when; import co.kirikiri.domain.ImageContentType; +import co.kirikiri.domain.exception.ImageExtensionException; import co.kirikiri.domain.goalroom.CheckFeed; import co.kirikiri.domain.goalroom.GoalRoom; import co.kirikiri.domain.goalroom.GoalRoomMember; @@ -22,6 +23,7 @@ import co.kirikiri.domain.goalroom.GoalRoomRole; import co.kirikiri.domain.goalroom.GoalRoomToDo; import co.kirikiri.domain.goalroom.GoalRoomToDoCheck; +import co.kirikiri.domain.goalroom.exception.GoalRoomException; import co.kirikiri.domain.goalroom.vo.GoalRoomName; import co.kirikiri.domain.goalroom.vo.GoalRoomTodoContent; import co.kirikiri.domain.goalroom.vo.LimitedMemberCount; @@ -43,8 +45,6 @@ import co.kirikiri.domain.roadmap.RoadmapNodeImages; import co.kirikiri.domain.roadmap.RoadmapNodes; import co.kirikiri.domain.roadmap.RoadmapStatus; -import co.kirikiri.exception.BadRequestException; -import co.kirikiri.exception.NotFoundException; import co.kirikiri.persistence.goalroom.CheckFeedRepository; import co.kirikiri.persistence.goalroom.GoalRoomMemberRepository; import co.kirikiri.persistence.goalroom.GoalRoomRepository; @@ -56,6 +56,9 @@ import co.kirikiri.service.dto.goalroom.request.GoalRoomRoadmapNodeRequest; import co.kirikiri.service.dto.goalroom.request.GoalRoomTodoRequest; import co.kirikiri.service.dto.goalroom.response.GoalRoomToDoCheckResponse; +import co.kirikiri.service.exception.BadRequestException; +import co.kirikiri.service.exception.NotFoundException; +import co.kirikiri.service.goalroom.GoalRoomCreateService; import java.net.MalformedURLException; import java.net.URL; import java.time.LocalDate; @@ -86,7 +89,7 @@ class GoalRoomCreateServiceTest { private static final Member MEMBER = new Member(new Identifier("identifier2"), new EncryptedPassword(new Password("password!2")), new Nickname("name2"), null, - new MemberProfile(Gender.FEMALE, LocalDate.now(), "010-1111-2222")); + new MemberProfile(Gender.FEMALE, "kirikiri@email.com")); private static final Roadmap ROADMAP = new Roadmap("roadmap", "introduction", 30, RoadmapDifficulty.DIFFICULT, MEMBER, new RoadmapCategory("IT")); @@ -132,8 +135,8 @@ static void setUp() { final Password password = new Password("password1!"); final EncryptedPassword encryptedPassword = new EncryptedPassword(password); final Nickname nickname = new Nickname("nickname"); - final String phoneNumber = "010-1234-5678"; - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, TODAY, phoneNumber); + final String email = "kirikiri@email.com"; + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, email); member = new Member(identifier, encryptedPassword, nickname, null, memberProfile); } @@ -141,8 +144,7 @@ static void setUp() { void 정상적으로_골룸을_생성한다() { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); given(roadmapContentRepository.findByIdWithRoadmap(anyLong())) .willReturn(Optional.of(ROADMAP_CONTENT)); @@ -159,8 +161,7 @@ static void setUp() { void 골룸_생성_시_삭제된_로드맵이면_예외를_던진다() { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); given(roadmapContentRepository.findByIdWithRoadmap(anyLong())) .willReturn(Optional.of(DELETED_ROADMAP_CONTENT)); @@ -175,8 +176,7 @@ static void setUp() { void 골룸_생성_시_존재하지_않은_로드맵_컨텐츠가_들어올때_예외를_던진다() { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); given(roadmapContentRepository.findByIdWithRoadmap(anyLong())) .willReturn(Optional.empty()); @@ -194,8 +194,7 @@ static void setUp() { new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER), new GoalRoomRoadmapNodeRequest(2L, 10, TODAY, TEN_DAY_LATER))); final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - wrongSizeGoalRoomRoadmapNodeRequest); + 20, wrongSizeGoalRoomRoadmapNodeRequest); given(roadmapContentRepository.findByIdWithRoadmap(anyLong())) .willReturn(Optional.of(ROADMAP_CONTENT)); @@ -211,7 +210,7 @@ static void setUp() { //given final long wrongRoadmapNodId = 2L; final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(wrongRoadmapNodId, 10, TODAY, TEN_DAY_LATER)))); given(roadmapContentRepository.findByIdWithRoadmap(anyLong())) @@ -227,8 +226,7 @@ static void setUp() { void 골룸_생성_시_존재하지_않은_회원의_Identifier가_들어올때_예외를_던진다() { //given final GoalRoomCreateRequest request = new GoalRoomCreateRequest(1L, "name", - 20, new GoalRoomTodoRequest("content", TODAY, TEN_DAY_LATER), - new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); + 20, new ArrayList<>(List.of(new GoalRoomRoadmapNodeRequest(1L, 10, TODAY, TEN_DAY_LATER)))); given(roadmapContentRepository.findByIdWithRoadmap(anyLong())) .willReturn(Optional.of(ROADMAP_CONTENT)); @@ -244,17 +242,17 @@ static void setUp() { @Test void 골룸에_참가한다() { //given - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "시진이", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "시진이", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); final RoadmapContent targetRoadmapContent = roadmapContents.getValues().get(0); final int limitedMemberCount = 20; final GoalRoom goalRoom = 골룸을_생성한다(1L, creator, targetRoadmapContent, limitedMemberCount); - final Member follower = 사용자를_생성한다(2L, "identifier2", "password1!", "팔로워", "010-1234-5678"); + final Member follower = 사용자를_생성한다(2L, "identifier2", "password1!", "팔로워", "kirikiri1@email"); when(memberRepository.findByIdentifier(any())) .thenReturn(Optional.of(follower)); - when(goalRoomRepository.findById(anyLong())) + when(goalRoomRepository.findGoalRoomByIdWithPessimisticLock(anyLong())) .thenReturn(Optional.of(goalRoom)); //when @@ -280,11 +278,11 @@ static void setUp() { @Test void 골룸_참가_요청시_유효한_골룸_아이디가_아니면_예외가_발생한다() { //given - final Member follower = 사용자를_생성한다(1L, "identifier1", "password1!", "팔로워", "010-1234-5678"); + final Member follower = 사용자를_생성한다(1L, "identifier1", "password1!", "팔로워", "kirikiri1@email"); when(memberRepository.findByIdentifier(any())) .thenReturn(Optional.of(follower)); - when(goalRoomRepository.findById(anyLong())) + when(goalRoomRepository.findGoalRoomByIdWithPessimisticLock(anyLong())) .thenReturn(Optional.empty()); //when, then @@ -296,22 +294,22 @@ static void setUp() { @Test void 골룸_참가_요청시_제한_인원이_가득_찼을_경우_예외가_발생한다() { //given - final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); final RoadmapContent targetRoadmapContent = roadmapContents.getValues().get(0); final int limitedMemberCount = 1; final GoalRoom goalRoom = 골룸을_생성한다(1L, creator, targetRoadmapContent, limitedMemberCount); - final Member follower = 사용자를_생성한다(1L, "identifier2", "password1!", "팔로워", "010-1234-5678"); + final Member follower = 사용자를_생성한다(1L, "identifier2", "password1!", "팔로워", "kirikiri1@email"); when(memberRepository.findByIdentifier(any())) .thenReturn(Optional.of(follower)); - when(goalRoomRepository.findById(anyLong())) + when(goalRoomRepository.findGoalRoomByIdWithPessimisticLock(anyLong())) .thenReturn(Optional.of(goalRoom)); //when, then assertThatThrownBy(() -> goalRoomCreateService.join("identifier2", 1L)) - .isInstanceOf(BadRequestException.class) + .isInstanceOf(GoalRoomException.class) .hasMessage("제한 인원이 꽉 찬 골룸에는 참여할 수 없습니다."); } @@ -320,27 +318,27 @@ static void setUp() { //given final List roadmapNodes = 로드맵_노드들을_생성한다(); final RoadmapContent roadmapContent = 로드맵_본문을_생성한다(roadmapNodes); - final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "010-1111-1111"); + final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "kirikiri1@email"); final int limitedMemberCount = 20; final GoalRoom goalRoom = 골룸을_생성한다(1L, creator, roadmapContent, limitedMemberCount); - final Member follower = 사용자를_생성한다(2L, "identifier2", "password2!", "팔로워", "010-1111-2222"); + final Member follower = 사용자를_생성한다(2L, "identifier2", "password2!", "팔로워", "kirikiri1@email"); goalRoom.start(); when(memberRepository.findByIdentifier(any())) .thenReturn(Optional.of(follower)); - when(goalRoomRepository.findById(anyLong())) + when(goalRoomRepository.findGoalRoomByIdWithPessimisticLock(anyLong())) .thenReturn(Optional.of(goalRoom)); //when, then assertThatThrownBy(() -> goalRoomCreateService.join("identifier2", 1L)) - .isInstanceOf(BadRequestException.class) + .isInstanceOf(GoalRoomException.class) .hasMessage("모집 중이지 않은 골룸에는 참여할 수 없습니다."); } @Test void 정상적으로_골룸에_투두리스트를_추가한다() { //given - final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); final RoadmapContent targetRoadmapContent = roadmapContents.getValues().get(0); @@ -381,7 +379,7 @@ static void setUp() { @Test void 골룸에_투두리스트_추가시_골룸을_찾지_못할_경우_예외를_던진다() { //given - final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); final RoadmapContent targetRoadmapContent = roadmapContents.getValues().get(0); @@ -408,7 +406,7 @@ static void setUp() { @Test void 골룸에_투두리스트_추가시_종료된_골룸일_경우_예외를_던진다() { //given - final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); final RoadmapContent targetRoadmapContent = roadmapContents.getValues().get(0); @@ -436,7 +434,7 @@ static void setUp() { @Test void 골룸에_투두리스트_추가시_리더가_아닐_경우_예외를_던진다() { //given - final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); final RoadmapContent targetRoadmapContent = roadmapContents.getValues().get(0); @@ -463,7 +461,7 @@ static void setUp() { @Test void 골룸에_투두리스트_추가시_골룸_컨텐츠가_250글자가_넘을때_예외를_던진다() { //given - final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "identifier1", "password1!", "시진이", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); final RoadmapContent targetRoadmapContent = roadmapContents.getValues().get(0); @@ -485,13 +483,13 @@ static void setUp() { //when //then assertThatThrownBy(() -> goalRoomCreateService.addGoalRoomTodo(1L, "identifier1", goalRoomTodoRequest)) - .isInstanceOf(BadRequestException.class); + .isInstanceOf(GoalRoomException.class); } @Test void 골룸을_시작한다() { // given - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); @@ -524,7 +522,7 @@ static void setUp() { @Test void 골룸_시작시_존재하지_않는_골룸이면_예외가_발생한다() { // given - final Member member = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member member = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); when(memberRepository.findByIdentifier(any())) .thenReturn(Optional.of(member)); @@ -539,8 +537,8 @@ static void setUp() { @Test void 골룸을_시작하는_사용자가_골룸의_리더가_아니면_예외가_발생한다() { // given - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); - final Member follower = 사용자를_생성한다(2L, "kirikirico", "password2!", "끼리코", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); + final Member follower = 사용자를_생성한다(2L, "kirikirico", "password2!", "끼리코", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); @@ -560,7 +558,7 @@ static void setUp() { @Test void 골룸_시작시_시작날짜가_아직_지나지_않았으면_예외가_발생한다() { // given - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); @@ -582,7 +580,7 @@ static void setUp() { // given final CheckFeedRequest request = 인증_피드_요청_DTO를_생성한다("image/jpeg"); - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); @@ -624,7 +622,7 @@ static void setUp() { // given final CheckFeedRequest request = 인증_피드_요청_DTO를_생성한다("image/jpeg"); - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); @@ -651,7 +649,7 @@ static void setUp() { // given final CheckFeedRequest request = 인증_피드_요청_DTO를_생성한다("image/jpeg"); - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); @@ -682,7 +680,7 @@ static void setUp() { // given final CheckFeedRequest request = 인증_피드_요청_DTO를_생성한다("image/jpeg"); - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); @@ -712,7 +710,7 @@ static void setUp() { // given final CheckFeedRequest request = 인증_피드_요청_DTO를_생성한다("image/gif"); - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); @@ -731,7 +729,7 @@ static void setUp() { // when assertThatThrownBy( () -> goalRoomCreateService.createCheckFeed("identifier", 1L, request)) - .isInstanceOf(BadRequestException.class) + .isInstanceOf(ImageExtensionException.class) .hasMessage("허용되지 않는 확장자입니다."); } @@ -740,7 +738,7 @@ static void setUp() { // given final CheckFeedRequest request = 인증_피드_요청_DTO를_생성한다("image/jpeg"); - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); final RoadmapContent targetRoadmapContent = roadmapContents.getValues().get(0); @@ -764,7 +762,7 @@ static void setUp() { // given final CheckFeedRequest request = 인증_피드_요청_DTO를_생성한다("image/jpeg"); - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); final RoadmapContent targetRoadmapContent = roadmapContents.getValues().get(0); @@ -789,7 +787,7 @@ static void setUp() { @Test void 투두리스트를_체크한다() { // given - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); @@ -821,7 +819,7 @@ static void setUp() { @Test void 투두리스트_체크시_체크_이력이_있으면_제거한다() { // given - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); @@ -867,7 +865,7 @@ static void setUp() { @Test void 투두리스트_체크시_해당_투두가_존재하지_않으면_예외가_발생한다() { // given - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); @@ -888,7 +886,7 @@ static void setUp() { @Test void 투두리스트_체크시_골룸에_사용자가_없으면_예외가_발생한다() { // given - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri1@email"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); @@ -990,11 +988,10 @@ static void setUp() { } private Member 사용자를_생성한다(final Long memberId, final String identifier, final String password, final String nickname, - final String phoneNumber) { - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, - LocalDate.of(1995, 9, 30), phoneNumber); + final String email) { + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, email); - return new Member(memberId, new Identifier(identifier), new EncryptedPassword(new Password(password)), + return new Member(memberId, new Identifier(identifier), null, new EncryptedPassword(new Password(password)), new Nickname(nickname), null, memberProfile); } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/GoalRoomReadServiceTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/GoalRoomReadServiceTest.java index aa4156b29..cf1452150 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/service/GoalRoomReadServiceTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/GoalRoomReadServiceTest.java @@ -41,8 +41,6 @@ import co.kirikiri.domain.roadmap.RoadmapNodeImage; import co.kirikiri.domain.roadmap.RoadmapNodeImages; import co.kirikiri.domain.roadmap.RoadmapNodes; -import co.kirikiri.exception.ForbiddenException; -import co.kirikiri.exception.NotFoundException; import co.kirikiri.persistence.goalroom.CheckFeedRepository; import co.kirikiri.persistence.goalroom.GoalRoomMemberRepository; import co.kirikiri.persistence.goalroom.GoalRoomPendingMemberRepository; @@ -56,6 +54,7 @@ import co.kirikiri.service.dto.goalroom.response.GoalRoomCheckFeedResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomMemberResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomResponse; +import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodeDetailResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodeResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomRoadmapNodesResponse; import co.kirikiri.service.dto.goalroom.response.GoalRoomToDoCheckResponse; @@ -63,6 +62,9 @@ import co.kirikiri.service.dto.member.response.MemberGoalRoomForListResponse; import co.kirikiri.service.dto.member.response.MemberGoalRoomResponse; import co.kirikiri.service.dto.member.response.MemberResponse; +import co.kirikiri.service.exception.ForbiddenException; +import co.kirikiri.service.exception.NotFoundException; +import co.kirikiri.service.goalroom.GoalRoomReadService; import java.net.MalformedURLException; import java.net.URL; import java.time.LocalDate; @@ -926,7 +928,7 @@ THIRTY_DAY_LATER, new MemberResponse(creator.getId(), creator.getNickname().getV } @Test - void 골룸의_전체_노드를_조회한다() { + void 골룸의_전체_노드를_조회한다() throws MalformedURLException { // given final Member creator = 사용자를_생성한다(1L); final Roadmap roadmap = 로드맵을_생성한다(creator); @@ -938,12 +940,18 @@ THIRTY_DAY_LATER, new MemberResponse(creator.getId(), creator.getNickname().getV .thenReturn(Optional.of(goalRoomMember)); when(goalRoomRepository.findByIdWithNodes(1L)) .thenReturn(Optional.of(goalRoom)); + given(fileService.generateUrl(anyString(), any())) + .willReturn(new URL("http://example.com/serverFilePath")); // when - final List responses = goalRoomReadService.findAllGoalRoomNodes(1L, "identifier"); - final List expected = List.of( - new GoalRoomRoadmapNodeResponse(1L, "로드맵 1주차", TODAY, TEN_DAY_LATER, 10), - new GoalRoomRoadmapNodeResponse(2L, "로드맵 2주차", TWENTY_DAY_LAYER, THIRTY_DAY_LATER, 2) + final List responses = goalRoomReadService.findAllGoalRoomNodes(1L, + "identifier"); + final List expected = List.of( + new GoalRoomRoadmapNodeDetailResponse(1L, "로드맵 1주차", "로드맵 1주차 내용", + List.of("http://example.com/serverFilePath", "http://example.com/serverFilePath"), TODAY, + TEN_DAY_LATER, 10), + new GoalRoomRoadmapNodeDetailResponse(2L, "로드맵 2주차", "로드맵 2주차 내용", + Collections.emptyList(), TWENTY_DAY_LAYER, THIRTY_DAY_LATER, 2) ); // then @@ -1177,17 +1185,16 @@ THIRTY_DAY_LATER, new MemberResponse(creator.getId(), creator.getNickname().getV private Member 크리에이터를_생성한다() { final MemberImage memberImage = new MemberImage("originalFileName", "default-member-image", ImageContentType.JPG); - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, LocalDate.of(1990, 1, 1), "010-1234-5678"); - return new Member(1L, new Identifier("cokirikiri"), new EncryptedPassword(new Password("password1!")), + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, "kirikiri@email.com"); + return new Member(1L, new Identifier("cokirikiri"), null, new EncryptedPassword(new Password("password1!")), new Nickname("코끼리"), memberImage, memberProfile); } private Member 사용자를_생성한다(final Long id) { return new Member(id, new Identifier("identifier1"), - new EncryptedPassword(new Password("password1")), new Nickname("name1"), + null, new EncryptedPassword(new Password("password1")), new Nickname("name1"), new MemberImage("originalFileName", "serverFilePath", ImageContentType.JPEG), - new MemberProfile(Gender.FEMALE, LocalDate.of(2000, 7, 20), - "010-1111-1111")); + new MemberProfile(Gender.FEMALE, "kirikiri@email.com")); } private Roadmap 로드맵을_생성한다(final Member creator) { diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/GoalRoomSchedulerTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/GoalRoomSchedulerTest.java index 9b248316c..f4118210d 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/service/GoalRoomSchedulerTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/GoalRoomSchedulerTest.java @@ -4,9 +4,8 @@ import static co.kirikiri.domain.goalroom.GoalRoomStatus.RUNNING; 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.ArgumentMatchers.anyList; -import static org.mockito.Mockito.times; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -38,6 +37,7 @@ import co.kirikiri.persistence.goalroom.GoalRoomMemberRepository; import co.kirikiri.persistence.goalroom.GoalRoomPendingMemberRepository; import co.kirikiri.persistence.goalroom.GoalRoomRepository; +import co.kirikiri.service.scheduler.GoalRoomScheduler; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Collections; @@ -49,7 +49,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -public class GoalRoomSchedulerTest { +class GoalRoomSchedulerTest { private static final LocalDate TODAY = LocalDate.now(); private static final LocalDate TEN_DAY_LATER = TODAY.plusDays(10); @@ -58,11 +58,11 @@ public class GoalRoomSchedulerTest { @Mock private GoalRoomRepository goalRoomRepository; - @Mock - private GoalRoomMemberRepository goalRoomMemberRepository; - @Mock private GoalRoomPendingMemberRepository goalRoomPendingMemberRepository; + + @Mock + private GoalRoomMemberRepository goalRoomMemberRepository; @InjectMocks private GoalRoomScheduler goalRoomScheduler; @@ -78,19 +78,19 @@ public class GoalRoomSchedulerTest { final GoalRoom goalRoom1 = 골룸을_생성한다(1L, creator, targetRoadmapContent, 10); final GoalRoom goalRoom2 = 골룸을_생성한다(2L, creator, targetRoadmapContent, 10); - final Member follower1 = 사용자를_생성한다(2L, "identifier1", "password2!", "name1", "010-1111-1111"); - final Member follower2 = 사용자를_생성한다(3L, "identifier2", "password3!", "name2", "010-1111-1112"); - final Member follower3 = 사용자를_생성한다(4L, "identifier3", "password4!", "name3", "010-1111-1113"); + final Member follower1 = 사용자를_생성한다(2L, "identifier1", "password2!", "name1", "kirikiri@email.com"); + final Member follower2 = 사용자를_생성한다(3L, "identifier2", "password3!", "name2", "kirikiri@email.com"); + final Member follower3 = 사용자를_생성한다(4L, "identifier3", "password4!", "name3", "kirikiri@email.com"); - final GoalRoomPendingMember goalRoomPendingMember = 골룸_대기자를_생성한다(goalRoom2, creator, GoalRoomRole.FOLLOWER); - final GoalRoomPendingMember goalRoomPendingMember1 = 골룸_대기자를_생성한다(goalRoom1, follower1, GoalRoomRole.FOLLOWER); - final GoalRoomPendingMember goalRoomPendingMember2 = 골룸_대기자를_생성한다(goalRoom1, follower2, GoalRoomRole.FOLLOWER); + 골룸_대기자를_생성한다(goalRoom2, creator, GoalRoomRole.FOLLOWER); + 골룸_대기자를_생성한다(goalRoom1, follower1, GoalRoomRole.FOLLOWER); + 골룸_대기자를_생성한다(goalRoom1, follower2, GoalRoomRole.FOLLOWER); goalRoom1.join(follower1); goalRoom1.join(follower2); goalRoom2.join(follower3); - when(goalRoomRepository.findAllByStartDate(LocalDate.now())) + when(goalRoomRepository.findAllRecruitingGoalRoomsByStartDateEarlierThan(LocalDate.now())) .thenReturn(List.of(goalRoom1)); // when @@ -106,7 +106,7 @@ public class GoalRoomSchedulerTest { @Test void 골룸의_시작날짜가_아직_지나지_않았다면_골룸의_상태가_변경되지_않는다() { // given - final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "010-1234-5678"); + final Member creator = 사용자를_생성한다(1L, "cokirikiri", "password1!", "코끼리", "kirikiri@email.com"); final Roadmap roadmap = 로드맵을_생성한다(creator); final RoadmapContents roadmapContents = roadmap.getContents(); @@ -114,24 +114,22 @@ public class GoalRoomSchedulerTest { final GoalRoom goalRoom1 = 골룸을_생성한다(1L, creator, targetRoadmapContent, 10); final GoalRoom goalRoom2 = 골룸을_생성한다(2L, creator, targetRoadmapContent, 10); - final Member follower1 = 사용자를_생성한다(2L, "identifier1", "password2!", "name1", "010-1111-1111"); - final Member follower2 = 사용자를_생성한다(3L, "identifier2", "password3!", "name2", "010-1111-1112"); - final Member follower3 = 사용자를_생성한다(4L, "identifier3", "password4!", "name3", "010-1111-1113"); + final Member follower1 = 사용자를_생성한다(2L, "identifier1", "password2!", "name1", "kirikiri@email.com"); + final Member follower2 = 사용자를_생성한다(3L, "identifier2", "password3!", "name2", "kirikiri@email.com"); + final Member follower3 = 사용자를_생성한다(4L, "identifier3", "password4!", "name3", "kirikiri@email.com"); goalRoom1.join(follower1); goalRoom1.join(follower2); goalRoom2.join(follower3); - when(goalRoomRepository.findAllByStartDate(LocalDate.now())) + when(goalRoomRepository.findAllRecruitingGoalRoomsByStartDateEarlierThan(LocalDate.now())) .thenReturn(Collections.emptyList()); // when goalRoomScheduler.startGoalRooms(); // then - verify(goalRoomPendingMemberRepository, times(0)).findAllByGoalRoom(any()); - verify(goalRoomMemberRepository, times(0)).saveAll(anyList()); - verify(goalRoomPendingMemberRepository, times(0)).deleteAll(anyList()); + verify(goalRoomPendingMemberRepository, never()).deleteAllByIdIn(anyList()); assertAll( () -> assertThat(goalRoom1.getStatus()).isEqualTo(RECRUITING), @@ -140,11 +138,10 @@ public class GoalRoomSchedulerTest { } private Member 사용자를_생성한다(final Long memberId, final String identifier, final String password, final String nickname, - final String phoneNumber) { - final MemberProfile memberProfile = new MemberProfile(Gender.MALE, - LocalDate.of(1995, 9, 30), phoneNumber); + final String email) { + final MemberProfile memberProfile = new MemberProfile(Gender.MALE, email); - return new Member(memberId, new Identifier(identifier), new EncryptedPassword(new Password(password)), + return new Member(memberId, new Identifier(identifier), null, new EncryptedPassword(new Password(password)), new Nickname(nickname), null, memberProfile); } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/JwtTokenProviderTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/JwtTokenProviderTest.java index 3bc56307a..ec35509ae 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/service/JwtTokenProviderTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/JwtTokenProviderTest.java @@ -4,10 +4,13 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import co.kirikiri.exception.AuthenticationException; +import co.kirikiri.service.auth.JwtTokenProvider; +import co.kirikiri.service.auth.TokenProvider; +import co.kirikiri.service.exception.AuthenticationException; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.security.Keys; +import java.time.LocalDateTime; import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.Test; @@ -45,10 +48,10 @@ class JwtTokenProviderTest { final Map claims = new HashMap<>(Map.of("test1", "test1", "test2", "test2")); //when - final String accessToken = tokenProvider.createRefreshToken(subject, claims); + final String refreshToken = tokenProvider.createRefreshToken(subject, claims); //then - final Claims result = getClaims(accessToken); + final Claims result = getClaims(refreshToken); assertThat(result.getSubject()).isEqualTo(subject); // subject 확인 for (final String claimKey : claims.keySet()) { // custom claim 확인 @@ -122,4 +125,18 @@ private Claims getClaims(final String accessToken) { //then assertThat(result).isEqualTo(subject); } + + @Test + void 토큰의_만료기간을_가져온다() { + //given + final String subject = "subject"; + final Map claims = new HashMap<>(Map.of("test1", "test1", "test2", "test2")); + final String refreshToken = tokenProvider.createRefreshToken(subject, claims); + + //when + final LocalDateTime tokenExpiredAt = tokenProvider.findTokenExpiredAt(refreshToken); + + //then + assertThat(tokenExpiredAt).isAfter(LocalDateTime.now()); + } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/MemberServiceTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/MemberServiceTest.java index 04a252fe4..30d66dc46 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/service/MemberServiceTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/MemberServiceTest.java @@ -15,19 +15,25 @@ import co.kirikiri.domain.member.vo.Identifier; import co.kirikiri.domain.member.vo.Nickname; import co.kirikiri.domain.member.vo.Password; -import co.kirikiri.exception.ConflictException; -import co.kirikiri.exception.NotFoundException; +import co.kirikiri.persistence.auth.RefreshTokenRepository; import co.kirikiri.persistence.member.MemberRepository; +import co.kirikiri.service.auth.TokenProvider; +import co.kirikiri.service.dto.auth.response.AuthenticationResponse; +import co.kirikiri.service.dto.member.OauthMemberJoinDto; import co.kirikiri.service.dto.member.request.GenderType; import co.kirikiri.service.dto.member.request.MemberJoinRequest; import co.kirikiri.service.dto.member.response.MemberInformationForPublicResponse; import co.kirikiri.service.dto.member.response.MemberInformationResponse; +import co.kirikiri.service.exception.ConflictException; +import co.kirikiri.service.exception.NotFoundException; +import co.kirikiri.service.member.MemberService; import java.net.MalformedURLException; import java.net.URL; -import java.time.LocalDate; import java.util.Optional; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -49,6 +55,12 @@ class MemberServiceTest { @Mock private NumberGenerator numberGenerator; + @Mock + private TokenProvider tokenProvider; + + @Mock + private RefreshTokenRepository refreshTokenRepository; + @Mock private FileService fileService; @@ -59,12 +71,12 @@ class MemberServiceTest { void 회원가입을_한다() { //given final MemberJoinRequest request = new MemberJoinRequest("identifier1", "password1!", "nickname", - "010-1234-5678", GenderType.MALE, LocalDate.now()); + GenderType.MALE, "kirikiri@email.com"); given(memberRepository.findByIdentifier(any())) .willReturn(Optional.empty()); given(memberRepository.save(any())) - .willReturn(new Member(1L, null, null, null, null, null)); + .willReturn(new Member(1L, null, null, null, null, null, null)); given(environment.getProperty(IMAGE_DEFAULT_ORIGINAL_FILE_NAME_PROPERTY)) .willReturn("default-member-image"); given(environment.getProperty(IMAGE_DEFAULT_SERVER_FILE_PATH_PROPERTY)) @@ -84,14 +96,14 @@ class MemberServiceTest { void 회원가입_시_이미_존재하는_아이디가_존재할때_예외를_던진다() { //given final MemberJoinRequest request = new MemberJoinRequest("identifier1", "password1!", "nickname", - "010-1234-5678", GenderType.MALE, LocalDate.now()); + GenderType.MALE, "kirikiri@email.com"); final Identifier identifier = new Identifier("identifier1"); final Password password = new Password("password1!"); final Nickname nickname = new Nickname("nickname"); final String phoneNumber = "010-1234-5678"; final Member member = new Member(identifier, new EncryptedPassword(password), nickname, null, - new MemberProfile(Gender.MALE, LocalDate.now(), phoneNumber)); + new MemberProfile(Gender.MALE, "kirikiri@email.com")); given(memberRepository.findByIdentifier(any())) .willReturn(Optional.of(member)); @@ -101,31 +113,15 @@ class MemberServiceTest { .isInstanceOf(ConflictException.class); } - @Test - void 회원가입_시_이미_존재하는_닉네임_존재할때_예외를_던진다() { - //given - final MemberJoinRequest request = new MemberJoinRequest("identifier1", "password1!", "nickname", - "010-1234-5678", GenderType.MALE, LocalDate.now()); - - given(memberRepository.findByNickname(any())) - .willReturn(Optional.of(new Member(null, null, null, null, null, null))); - - //when - //then - assertThatThrownBy(() -> memberService.join(request)) - .isInstanceOf(ConflictException.class); - } - @Test void 로그인한_사용자_자신의_정보를_조회한다() throws MalformedURLException { // given final Identifier identifier = new Identifier("identifier1"); final Password password = new Password("password1!"); final Nickname nickname = new Nickname("nickname"); - final String phoneNumber = "010-1234-5678"; final MemberImage memberImage = new MemberImage("originalFileName", "serverFilePath", ImageContentType.PNG); - final Member member = new Member(1L, identifier, new EncryptedPassword(password), nickname, memberImage, - new MemberProfile(Gender.MALE, LocalDate.now(), phoneNumber)); + final Member member = new Member(1L, identifier, null, new EncryptedPassword(password), nickname, memberImage, + new MemberProfile(Gender.MALE, "kirikiri@email.com")); given(memberRepository.findWithMemberProfileAndImageByIdentifier(any())) .willReturn(Optional.of(member)); @@ -139,7 +135,7 @@ class MemberServiceTest { final MemberInformationResponse expected = new MemberInformationResponse(1L, "nickname", "http://example.com/serverFilePath", Gender.MALE.name(), - "identifier1", "010-1234-5678", LocalDate.now()); + "identifier1", "kirikiri@email.com"); assertThat(response).isEqualTo(expected); } @@ -168,7 +164,7 @@ class MemberServiceTest { final String phoneNumber = "010-1234-5678"; final MemberImage memberImage = new MemberImage("originalFileName", "serverFilePath", ImageContentType.PNG); final Member member = new Member(identifier, new EncryptedPassword(password), nickname, memberImage, - new MemberProfile(Gender.MALE, LocalDate.now(), phoneNumber)); + new MemberProfile(Gender.MALE, "kirikiri@email.com")); given(memberRepository.findWithMemberProfileAndImageById(any())) .willReturn(Optional.of(member)); @@ -205,7 +201,7 @@ class MemberServiceTest { final String phoneNumber = "010-1234-5678"; final MemberImage memberImage = new MemberImage("originalFileName", "serverFilePath", ImageContentType.PNG); final Member member = new Member(identifier, new EncryptedPassword(password), nickname, memberImage, - new MemberProfile(Gender.MALE, LocalDate.now(), phoneNumber)); + new MemberProfile(Gender.MALE, "kirikiri@email.com")); given(memberRepository.findWithMemberProfileAndImageById(any())) .willReturn(Optional.empty()); @@ -216,4 +212,90 @@ class MemberServiceTest { .isInstanceOf(NotFoundException.class) .hasMessageContaining("존재하지 않는 회원입니다. memberId = 1"); } + + @Test + void oauth_회원가입을_한다() { + //given + final OauthMemberJoinDto request = new OauthMemberJoinDto("oauthId", "kirikiri@email.com", "nickname", + GenderType.UNDEFINED); + + given(memberRepository.save(any())) + .willReturn(new Member(1L, null, null, null, null, null, null)); + given(environment.getProperty(IMAGE_DEFAULT_ORIGINAL_FILE_NAME_PROPERTY)) + .willReturn("default-member-image"); + given(environment.getProperty(IMAGE_DEFAULT_SERVER_FILE_PATH_PROPERTY)) + .willReturn("https://blog.kakaocdn.net/dn/GHYFr/btrsSwcSDQV/UQZxkayGyAXrPACyf0MaV1/img.jpg"); + given(environment.getProperty(IMAGE_DEFAULT_IMAGE_CONTENT_TYPE_PROPERTY)) + .willReturn("JPG"); + given(numberGenerator.generate()) + .willReturn(7); + given(tokenProvider.createRefreshToken(any(), any())) + .willReturn("refreshToken"); + given(tokenProvider.createAccessToken(any(), any())) + .willReturn("accessToken"); + + //when + final AuthenticationResponse result = memberService.oauthJoin(request); + + //then + assertThat(result).isEqualTo(new AuthenticationResponse("refreshToken", "accessToken")); + } + + @ParameterizedTest + @ValueSource(strings = {"k", "kk", "kkk", "kkkk"}) + void oauth_회원가입_시_이메일의_아이디와_UUID_길이의_합이_40이하일때_회원을_생성한다(final String value) { + //given + final OauthMemberJoinDto request = new OauthMemberJoinDto("oauthId", value + "@email.com", "nickname", + GenderType.UNDEFINED); + + given(memberRepository.save(any())) + .willReturn(new Member(1L, null, null, null, null, null, null)); + given(environment.getProperty(IMAGE_DEFAULT_ORIGINAL_FILE_NAME_PROPERTY)) + .willReturn("default-member-image"); + given(environment.getProperty(IMAGE_DEFAULT_SERVER_FILE_PATH_PROPERTY)) + .willReturn("https://blog.kakaocdn.net/dn/GHYFr/btrsSwcSDQV/UQZxkayGyAXrPACyf0MaV1/img.jpg"); + given(environment.getProperty(IMAGE_DEFAULT_IMAGE_CONTENT_TYPE_PROPERTY)) + .willReturn("JPG"); + given(numberGenerator.generate()) + .willReturn(7); + given(tokenProvider.createRefreshToken(any(), any())) + .willReturn("refreshToken"); + given(tokenProvider.createAccessToken(any(), any())) + .willReturn("accessToken"); + + //when + final AuthenticationResponse result = memberService.oauthJoin(request); + + //then + assertThat(result).isEqualTo(new AuthenticationResponse("refreshToken", "accessToken")); + } + + @ParameterizedTest + @ValueSource(strings = {"kkkkk", "kkkkkk", "kkkkkkkkkkkkkkkkk"}) + void oauth_회원가입_시_이메일의_아이디와_UUID_길이의_합이_40초과일때_회원을_생성한다(final String value) { + //given + final OauthMemberJoinDto request = new OauthMemberJoinDto("oauthId", value + "@email.com", "nickname", + GenderType.UNDEFINED); + + given(memberRepository.save(any())) + .willReturn(new Member(1L, null, null, null, null, null, null)); + given(environment.getProperty(IMAGE_DEFAULT_ORIGINAL_FILE_NAME_PROPERTY)) + .willReturn("default-member-image"); + given(environment.getProperty(IMAGE_DEFAULT_SERVER_FILE_PATH_PROPERTY)) + .willReturn("https://blog.kakaocdn.net/dn/GHYFr/btrsSwcSDQV/UQZxkayGyAXrPACyf0MaV1/img.jpg"); + given(environment.getProperty(IMAGE_DEFAULT_IMAGE_CONTENT_TYPE_PROPERTY)) + .willReturn("JPG"); + given(numberGenerator.generate()) + .willReturn(7); + given(tokenProvider.createRefreshToken(any(), any())) + .willReturn("refreshToken"); + given(tokenProvider.createAccessToken(any(), any())) + .willReturn("accessToken"); + + //when + final AuthenticationResponse result = memberService.oauthJoin(request); + + //then + assertThat(result).isEqualTo(new AuthenticationResponse("refreshToken", "accessToken")); + } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/NaverOauthServiceTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/NaverOauthServiceTest.java new file mode 100644 index 000000000..2b0a06491 --- /dev/null +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/NaverOauthServiceTest.java @@ -0,0 +1,125 @@ +package co.kirikiri.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +import co.kirikiri.domain.member.Member; +import co.kirikiri.persistence.member.MemberRepository; +import co.kirikiri.service.auth.AuthService; +import co.kirikiri.service.auth.NaverOauthService; +import co.kirikiri.service.dto.auth.NaverMemberProfileDto; +import co.kirikiri.service.dto.auth.NaverMemberProfileResponseDto; +import co.kirikiri.service.dto.auth.NaverOauthTokenDto; +import co.kirikiri.service.dto.auth.OauthRedirectResponse; +import co.kirikiri.service.dto.auth.response.AuthenticationResponse; +import co.kirikiri.service.member.MemberService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import java.util.Map; +import java.util.Optional; + +@ExtendWith(MockitoExtension.class) +class NaverOauthServiceTest { + + private static final String OAUTH_NAVER_REDIRECT_URL_PROPERTY = "oauth.naver.redirect-url"; + private static final String OAUTH_NAVER_CALLBACK_URL_PROPERTY = "oauth.naver.callback-url"; + private static final String OAUTH_NAVER_CLIENT_ID_PROPERTY = "oauth.naver.client-id"; + + @Mock + private MemberRepository memberRepository; + + @Mock + private MemberService memberService; + + @Mock + private AuthService authService; + + @Mock + private OauthNetworkService oauthNetworkService; + + @Mock + private Environment environment; + + @InjectMocks + private NaverOauthService naverOauthService; + + @Test + void 정상적으로_Oauth_url을_생성한다() { + //given + when(environment.getProperty(OAUTH_NAVER_REDIRECT_URL_PROPERTY)) + .thenReturn("https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=%s&redirect_uri=%s&state=%s"); + when(environment.getProperty(OAUTH_NAVER_CLIENT_ID_PROPERTY)) + .thenReturn("clientId"); + when(environment.getProperty(OAUTH_NAVER_CALLBACK_URL_PROPERTY)) + .thenReturn("http://localhost:8080/api/auth/oauth/login/callback"); + + //when + final OauthRedirectResponse result = naverOauthService.makeOauthUrl(); + + //then + assertThat(result.url()).contains("https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=clientId&redirect_uri=http://localhost:8080/api/auth/oauth/login/callback&state="); + } + + @Test + void oauth로_회원가입_했던_회원의_경우_정상적으로_naver_oauth_로그인을_한다() { + //given + final Map queryParams = Map.of("state", "state", "code", "code"); + final NaverOauthTokenDto naverOauthTokenDto = new NaverOauthTokenDto("accessToken", "refreshToken", "tokenType", 1000); + when(oauthNetworkService.requestToken(NaverOauthTokenDto.class, queryParams)) + .thenReturn(ResponseEntity.ok(naverOauthTokenDto)); + + final NaverMemberProfileResponseDto naverMemberProfileResponseDto = new NaverMemberProfileResponseDto("id", "email", "nickname", "M"); + final NaverMemberProfileDto naverMemberProfileDto = new NaverMemberProfileDto("resultCode", "message", naverMemberProfileResponseDto); + when(oauthNetworkService.requestMemberInfo(NaverMemberProfileDto.class, Map.of(HttpHeaders.AUTHORIZATION, "Bearer accessToken"))) + .thenReturn(ResponseEntity.ok(naverMemberProfileDto)); + + final Member member = new Member(1L, null, null, null, null, null, null); + when(memberRepository.findByOauthId(anyString())) + .thenReturn(Optional.of(member)); + + final AuthenticationResponse authenticationResponse = new AuthenticationResponse("refreshToken", "accessToken"); + when(authService.oauthLogin(member)) + .thenReturn(authenticationResponse); + + //when + final AuthenticationResponse result = naverOauthService.login(queryParams); + + //then + assertThat(result).isEqualTo(authenticationResponse); + } + + @Test + void oauth로_회원가입을_하지않은_회원의_경무_naver_oauth_회원가입을_한다() { + //given + final Map queryParams = Map.of("state", "state", "code", "code"); + final NaverOauthTokenDto naverOauthTokenDto = new NaverOauthTokenDto("accessToken", "refreshToken", "tokenType", 1000); + when(oauthNetworkService.requestToken(NaverOauthTokenDto.class, queryParams)) + .thenReturn(ResponseEntity.ok(naverOauthTokenDto)); + + final NaverMemberProfileResponseDto naverMemberProfileResponseDto = new NaverMemberProfileResponseDto("id", "email", "nickname", "M"); + final NaverMemberProfileDto naverMemberProfileDto = new NaverMemberProfileDto("resultCode", "message", naverMemberProfileResponseDto); + when(oauthNetworkService.requestMemberInfo(NaverMemberProfileDto.class, Map.of(HttpHeaders.AUTHORIZATION, "Bearer accessToken"))) + .thenReturn(ResponseEntity.ok(naverMemberProfileDto)); + + when(memberRepository.findByOauthId(anyString())) + .thenReturn(Optional.empty()); + + final AuthenticationResponse authenticationResponse = new AuthenticationResponse("refreshToken", "accessToken"); + when(memberService.oauthJoin(any())) + .thenReturn(authenticationResponse); + + //when + final AuthenticationResponse result = naverOauthService.login(queryParams); + + //then + assertThat(result).isEqualTo(authenticationResponse); + } +} diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapCreateEventListenerTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapCreateEventListenerTest.java index c14d0781e..e2ce4b915 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapCreateEventListenerTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapCreateEventListenerTest.java @@ -17,8 +17,6 @@ import co.kirikiri.domain.roadmap.RoadmapDifficulty; import co.kirikiri.domain.roadmap.RoadmapNode; import co.kirikiri.domain.roadmap.RoadmapNodes; -import co.kirikiri.exception.BadRequestException; -import co.kirikiri.exception.ServerException; import co.kirikiri.persistence.roadmap.RoadmapContentRepository; import co.kirikiri.service.dto.FileInformation; import co.kirikiri.service.dto.roadmap.RoadmapNodeSaveDto; @@ -26,6 +24,11 @@ import co.kirikiri.service.dto.roadmap.RoadmapTagSaveDto; import co.kirikiri.service.dto.roadmap.request.RoadmapDifficultyType; import co.kirikiri.service.event.RoadmapCreateEvent; +import co.kirikiri.service.exception.BadRequestException; +import co.kirikiri.service.exception.ServerException; +import co.kirikiri.service.roadmap.RoadmapCreateEventListener; +import java.io.IOException; +import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -33,16 +36,13 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.mock.web.MockMultipartFile; import org.springframework.web.multipart.MultipartFile; -import java.io.IOException; -import java.time.LocalDate; -import java.util.List; @ExtendWith(MockitoExtension.class) class RoadmapCreateEventListenerTest { private static final Member member = new Member(1L, new Identifier("identifier1"), - new EncryptedPassword(new Password("password1!")), new Nickname("닉네임"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(1999, 6, 8), "010-1234-5678")); + null, new EncryptedPassword(new Password("password1!")), new Nickname("닉네임"), null, + new MemberProfile(Gender.FEMALE, "kirikiri@email.com")); @Mock private RoadmapContentRepository roadmapContentRepository; diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapCreateServiceTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapCreateServiceTest.java index 9908c1e0c..f0c78c42e 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapCreateServiceTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapCreateServiceTest.java @@ -30,22 +30,24 @@ import co.kirikiri.domain.roadmap.RoadmapContents; import co.kirikiri.domain.roadmap.RoadmapDifficulty; import co.kirikiri.domain.roadmap.RoadmapReview; -import co.kirikiri.exception.AuthenticationException; -import co.kirikiri.exception.BadRequestException; -import co.kirikiri.exception.ForbiddenException; -import co.kirikiri.exception.NotFoundException; import co.kirikiri.persistence.goalroom.GoalRoomMemberRepository; import co.kirikiri.persistence.goalroom.GoalRoomRepository; import co.kirikiri.persistence.member.MemberRepository; import co.kirikiri.persistence.roadmap.RoadmapCategoryRepository; import co.kirikiri.persistence.roadmap.RoadmapRepository; import co.kirikiri.persistence.roadmap.RoadmapReviewRepository; +import co.kirikiri.service.dto.roadmap.request.RoadmapCategorySaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapDifficultyType; import co.kirikiri.service.dto.roadmap.request.RoadmapNodeSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapReviewSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapSaveRequest; import co.kirikiri.service.dto.roadmap.request.RoadmapTagSaveRequest; -import java.time.LocalDate; +import co.kirikiri.service.exception.AuthenticationException; +import co.kirikiri.service.exception.BadRequestException; +import co.kirikiri.service.exception.ConflictException; +import co.kirikiri.service.exception.ForbiddenException; +import co.kirikiri.service.exception.NotFoundException; +import co.kirikiri.service.roadmap.RoadmapCreateService; import java.time.LocalDateTime; import java.util.Collections; import java.util.List; @@ -61,9 +63,9 @@ class RoadmapCreateServiceTest { private static final Member MEMBER = new Member(1L, new Identifier("identifier1"), - new EncryptedPassword(new Password("password1!")), new Nickname("닉네임"), + null, new EncryptedPassword(new Password("password1!")), new Nickname("닉네임"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(1999, 6, 8), "010-1234-5678")); + new MemberProfile(Gender.FEMALE, "kirikiri@email.com")); @Mock private MemberRepository memberRepository; @@ -87,7 +89,7 @@ class RoadmapCreateServiceTest { private ApplicationEventPublisher applicationEventPublisher; @InjectMocks - private RoadmapCreateService roadmapService; + private RoadmapCreateService roadmapCreateService; @Test void 로드맵을_생성한다() { @@ -114,7 +116,7 @@ class RoadmapCreateServiceTest { .thenReturn(Optional.of(MEMBER)); // expect - assertDoesNotThrow(() -> roadmapService.create(request, "identifier1")); + assertDoesNotThrow(() -> roadmapCreateService.create(request, "identifier1")); } @Test @@ -129,7 +131,7 @@ class RoadmapCreateServiceTest { .willReturn(Optional.empty()); // expect - assertThatThrownBy(() -> roadmapService.create(request, "identifier1")) + assertThatThrownBy(() -> roadmapCreateService.create(request, "identifier1")) .isInstanceOf(AuthenticationException.class); } @@ -147,7 +149,7 @@ class RoadmapCreateServiceTest { .willReturn(Optional.empty()); // expect - assertThatThrownBy(() -> roadmapService.create(request, "identifier1")) + assertThatThrownBy(() -> roadmapCreateService.create(request, "identifier1")) .isInstanceOf(NotFoundException.class); } @@ -155,9 +157,9 @@ class RoadmapCreateServiceTest { void 로드맵에_대한_리뷰를_추가한다() { // given final Member follower = new Member(2L, new Identifier("identifier2"), - new EncryptedPassword(new Password("password1!")), new Nickname("닉네임2"), + null, new EncryptedPassword(new Password("password1!")), new Nickname("닉네임2"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(1999, 6, 8), "010-1234-5678")); + new MemberProfile(Gender.FEMALE, "kirikiri@email.com")); final RoadmapCategory category = new RoadmapCategory(1L, "운동"); @@ -177,7 +179,7 @@ class RoadmapCreateServiceTest { final RoadmapReviewSaveRequest roadmapReviewSaveRequest = new RoadmapReviewSaveRequest("최고의 로드맵이네요", 5.0); // expected - assertDoesNotThrow(() -> roadmapService.createReview(1L, "identifier2", roadmapReviewSaveRequest)); + assertDoesNotThrow(() -> roadmapCreateService.createReview(1L, "identifier2", roadmapReviewSaveRequest)); } @Test @@ -190,7 +192,7 @@ class RoadmapCreateServiceTest { // expected assertThatThrownBy(() -> - roadmapService.createReview(1L, "cokirikiri", roadmapReviewSaveRequest)) + roadmapCreateService.createReview(1L, "cokirikiri", roadmapReviewSaveRequest)) .isInstanceOf(NotFoundException.class); } @@ -210,7 +212,7 @@ class RoadmapCreateServiceTest { // expected assertThatThrownBy(() -> - roadmapService.createReview(1L, "cokirikiri", roadmapReviewSaveRequest)) + roadmapCreateService.createReview(1L, "cokirikiri", roadmapReviewSaveRequest)) .isInstanceOf(BadRequestException.class); } @@ -218,9 +220,9 @@ class RoadmapCreateServiceTest { void 로드맵_리뷰_작성시_이미_작성을_완료했으면_예외가_발생한다() { // given final Member follower = new Member(2L, new Identifier("identifier2"), - new EncryptedPassword(new Password("password1!")), new Nickname("닉네임2"), + null, new EncryptedPassword(new Password("password1!")), new Nickname("닉네임2"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(1999, 6, 8), "010-1234-5678")); + new MemberProfile(Gender.FEMALE, "kirikiri@email.com")); final RoadmapCategory category = new RoadmapCategory(1L, "운동"); @@ -240,7 +242,7 @@ class RoadmapCreateServiceTest { final RoadmapReviewSaveRequest roadmapReviewSaveRequest = new RoadmapReviewSaveRequest("최고의 로드맵이네요", 5.0); // expected - assertThatThrownBy(() -> roadmapService.createReview(1L, "cokirikiri", roadmapReviewSaveRequest)) + assertThatThrownBy(() -> roadmapCreateService.createReview(1L, "cokirikiri", roadmapReviewSaveRequest)) .isInstanceOf(BadRequestException.class); } @@ -259,7 +261,7 @@ class RoadmapCreateServiceTest { // when // then - assertDoesNotThrow(() -> roadmapService.deleteRoadmap("identifier1", 1L)); + assertDoesNotThrow(() -> roadmapCreateService.deleteRoadmap("identifier1", 1L)); verify(roadmapRepository, times(1)).delete(any()); } @@ -267,8 +269,8 @@ class RoadmapCreateServiceTest { void 골룸이_생성된_적이_있는_로드맵을_삭제한다() { // given final Member follower = new Member(2L, new Identifier("identifier2"), - new EncryptedPassword(new Password("password1!")), new Nickname("닉네임2"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(1999, 6, 8), "010-1234-5678")); + null, new EncryptedPassword(new Password("password1!")), new Nickname("닉네임2"), null, + new MemberProfile(Gender.FEMALE, "kirikiri@email.com")); final RoadmapCategory category = new RoadmapCategory(1L, "운동"); final Roadmap roadmap = 로드맵을_생성한다(MEMBER, category); @@ -286,7 +288,7 @@ class RoadmapCreateServiceTest { // when // then - assertDoesNotThrow(() -> roadmapService.deleteRoadmap("identifier1", 1L)); + assertDoesNotThrow(() -> roadmapCreateService.deleteRoadmap("identifier1", 1L)); assertThat(roadmap.isDeleted()).isTrue(); verify(roadmapRepository, never()).delete(any()); } @@ -299,7 +301,7 @@ class RoadmapCreateServiceTest { // when // then - assertThatThrownBy(() -> roadmapService.deleteRoadmap("identifier1", 1L)) + assertThatThrownBy(() -> roadmapCreateService.deleteRoadmap("identifier1", 1L)) .isInstanceOf(NotFoundException.class) .hasMessage("존재하지 않는 로드맵입니다. roadmapId = 1"); } @@ -321,11 +323,38 @@ class RoadmapCreateServiceTest { // when // then - assertThatThrownBy(() -> roadmapService.deleteRoadmap("identifier2", 1L)) + assertThatThrownBy(() -> roadmapCreateService.deleteRoadmap("identifier2", 1L)) .isInstanceOf(ForbiddenException.class) .hasMessage("해당 로드맵을 생성한 사용자가 아닙니다."); } + @Test + void 정상적으로_로드맵_카테고리를_생성한다() { + //given + final RoadmapCategorySaveRequest category = new RoadmapCategorySaveRequest("운동"); + + when(roadmapCategoryRepository.findByName(anyString())) + .thenReturn(Optional.empty()); + + //when + //then + assertDoesNotThrow(() -> roadmapCreateService.createRoadmapCategory(category)); + } + + @Test + void 로드맵_카테고리_생성_시_중복될_이름일_경우_예외를_던진다() { + //given + final RoadmapCategorySaveRequest category = new RoadmapCategorySaveRequest("운동"); + + when(roadmapCategoryRepository.findByName(anyString())) + .thenReturn(Optional.of(new RoadmapCategory("운동"))); + + //when + //then + assertThatThrownBy(() -> roadmapCreateService.createRoadmapCategory(category)) + .isInstanceOf(ConflictException.class); + } + private Roadmap 로드맵을_생성한다(final Member creator, final RoadmapCategory category) { final RoadmapContent content = new RoadmapContent("콘텐츠 제목"); final Roadmap roadmap = new Roadmap("로드맵 제목", "로드맵 설명", 100, RoadmapDifficulty.NORMAL, creator, category); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapReadServiceTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapReadServiceTest.java index 655d3cab7..d6222964e 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapReadServiceTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapReadServiceTest.java @@ -13,6 +13,7 @@ import co.kirikiri.domain.goalroom.GoalRoom; import co.kirikiri.domain.goalroom.GoalRoomRoadmapNode; import co.kirikiri.domain.goalroom.GoalRoomRoadmapNodes; +import co.kirikiri.domain.goalroom.GoalRoomStatus; import co.kirikiri.domain.goalroom.vo.GoalRoomName; import co.kirikiri.domain.goalroom.vo.LimitedMemberCount; import co.kirikiri.domain.goalroom.vo.Period; @@ -34,7 +35,6 @@ import co.kirikiri.domain.roadmap.RoadmapTag; import co.kirikiri.domain.roadmap.RoadmapTags; import co.kirikiri.domain.roadmap.vo.RoadmapTagName; -import co.kirikiri.exception.NotFoundException; import co.kirikiri.persistence.goalroom.GoalRoomRepository; import co.kirikiri.persistence.goalroom.dto.RoadmapGoalRoomsOrderType; import co.kirikiri.persistence.member.MemberRepository; @@ -59,6 +59,8 @@ import co.kirikiri.service.dto.roadmap.response.RoadmapResponse; import co.kirikiri.service.dto.roadmap.response.RoadmapReviewResponse; import co.kirikiri.service.dto.roadmap.response.RoadmapTagResponse; +import co.kirikiri.service.exception.NotFoundException; +import co.kirikiri.service.roadmap.RoadmapReadService; import java.net.MalformedURLException; import java.net.URL; import java.time.LocalDate; @@ -78,9 +80,9 @@ class RoadmapReadServiceTest { private static final LocalDate TODAY = LocalDate.now(); private final Member member = new Member(1L, new Identifier("identifier1"), - new EncryptedPassword(new Password("password1!")), new Nickname("닉네임"), + null, new EncryptedPassword(new Password("password1!")), new Nickname("닉네임"), new MemberImage("originalFileName", "default-member-image", ImageContentType.JPG), - new MemberProfile(Gender.FEMALE, LocalDate.of(1999, 6, 8), "010-1234-5678")); + new MemberProfile(Gender.FEMALE, "kirikiri1@email.com")); private final LocalDateTime now = LocalDateTime.now(); @Mock @@ -491,7 +493,7 @@ roadmapId, new RoadmapCategoryResponse(1L, "운동"), "로드맵 제목", "로 final List goalRooms = List.of(goalRoom2, goalRoom1); given(roadmapRepository.findRoadmapById(anyLong())) .willReturn(Optional.of(roadmap)); - given(goalRoomRepository.findGoalRoomsWithPendingMembersByRoadmapAndCond(roadmap, + given(goalRoomRepository.findGoalRoomsByRoadmapAndCond(roadmap, RoadmapGoalRoomsOrderType.LATEST, null, 10)) .willReturn(goalRooms); given(fileService.generateUrl(anyString(), any())) @@ -503,11 +505,13 @@ roadmapId, new RoadmapCategoryResponse(1L, "운동"), "로드맵 제목", "로 final RoadmapGoalRoomResponses expected = new RoadmapGoalRoomResponses(List.of( - new RoadmapGoalRoomResponse(2L, "goalroom2", 1, 10, LocalDateTime.now(), + new RoadmapGoalRoomResponse(2L, "goalroom2", GoalRoomStatus.RECRUITING, 1, 10, + LocalDateTime.now(), TODAY, TODAY.plusDays(20), new MemberResponse(member3.getId(), member3.getNickname().getValue(), "http://example.com/serverFilePath")), - new RoadmapGoalRoomResponse(1L, "goalroom1", 1, 10, LocalDateTime.now(), + new RoadmapGoalRoomResponse(1L, "goalroom1", GoalRoomStatus.RECRUITING, 1, 10, + LocalDateTime.now(), TODAY, TODAY.plusDays(20), new MemberResponse(member2.getId(), member2.getNickname().getValue(), "http://example.com/serverFilePath"))), false); @@ -588,10 +592,10 @@ RoadmapGoalRoomsOrderTypeDto.LATEST, new CustomScrollRequest(null, 10))) private Member 사용자를_생성한다(final Long id, final String identifier, final String nickname) { return new Member(id, new Identifier(identifier), - new EncryptedPassword(new Password("password1!")), + null, new EncryptedPassword(new Password("password1!")), new Nickname(nickname), new MemberImage("originalFileName", "default-profile-image", ImageContentType.JPG), - new MemberProfile(Gender.FEMALE, LocalDate.of(2000, 7, 20), "010-1111-1111")); + new MemberProfile(Gender.FEMALE, "kirikiri1@email.com")); } private Roadmap 로드맵을_생성한다(final String roadmapTitle, final RoadmapCategory category) { diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapSchedulerTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapSchedulerTest.java index 6487784dd..eaea4f202 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapSchedulerTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/RoadmapSchedulerTest.java @@ -27,14 +27,15 @@ import co.kirikiri.domain.roadmap.RoadmapNodes; import co.kirikiri.persistence.goalroom.GoalRoomRepository; import co.kirikiri.persistence.roadmap.RoadmapRepository; -import java.time.LocalDate; -import java.util.Collections; -import java.util.List; +import co.kirikiri.service.scheduler.RoadmapScheduler; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import java.time.LocalDate; +import java.util.Collections; +import java.util.List; @ExtendWith(MockitoExtension.class) class RoadmapSchedulerTest { @@ -56,10 +57,10 @@ class RoadmapSchedulerTest { // given final Member member1 = new Member(new Identifier("identifier1"), new EncryptedPassword(new Password("password1!")), new Nickname("name1"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(1900, 1, 1), "010-1111-1111")); + new MemberProfile(Gender.FEMALE, "kirikiri@email.com")); final Member member2 = new Member(new Identifier("identifier2"), new EncryptedPassword(new Password("password2!")), new Nickname("name2"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(1900, 1, 1), "010-1111-2222")); + new MemberProfile(Gender.FEMALE, "kirikiri@email.com")); final RoadmapCategory category = new RoadmapCategory("여행"); final RoadmapContent roadmapContent1_1 = new RoadmapContent("로드맵 본문2"); @@ -101,10 +102,10 @@ class RoadmapSchedulerTest { // given final Member member1 = new Member(new Identifier("identifier1"), new EncryptedPassword(new Password("password1!")), new Nickname("name1"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(1900, 1, 1), "010-1111-1111")); + new MemberProfile(Gender.FEMALE, "kirikiri@email.com")); final Member member2 = new Member(new Identifier("identifier2"), new EncryptedPassword(new Password("password2!")), new Nickname("name2"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(1900, 1, 1), "010-1111-2222")); + new MemberProfile(Gender.FEMALE, "kirikiri@email.com")); final RoadmapCategory category = new RoadmapCategory("여행"); final RoadmapContent roadmapContent1 = new RoadmapContent("로드맵 본문1"); @@ -140,10 +141,10 @@ class RoadmapSchedulerTest { // given final Member member1 = new Member(new Identifier("identifier1"), new EncryptedPassword(new Password("password1!")), new Nickname("name1"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(1900, 1, 1), "010-1111-1111")); + new MemberProfile(Gender.FEMALE, "kirikiri@email.com")); final Member member2 = new Member(new Identifier("identifier2"), new EncryptedPassword(new Password("password2!")), new Nickname("name2"), null, - new MemberProfile(Gender.FEMALE, LocalDate.of(1900, 1, 1), "010-1111-2222")); + new MemberProfile(Gender.FEMALE, "kirikiri@email.com")); final RoadmapCategory category = new RoadmapCategory("여행"); final RoadmapContent roadmapContent1 = new RoadmapContent("로드맵 본문1"); diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/UUIDFilePathGeneratorTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/UUIDFilePathGeneratorTest.java index 39a036b81..7e9dc620d 100644 --- a/backend/kirikiri/src/test/java/co/kirikiri/service/UUIDFilePathGeneratorTest.java +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/UUIDFilePathGeneratorTest.java @@ -1,9 +1,12 @@ package co.kirikiri.service; -import static org.junit.jupiter.api.Assertions.assertAll; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertTrue; +import co.kirikiri.service.exception.BadRequestException; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; class UUIDFilePathGeneratorTest { @@ -19,9 +22,44 @@ class UUIDFilePathGeneratorTest { final String filePath = filePathGenerator.makeFilePath(imageDirType, originalFileName); //then - assertAll( - () -> assertTrue(filePath.contains(imageDirType.getDirName())), - () -> assertTrue(filePath.contains(originalFileName)) - ); + assertTrue(filePath.contains(imageDirType.getDirName())); + } + + @ParameterizedTest + @ValueSource(strings = {"가.jpg", "나다.jpg", "랅.jpg", "테스트.jpg"}) + void 파일이름에_한글이_들어간_경우_정상적으로_경로를_쌩성한다(final String originalFileName) { + //given + final ImageDirType imageDirType = ImageDirType.ROADMAP_NODE; + + //when + final String filePath = filePathGenerator.makeFilePath(imageDirType, originalFileName); + + //then + assertTrue(filePath.contains(imageDirType.getDirName())); + } + + @ParameterizedTest + @ValueSource(strings = {" .jpg", "가운데 공백.jpg", " 앞에공백.jpg", "뒤에공백 .jpg"}) + void 파일이름에_공백이_들어간_경우_정상적으로_경로를_쌩성한다(final String originalFileName) { + //given + final ImageDirType imageDirType = ImageDirType.ROADMAP_NODE; + + //when + final String filePath = filePathGenerator.makeFilePath(imageDirType, originalFileName); + + //then + assertTrue(filePath.contains(imageDirType.getDirName())); + } + + @Test + void 파일_이름에_확장자가_없을_경우_예외가_발생한다() { + //given + final ImageDirType imageDirType = ImageDirType.ROADMAP_NODE; + final String originalFileName = "originalFileName"; + + //when + //then + assertThatThrownBy(() -> filePathGenerator.makeFilePath(imageDirType, originalFileName)) + .isInstanceOf(BadRequestException.class); } } diff --git a/backend/kirikiri/src/test/java/co/kirikiri/service/dto/member/request/GenderTypeTest.java b/backend/kirikiri/src/test/java/co/kirikiri/service/dto/member/request/GenderTypeTest.java new file mode 100644 index 000000000..0c043f4e4 --- /dev/null +++ b/backend/kirikiri/src/test/java/co/kirikiri/service/dto/member/request/GenderTypeTest.java @@ -0,0 +1,44 @@ +package co.kirikiri.service.dto.member.request; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +class GenderTypeTest { + + @Test + void oauthGenderType이_M인_경우_MALE을_반환한다() { + //given + final String oauthGenderType = "M"; + + //when + final GenderType genderType = GenderType.findByOauthType(oauthGenderType); + + //then + assertThat(genderType).isEqualTo(GenderType.MALE); + } + + @Test + void oauthGenderType이_F인_경우_FEMALE을_반환한다() { + //given + final String oauthGenderType = "F"; + + //when + final GenderType genderType = GenderType.findByOauthType(oauthGenderType); + + //then + assertThat(genderType).isEqualTo(GenderType.FEMALE); + } + + @Test + void oauthGenderType이_U인_경우_UNDEFINED을_반환한다() { + //given + final String oauthGenderType = "U"; + + //when + final GenderType genderType = GenderType.findByOauthType(oauthGenderType); + + //then + assertThat(genderType).isEqualTo(GenderType.UNDEFINED); + } +} diff --git a/backend/kirikiri/src/test/resources/application.yml b/backend/kirikiri/src/test/resources/application.yml index c36e03cde..54e9cdfd7 100644 --- a/backend/kirikiri/src/test/resources/application.yml +++ b/backend/kirikiri/src/test/resources/application.yml @@ -15,6 +15,10 @@ spring: max-file-size: 10MB flyway: enabled: false + data: + redis: + host: localhost + port: 6379 logging: level: @@ -55,9 +59,21 @@ cloud: stack: auto: false credentials: - instanceProfile: true + access-key: access-key + secret-key: secret-key s3: - bucket: 2023-team-project + bucket: 2023-team-project-kirikiri root-directory: 2023-co-kirikiri sub-directory: prod url-expiration: 60000 + cloud-front: + distribution-domain: https://d3c3ldqehj669c.cloudfront.net + +oauth: + naver: + client-id: test + client-secret: test + redirect-url: https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=%s&redirect_uri=%s&state=%s + callback-url: test + token-url: https://nid.naver.com/oauth2.0/token? + member-info-url: https://openapi.naver.com/v1/nid/me diff --git a/client/src/apis/user.ts b/client/src/apis/user.ts index 3d101a02d..1d1cd15e4 100644 --- a/client/src/apis/user.ts +++ b/client/src/apis/user.ts @@ -1,15 +1,22 @@ import client from '@apis/axios/client'; -import type { +import { MemberJoinRequest, + OAuthResponse, UserLoginRequest, UserLoginResponse, + UserInfoResponse, } from '@myTypes/user/remote'; -import { UserInfoResponse } from '@myTypes/user/remote'; export const signUp = (body: MemberJoinRequest) => { return client.post('/members/join', body); }; +export const naverLogin = async () => { + const { data } = await client.get('/auth/oauth/naver'); + + return data; +}; + export const login = (body: UserLoginRequest) => { return client.post('/auth/login', body); }; diff --git a/client/src/components/icons/svgIcons.tsx b/client/src/components/icons/svgIcons.tsx index b43d4786c..09e3a9139 100644 --- a/client/src/components/icons/svgIcons.tsx +++ b/client/src/components/icons/svgIcons.tsx @@ -82,7 +82,7 @@ export const CalendarIcon = ({ width, ...props }: SVGProps) => ( xmlns='http://www.w3.org/2000/svg' width={width} height={width} - viewBox='0 0 24 24' + viewBox='0 0 48 48' > ) => ( ); -export const GoogleIcon = ({ width }: SVGProps) => ( +export const NaverIcon = ({ width }: SVGProps) => ( - - - - - -); - -export const KakaoIcon = ({ width }: SVGProps) => ( - - - ); diff --git a/client/src/components/loginPage/loginOptions/LoginOptions.styles.ts b/client/src/components/loginPage/loginOptions/LoginOptions.styles.ts index 1836f9333..5e22a32c2 100644 --- a/client/src/components/loginPage/loginOptions/LoginOptions.styles.ts +++ b/client/src/components/loginPage/loginOptions/LoginOptions.styles.ts @@ -8,24 +8,24 @@ export const OathButtonContainer = styled.div` align-items: center; justify-content: center; - margin-top: 7rem; + margin-top: 2rem; `; export const OathButton = styled.button<{ type?: string }>` + ${({ theme }) => theme.fonts.button1} display: flex; align-items: center; justify-content: center; width: 100%; + height: 4rem; margin-top: 1rem; padding: 1rem; + color: ${({ type, theme }) => type === 'naver' && theme.colors.white}; + background: ${({ type, theme }) => - type === 'kakao' - ? 'rgb(255, 225, 83)' - : type === 'google' - ? theme.colors.gray100 - : theme.colors.main_dark}; + type === 'naver' ? '#5AC466' : theme.colors.main_dark}; border: none; border-radius: 1rem; @@ -34,4 +34,8 @@ export const OathButton = styled.button<{ type?: string }>` &:hover { transform: scale(1.04); } + + & > span { + margin-left: ${({ type }) => type === 'naver' && '1rem'}; + } `; diff --git a/client/src/components/loginPage/loginOptions/LoginOptions.tsx b/client/src/components/loginPage/loginOptions/LoginOptions.tsx index 2d5354a5d..7b2d5f961 100644 --- a/client/src/components/loginPage/loginOptions/LoginOptions.tsx +++ b/client/src/components/loginPage/loginOptions/LoginOptions.tsx @@ -1,3 +1,4 @@ +import { naverLogin } from '@apis/user'; import SVGIcon from '@components/icons/SVGIcon'; import * as S from './LoginOptions.styles'; @@ -6,19 +7,21 @@ type LoginOptionsProps = { }; const LoginOptions = ({ toggleLoginForm }: LoginOptionsProps) => { + const onClickNaverLoginButton = () => { + naverLogin(); + }; + return ( <>
- {/* - - 카카오톡으로 3초 만에 로그인하기 + + + 네이버 로그인 - - 구글로 로그인하기 - */} - 아이디로 로그인하기 + + 아이디로 로그인하기
diff --git a/client/src/constants/@queryKeys/queryKeys.ts b/client/src/constants/@queryKeys/queryKeys.ts index 49bac5db4..818f54f28 100644 --- a/client/src/constants/@queryKeys/queryKeys.ts +++ b/client/src/constants/@queryKeys/queryKeys.ts @@ -1,6 +1,7 @@ const QUERY_KEYS = { user: { user: 'user', + naver_oauth: 'naver_login', }, roadmap: { list: 'roadmapList', diff --git a/client/src/hooks/queries/user.ts b/client/src/hooks/queries/user.ts index 98181712f..a1c75c90a 100644 --- a/client/src/hooks/queries/user.ts +++ b/client/src/hooks/queries/user.ts @@ -4,7 +4,7 @@ import { UserInfoResponse, UserLoginRequest, } from '@myTypes/user/remote'; -import { getUserInfo, login, signUp } from '@apis/user'; +import { getUserInfo, login, naverLogin, signUp } from '@apis/user'; import useToast from '@hooks/_common/useToast'; import { defaultUserInfo, @@ -14,6 +14,8 @@ import { AxiosResponse } from 'axios'; import { useNavigate } from 'react-router-dom'; import { setCookie } from '@/utils/_common/cookies'; import logout from '@utils/user/logout'; +import { useSuspendedQuery } from './useSuspendedQuery'; +import QUERY_KEYS from '@/constants/@queryKeys/queryKeys'; export const useSignUp = () => { const { triggerToast } = useToast(); @@ -34,6 +36,26 @@ export const useSignUp = () => { }; }; +export const useNaverLogin = async () => { + const navigate = useNavigate(); + const { triggerToast } = useToast(); + const { setUserInfo } = useUserInfoContext(); + + useSuspendedQuery([QUERY_KEYS.user.naver_oauth], () => naverLogin(), { + onSuccess({ accessToken, refreshToken }) { + setCookie('access_token', accessToken); + setCookie('refresh_token', refreshToken); + triggerToast({ message: '로그인 성공!' }); + + getUserInfo().then((response: AxiosResponse) => { + setUserInfo(response.data); + }); + + navigate('/roadmap-list'); + }, + }); +}; + export const useLogin = () => { const navigate = useNavigate(); const { triggerToast } = useToast(); diff --git a/client/src/myTypes/user/remote.ts b/client/src/myTypes/user/remote.ts index 68f1c6871..ae3f3103d 100644 --- a/client/src/myTypes/user/remote.ts +++ b/client/src/myTypes/user/remote.ts @@ -12,6 +12,11 @@ export type UserLoginRequest = { password: string; }; +export type OAuthResponse = { + accessToken: string; + refreshToken: string; +}; + export type UserLoginResponse = { accessToken: string; refreshToken: string;