Skip to content

Commit

Permalink
merge: (#99) 프로필 사진 변경 기능 (#100)
Browse files Browse the repository at this point in the history
  • Loading branch information
khcho0125 authored Oct 11, 2022
2 parents 2d3e9a3 + 952cc31 commit f07a5d8
Show file tree
Hide file tree
Showing 14 changed files with 282 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package team.comit.simtong.domain.file.spi

/**
*
* 파일 확인을 요청하는 CheckFilePort
*
* @author Chokyunghyeon
* @date 2022/10/11
* @version 1.0.0
**/
interface CheckFilePort {

fun existsPath(path: String): Boolean

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import java.io.File

/**
*
* 파일을 업로드 요청하는 ManageFilePort
* 파일을 업로드 요청하는 UploadFilePort
*
* @author Chokyunghyeon
* @date 2022/09/07
* @version 1.0.0
**/
interface ManageFilePort {
interface UploadFilePort {

fun upload(file: File): String

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package team.comit.simtong.domain.file.usecase

import team.comit.simtong.domain.file.exception.FileInvalidExtensionException
import team.comit.simtong.domain.file.spi.ManageFilePort
import team.comit.simtong.domain.file.spi.UploadFilePort
import team.comit.simtong.global.annotation.UseCase
import java.io.File

Expand All @@ -15,7 +15,7 @@ import java.io.File
**/
@UseCase
class UploadImageUseCase(
private val manageFilePort: ManageFilePort
private val uploadFilePort: UploadFilePort
) {

fun execute(file: File): String {
Expand All @@ -24,7 +24,7 @@ class UploadImageUseCase(
throw FileInvalidExtensionException.EXCEPTION
}

return manageFilePort.upload(file)
return uploadFilePort.upload(file)
}

fun execute(files: List<File>): List<String> {
Expand All @@ -35,7 +35,7 @@ class UploadImageUseCase(
}
}

return manageFilePort.upload(files)
return uploadFilePort.upload(files)
}

private fun isCorrectExtension(file: File) = when (file.extension) { // TODO Coverage 경고 해결
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package team.comit.simtong.domain.user.dto

/**
*
* 프로필 사진 변경 요청 정보를 전달하는 ChangeProfileImageRequest
*
* @author Chokyunghyeon
* @date 2022/10/03
* @version 1.0.0
**/
data class ChangeProfileImageRequest(
val profileImagePath: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package team.comit.simtong.domain.user.usecase

import team.comit.simtong.domain.file.exception.NotFoundFilePathException
import team.comit.simtong.domain.file.spi.CheckFilePort
import team.comit.simtong.domain.user.dto.ChangeProfileImageRequest
import team.comit.simtong.domain.user.exception.UserNotFoundException
import team.comit.simtong.domain.user.spi.CommandUserPort
import team.comit.simtong.domain.user.spi.QueryUserPort
import team.comit.simtong.domain.user.spi.UserSecurityPort
import team.comit.simtong.global.annotation.UseCase

/**
*
* 프로필 사진 변경을 담당하는 ChangeProfileImageUseCase
*
* @author Chokyunghyeon
* @date 2022/10/03
* @version 1.0.0
**/
@UseCase
class ChangeProfileImageUseCase(
private val queryUserPort: QueryUserPort,
private val userSecurityPort: UserSecurityPort,
private val commandUserPort: CommandUserPort,
private val checkFilePort: CheckFilePort
) {

fun execute(request: ChangeProfileImageRequest) {
if (!checkFilePort.existsPath(request.profileImagePath)) {
throw NotFoundFilePathException.EXCEPTION
}

val currentUserId = userSecurityPort.getCurrentUserId()
val user = queryUserPort.queryUserById(currentUserId) ?: throw UserNotFoundException.EXCEPTION

commandUserPort.save(
user.copy(
profileImagePath = request.profileImagePath
)
)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import org.mockito.BDDMockito.given
import org.springframework.boot.test.mock.mockito.MockBean
import org.springframework.test.context.junit.jupiter.SpringExtension
import team.comit.simtong.domain.file.exception.FileInvalidExtensionException
import team.comit.simtong.domain.file.spi.ManageFilePort
import team.comit.simtong.domain.file.spi.UploadFilePort
import java.io.File

@ExtendWith(SpringExtension::class)
class UploadImageUseCaseTests {

@MockBean
private lateinit var managerFilePort: ManageFilePort
private lateinit var managerFilePort: UploadFilePort

private lateinit var uploadImageUseCase: UploadImageUseCase

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package team.comit.simtong.domain.user.usecase

import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertDoesNotThrow
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.BDDMockito.given
import org.springframework.boot.test.mock.mockito.MockBean
import org.springframework.test.context.junit.jupiter.SpringExtension
import team.comit.simtong.domain.file.exception.NotFoundFilePathException
import team.comit.simtong.domain.file.spi.CheckFilePort
import team.comit.simtong.domain.user.dto.ChangeProfileImageRequest
import team.comit.simtong.domain.user.exception.UserNotFoundException
import team.comit.simtong.domain.user.model.Authority
import team.comit.simtong.domain.user.model.User
import team.comit.simtong.domain.user.spi.CommandUserPort
import team.comit.simtong.domain.user.spi.QueryUserPort
import team.comit.simtong.domain.user.spi.UserSecurityPort
import java.util.UUID

@ExtendWith(SpringExtension::class)
class ChangeProfileImageUseCaseTests {

@MockBean
private lateinit var queryUserPort: QueryUserPort

@MockBean
private lateinit var userSecurityPort: UserSecurityPort

@MockBean
private lateinit var commandUserPort: CommandUserPort

@MockBean
private lateinit var checkFilePort: CheckFilePort

private lateinit var changeProfileImageUseCase: ChangeProfileImageUseCase

private val id = UUID.randomUUID()

private val requestStub: ChangeProfileImageRequest by lazy {
ChangeProfileImageRequest(
profileImagePath = "test path"
)
}

private val userStub: User by lazy {
User(
id = id,
nickname = "test nickname",
name = "test name",
email = "test email",
password = "test password",
employeeNumber = 1234567890,
authority = Authority.ROLE_COMMON,
spotId = id,
teamId = id,
profileImagePath = "test path"
)
}

@BeforeEach
fun setUp() {
changeProfileImageUseCase = ChangeProfileImageUseCase(
queryUserPort,
userSecurityPort,
commandUserPort,
checkFilePort
)
}

@Test
fun `프로필 사진 변경 성공`() {
// given
given(checkFilePort.existsPath(requestStub.profileImagePath))
.willReturn(true)

given(userSecurityPort.getCurrentUserId())
.willReturn(id)

given(queryUserPort.queryUserById(id))
.willReturn(userStub)

// when & then
assertDoesNotThrow {
changeProfileImageUseCase.execute(requestStub)
}
}

@Test
fun `업로드되지 않은 사진 경로`() {
// given
given(checkFilePort.existsPath(requestStub.profileImagePath))
.willReturn(false)

// when & then
assertThrows<NotFoundFilePathException> {
changeProfileImageUseCase.execute(requestStub)
}
}

@Test
fun `유저를 찾을 수 없음`() {
// given
given(checkFilePort.existsPath(requestStub.profileImagePath))
.willReturn(true)

given(userSecurityPort.getCurrentUserId())
.willReturn(id)

given(queryUserPort.queryUserById(id))
.willReturn(null)

// when & then
assertThrows<UserNotFoundException> {
changeProfileImageUseCase.execute(requestStub)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ enum class FileErrorCode(

INVALID_EXTENSION(400, "제한된 확장자(jpg, jpeg, png)"),

NOT_FOUND_FILE_PATH(404, "업로드되지 않은 파일 경로"),

IO_INTERRUPTED(500, "파일 입출력 처리 중단");

override fun status(): Int = status
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package team.comit.simtong.domain.file.exception

import team.comit.simtong.domain.file.error.FileErrorCode
import team.comit.simtong.global.error.BusinessException

class NotFoundFilePathException private constructor() : BusinessException(FileErrorCode.NOT_FOUND_FILE_PATH) {

companion object {
@JvmField
val EXCEPTION = NotFoundFilePathException()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class SecurityConfig(
.antMatchers(HttpMethod.POST, "/users/tokens").permitAll()
.antMatchers(HttpMethod.GET, "/users/information").hasAnyRole(Authority.ROLE_COMMON.name)
.antMatchers(HttpMethod.PUT, "/users/password/initialization").hasAnyRole(Authority.ROLE_COMMON.name)
.antMatchers(HttpMethod.PUT, "/users/profile-image").hasAnyRole(Authority.ROLE_COMMON.name)
.antMatchers(HttpMethod.PUT, "/users/nickname").hasAnyRole(Authority.ROLE_COMMON.name)
.antMatchers(HttpMethod.PUT, "/users/email").hasAnyRole(Authority.ROLE_COMMON.name)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import com.amazonaws.services.s3.model.ObjectMetadata
import com.amazonaws.services.s3.model.PutObjectRequest
import org.springframework.stereotype.Component
import team.comit.simtong.domain.file.exception.FileIOInterruptedException
import team.comit.simtong.domain.file.spi.ManageFilePort
import team.comit.simtong.domain.file.spi.CheckFilePort
import team.comit.simtong.domain.file.spi.UploadFilePort
import java.io.File
import java.io.IOException

Expand All @@ -23,7 +24,7 @@ import java.io.IOException
class AwsS3Adapter(
private val awsProperties: AwsS3Properties,
private val amazonS3Client: AmazonS3Client
): ManageFilePort {
): UploadFilePort, CheckFilePort {

override fun upload(file: File): String {
inputS3(file, file.name)
Expand Down Expand Up @@ -57,4 +58,8 @@ class AwsS3Adapter(
return amazonS3Client.getResourceUrl(awsProperties.bucket, fileName)
}

override fun existsPath(path: String): Boolean {
return amazonS3Client.doesObjectExist(awsProperties.bucket, path.substringAfterLast('/', ""))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package team.comit.simtong.thirdparty.storage

import com.amazonaws.services.s3.AmazonS3Client
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
Expand Down Expand Up @@ -48,23 +50,32 @@ class AwsS3AdapterTests {

@Test
fun `단일 파일 업로드`() {
// given
val file = createFile("test.png")

// when
val result = awsS3Adapter.upload(createFile("test.png"))
val result = awsS3Adapter.upload(file)

// then
assertThat(result).contains(awsS3Properties.bucket)
}

@Test
fun `다중 파일 업로드`() {
// given
val files = listOf(
createFile("test.jpg"),
createFile("test.jpeg"),
createFile("test.png")
)

// when
val result = awsS3Adapter.upload(listOf(
createFile("test.jpg"),
createFile("test.jpeg"),
createFile("test.png")))
val result = awsS3Adapter.upload(files)

// then
result.forEach{ assertThat(it).contains(awsS3Properties.bucket) }
result.forEach{
assertThat(it).contains(awsS3Properties.bucket)
}
}

@Test
Expand All @@ -78,4 +89,20 @@ class AwsS3AdapterTests {
}
}

@Test
fun `파일 경로 검사`() {
//given
val file = createFile("test.png")

// when
awsS3Adapter.upload(file)

val correct = awsS3Adapter.existsPath("/test.png")
val wrong = awsS3Adapter.existsPath("/test.svg")

// then
assertTrue(correct)
assertFalse(wrong)
}

}
Loading

0 comments on commit f07a5d8

Please sign in to comment.