-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
586674a
commit 8a47c6f
Showing
6 changed files
with
347 additions
and
1 deletion.
There are no files selected for viewing
26 changes: 26 additions & 0 deletions
26
server/src/main/kotlin/com/fone/profile/application/ValidateProfileFacade.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.fone.profile.application | ||
|
||
import com.fone.profile.domain.service.ValidateProfileService | ||
import com.fone.profile.presentation.dto.ValidateProfileDto | ||
import org.springframework.stereotype.Service | ||
|
||
@Service | ||
class ValidateProfileFacade( | ||
private val validateProfileService: ValidateProfileService, | ||
) { | ||
|
||
suspend fun validateBasicPage(basicPageValidation: ValidateProfileDto.BasicPageValidation) = | ||
validateProfileService.validateBasicPage(basicPageValidation) | ||
|
||
suspend fun validateDetailPage(email: String, detailPageValidation: ValidateProfileDto.DetailPageValidation) = | ||
validateProfileService.validateDetailPage(email, detailPageValidation) | ||
|
||
suspend fun validateDescriptionPage(descriptionPageValidation: ValidateProfileDto.DescriptionPageValidation) = | ||
validateProfileService.validateDescriptionPage(descriptionPageValidation) | ||
|
||
suspend fun validateCareerPage(careerPageValidation: ValidateProfileDto.CareerPageValidation) = | ||
validateProfileService.validateCareerPage(careerPageValidation) | ||
|
||
suspend fun validateInterestPage(interestPageValidation: ValidateProfileDto.InterestPageValidation) = | ||
validateProfileService.validateInterestPage(interestPageValidation) | ||
} |
86 changes: 86 additions & 0 deletions
86
server/src/main/kotlin/com/fone/profile/domain/service/ValidateProfileService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package com.fone.profile.domain.service | ||
|
||
import com.fone.common.exception.NotFoundUserException | ||
import com.fone.common.exception.RequestValidationException | ||
import com.fone.profile.presentation.dto.ValidateProfileDto | ||
import com.fone.user.domain.enum.Job | ||
import com.fone.user.domain.repository.UserRepository | ||
import org.hibernate.validator.internal.constraintvalidators.hv.URLValidator | ||
import org.springframework.stereotype.Service | ||
|
||
@Service | ||
class ValidateProfileService( | ||
private val userRepository: UserRepository, | ||
) { | ||
private val urlValidator = URLValidator() | ||
|
||
fun validateBasicPage(basicPageValidation: ValidateProfileDto.BasicPageValidation) { | ||
if (basicPageValidation.name.isNullOrBlank()) { | ||
throw RequestValidationException("항목 '이름'이 비었습니다.") | ||
} | ||
if (basicPageValidation.hookingComment.isNullOrEmpty()) { | ||
throw RequestValidationException("항목 '후킹멘트'가 비었습니다.") | ||
} | ||
if (basicPageValidation.profileImages.isNullOrEmpty()) { | ||
throw RequestValidationException("항목 '이미지 첨부'가 비었습니다.") | ||
} | ||
if (basicPageValidation.profileImages.any { urlValidator.isValid(it, null) }) { | ||
throw RequestValidationException("항목 '이미지 첨부'에 유효하지 않은 값이 있습니다.") | ||
} | ||
} | ||
|
||
suspend fun validateDetailPage( | ||
email: String, | ||
detailPageValidation: ValidateProfileDto.DetailPageValidation, | ||
) { | ||
val user = userRepository.findByEmail(email) ?: throw NotFoundUserException() | ||
if (detailPageValidation.birthday == null) { | ||
throw RequestValidationException("항목 '출생연도'가 비었습니다.") | ||
} | ||
if (detailPageValidation.gender == null) { | ||
throw RequestValidationException("항목 '성별'이 비었습니다.") | ||
} | ||
if (user.job == Job.STAFF) { | ||
if (detailPageValidation.domains.isNullOrEmpty()) { | ||
throw RequestValidationException("항목 '도메인'이 비었습니다.") | ||
} | ||
} else { | ||
if (detailPageValidation.height == null) { | ||
throw RequestValidationException("항목 '신장'이 비었습니다.") | ||
} | ||
if (detailPageValidation.weight == null) { | ||
throw RequestValidationException("항목 '체중'이 비었습니다.") | ||
} | ||
} | ||
if (detailPageValidation.email == null) { | ||
throw RequestValidationException("항목 '성별'이 비었습니다.") | ||
} | ||
} | ||
|
||
fun validateDescriptionPage(descriptionPageValidation: ValidateProfileDto.DescriptionPageValidation) { | ||
if (descriptionPageValidation.details.isNullOrBlank()) { | ||
throw RequestValidationException("항목 '상세요강'이 비었습니다.") | ||
} | ||
if (descriptionPageValidation.details.length > 200) { | ||
throw RequestValidationException("항목 '상세요강'이 200자 넘습니다.") | ||
} | ||
} | ||
|
||
fun validateCareerPage(careerPageValidation: ValidateProfileDto.CareerPageValidation) { | ||
if (careerPageValidation.career == null) { | ||
throw RequestValidationException("항목 '경력'이 비었습니다.") | ||
} | ||
if (careerPageValidation.careerDetail.isNullOrBlank()) { | ||
throw RequestValidationException("항목 '경력 상세사항'이 비었습니다.") | ||
} | ||
if (careerPageValidation.careerDetail.length > 500) { | ||
throw RequestValidationException("항목 '경력 상세사항'이 500자 넘습니다.") | ||
} | ||
} | ||
|
||
fun validateInterestPage(interestPageValidation: ValidateProfileDto.InterestPageValidation) { | ||
if (interestPageValidation.categories.isNullOrEmpty()) { | ||
throw RequestValidationException("항목 '관심사'가 비었습니다.") | ||
} | ||
} | ||
} |
97 changes: 97 additions & 0 deletions
97
server/src/main/kotlin/com/fone/profile/presentation/controller/ValidateProfileController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package com.fone.profile.presentation.controller | ||
|
||
import com.fone.common.response.CommonResponse | ||
import com.fone.profile.application.ValidateProfileFacade | ||
import com.fone.profile.presentation.dto.ValidateProfileDto | ||
import io.swagger.annotations.Api | ||
import io.swagger.annotations.ApiOperation | ||
import io.swagger.v3.oas.annotations.responses.ApiResponse | ||
import org.springframework.security.access.prepost.PreAuthorize | ||
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.RestController | ||
import java.security.Principal | ||
|
||
@Api(tags = ["04. Profile Info"], description = "프로필 서비스") | ||
@RestController | ||
@RequestMapping("/api/v1/profiles/validate") | ||
class ValidateProfileController( | ||
private val validateProfileFacade: ValidateProfileFacade, | ||
) { | ||
@PostMapping("/basic") | ||
@PreAuthorize("hasRole('USER')") | ||
@ApiOperation(value = "프로필 검증 API") | ||
@ApiResponse( | ||
responseCode = "200", | ||
description = "성공" | ||
) | ||
suspend fun basicPageValidate( | ||
@RequestBody | ||
basicPageValidation: ValidateProfileDto.BasicPageValidation, | ||
): CommonResponse<Unit> { | ||
validateProfileFacade.validateBasicPage(basicPageValidation) | ||
return CommonResponse.success() | ||
} | ||
|
||
@PostMapping("/details") | ||
@PreAuthorize("hasRole('USER')") | ||
@ApiOperation(value = "프로필 검증 API") | ||
@ApiResponse( | ||
responseCode = "200", | ||
description = "성공" | ||
) | ||
suspend fun detailPageValidate( | ||
principal: Principal, | ||
@RequestBody | ||
detailPageValidation: ValidateProfileDto.DetailPageValidation, | ||
): CommonResponse<Unit> { | ||
validateProfileFacade.validateDetailPage(principal.name, detailPageValidation) | ||
return CommonResponse.success() | ||
} | ||
|
||
@PostMapping("/description") | ||
@PreAuthorize("hasRole('USER')") | ||
@ApiOperation(value = "프로필 검증 API") | ||
@ApiResponse( | ||
responseCode = "200", | ||
description = "성공" | ||
) | ||
suspend fun descriptionValidate( | ||
@RequestBody | ||
descriptionPageValidation: ValidateProfileDto.DescriptionPageValidation, | ||
): CommonResponse<Unit> { | ||
validateProfileFacade.validateDescriptionPage(descriptionPageValidation) | ||
return CommonResponse.success() | ||
} | ||
|
||
@PostMapping("/career") | ||
@PreAuthorize("hasRole('USER')") | ||
@ApiOperation(value = "프로필 검증 API") | ||
@ApiResponse( | ||
responseCode = "200", | ||
description = "성공" | ||
) | ||
suspend fun careerValidate( | ||
@RequestBody | ||
careerPageValidation: ValidateProfileDto.CareerPageValidation, | ||
): CommonResponse<Unit> { | ||
validateProfileFacade.validateCareerPage(careerPageValidation) | ||
return CommonResponse.success() | ||
} | ||
|
||
@PostMapping("/interest") | ||
@PreAuthorize("hasRole('USER')") | ||
@ApiOperation(value = "프로필 검증 API") | ||
@ApiResponse( | ||
responseCode = "200", | ||
description = "성공" | ||
) | ||
suspend fun interestValidate( | ||
@RequestBody | ||
interestPageValidation: ValidateProfileDto.InterestPageValidation, | ||
): CommonResponse<Unit> { | ||
validateProfileFacade.validateInterestPage(interestPageValidation) | ||
return CommonResponse.success() | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
server/src/main/kotlin/com/fone/profile/presentation/dto/ValidateProfileDto.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package com.fone.profile.presentation.dto | ||
|
||
import com.fone.common.entity.Career | ||
import com.fone.common.entity.CategoryType | ||
import com.fone.common.entity.DomainType | ||
import com.fone.common.entity.Gender | ||
import com.fone.profile.presentation.dto.common.ProfileSnsUrl | ||
import io.swagger.v3.oas.annotations.media.Schema | ||
import java.time.LocalDate | ||
|
||
class ValidateProfileDto { | ||
data class BasicPageValidation( | ||
@Schema(description = "프로필 이름", required = true, example = "차이나는 클라스") | ||
val name: String?, | ||
@Schema(description = "후킹멘트", required = true, example = "제가 좋아하는 색은 노랑색이에요") | ||
val hookingComment: String?, | ||
@Schema( | ||
description = "이미지 URL", | ||
example = "['https://s3-ap-northeast-2.amazonaws.com/f-one-image/prod/user-profile/image.jpg']" | ||
) | ||
val profileImages: List<String>?, | ||
) | ||
|
||
data class DetailPageValidation( | ||
@Schema(description = "생년월일", example = "2000-10-01") | ||
val birthday: LocalDate?, | ||
@Schema(description = "성별", example = "WOMAN") | ||
val gender: Gender?, | ||
@Schema(description = "키", example = "188") | ||
val height: Int?, | ||
@Schema(description = "몸무게", example = "70") | ||
val weight: Int?, | ||
@Schema(description = "이메일", example = "example@something.com") | ||
val email: String?, | ||
@Schema(description = "SNS v2") | ||
val snsUrls: List<ProfileSnsUrl>?, | ||
@Schema(description = "특기", example = "매운 음식 먹기") | ||
val specialty: String?, | ||
@Schema(description = "분야", example = "PLANNING") | ||
val domains: List<DomainType>?, | ||
) | ||
|
||
data class DescriptionPageValidation( | ||
@Schema(description = "상세요강") | ||
val details: String?, | ||
) | ||
|
||
data class CareerPageValidation( | ||
@Schema(description = "경력", example = "LESS_THAN_3YEARS") | ||
val career: Career?, | ||
@Schema(description = "경력 상세 설명", example = "복숭아 요거트 제작 3년") | ||
val careerDetail: String?, | ||
) | ||
|
||
data class InterestPageValidation( | ||
@Schema(description = "관심사", example = "WEB_DRAMA") | ||
val categories: List<CategoryType>?, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
78 changes: 78 additions & 0 deletions
78
...src/test/kotlin/com/fone/profile/presentation/controller/ValidateProfileControllerTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package com.fone.profile.presentation.controller | ||
|
||
import com.fone.common.CommonUserCallApi | ||
import com.fone.common.CustomDescribeSpec | ||
import com.fone.common.IntegrationTest | ||
import com.fone.common.doPost | ||
import com.fone.common.entity.Gender | ||
import com.fone.profile.domain.enum.SNS | ||
import com.fone.profile.presentation.dto.ValidateProfileDto | ||
import com.fone.profile.presentation.dto.common.ProfileSnsUrl | ||
import org.springframework.test.web.reactive.server.WebTestClient | ||
import java.time.LocalDate | ||
|
||
@IntegrationTest | ||
class ValidateProfileControllerTest(client: WebTestClient) : CustomDescribeSpec() { | ||
init { | ||
val url = "/api/v1/profiles/validate" | ||
val (accessToken, _) = CommonUserCallApi.getAccessToken(client) | ||
describe("#Profile 검증 API") { | ||
context("basic 페이지") { | ||
it("성공한다") { | ||
val request = | ||
ValidateProfileDto.BasicPageValidation( | ||
"제목", | ||
"후킹멘트", | ||
listOf("https://s3-ap-northeast-2.amazonaws.com/f-one-image/prod/user-profile/image.jpg") | ||
) | ||
client.doPost("$url/basic", request, accessToken) | ||
.expectStatus().isOk.expectBody() | ||
.consumeWith { println(it) }.jsonPath("$.result").isEqualTo("SUCCESS") | ||
} | ||
it("실패한다") { | ||
val request = | ||
ValidateProfileDto.BasicPageValidation( | ||
"제목", | ||
"후킹멘트", | ||
listOf("") | ||
) | ||
client.doPost("$url/basic", request, accessToken).expectStatus().isBadRequest.expectBody() | ||
.consumeWith { println(it) }.jsonPath("$.result").isEqualTo("FAIL") | ||
} | ||
} | ||
context("details 페이지") { | ||
it("성공한다") { | ||
val request = | ||
ValidateProfileDto.DetailPageValidation( | ||
LocalDate.now(), | ||
Gender.MAN, | ||
170, | ||
300, | ||
"mail@mail.com", | ||
listOf(ProfileSnsUrl("123", SNS.YOUTUBE)), | ||
"고추장 잘 먹음", | ||
null | ||
) | ||
client.doPost("$url/details", request, accessToken) | ||
.expectStatus().isOk.expectBody() | ||
.consumeWith { println(it) }.jsonPath("$.result").isEqualTo("SUCCESS") | ||
} | ||
it("실패한다") { | ||
val request = | ||
ValidateProfileDto.DetailPageValidation( | ||
LocalDate.now(), | ||
Gender.MAN, | ||
null, | ||
300, | ||
"mail@mail.com", | ||
listOf(ProfileSnsUrl("123", SNS.YOUTUBE)), | ||
"고추장 잘 먹음", | ||
null | ||
) | ||
client.doPost("$url/details", request, accessToken).expectStatus().isBadRequest.expectBody() | ||
.consumeWith { println(it) }.jsonPath("$.result").isEqualTo("FAIL") | ||
} | ||
} | ||
} | ||
} | ||
} |