-
Notifications
You must be signed in to change notification settings - Fork 0
[GMSS-136][GMSS-102] feat: 사용자 정보 조회 및 닉네임 변경·회원 탈퇴 기능 구현 #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
38f3e77
feat: 사용자 설정 기능제공 setting 모듈 생성
seunghee17 55fc686
feat: 사용자 정보 조회, 닉네임 업데이트, 회원 탈퇴 수행하는 설정기능 구현
seunghee17 de7de5a
feat: 홈 화면에 설정 화면 진입점 추가 및 GetUserInfoUseCase, UserInfo data class 누락…
seunghee17 40fa263
feat: 닉네임 업데이트시 예외 처리 추가
seunghee17 263b3ef
feat: 닉네임 길이에 따른 조건 추가
seunghee17 e7c2b40
feat: 사용자 정보 조회 및 설정 기능 리팩토링
seunghee17 4702521
fix: 사용자 정보 조회 응답값 일부 nullable로 변환
seunghee17 8abd494
fix: 닉네임 검증 예외 분리 및 설정 액션 중복 요청 방어
seunghee17 8d9ab58
fix: 불필요 종속성 삭제
seunghee17 61fa157
feat: 탈퇴 관련 클래스 및 메소드 명칭 deleteUserAccount로 변경
seunghee17 46d15ea
fix: 탈퇴 성공 시 로그아웃 실패와 무관하게 성공 반환하도록 수정
seunghee17 2b258dc
fix: UserInfoResponse default value Null로 수정
seunghee17 7dcd20b
fix: NicknameUpdateException에 원인 예외 보존
seunghee17 c41c7d9
refactor: 설정 화면 UI와 도메인 계층 결합도 낮추기
seunghee17 ee8d358
chore: 정렬 수정
seunghee17 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
22 changes: 22 additions & 0 deletions
22
data/src/main/java/com/gamss/android/data/remote/user/model/response/UserInfoResponse.kt
This file contains hidden or 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,22 @@ | ||
| package com.gamss.android.data.remote.user.model.response | ||
|
|
||
| import com.gamss.android.domain.user.UserProfile | ||
| import kotlinx.serialization.Serializable | ||
|
|
||
| @Serializable | ||
| internal data class UserInfoResponse( | ||
| val id: Long, | ||
| val email: String? = null, | ||
| val nickname: String? = null, | ||
| val status: String? = null, | ||
| val createdAt: String? = null, | ||
| ) | ||
|
|
||
| internal fun UserInfoResponse.toDomain(): UserProfile = | ||
| UserProfile( | ||
| id = id, | ||
| email = email, | ||
| nickname = nickname, | ||
| status = status, | ||
| createdAt = createdAt, | ||
| ) |
This file contains hidden or 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
119 changes: 119 additions & 0 deletions
119
data/src/test/java/com/gamss/android/data/repository/UserRepositoryImplTest.kt
This file contains hidden or 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,119 @@ | ||
| package com.gamss.android.data.repository | ||
|
|
||
| import com.gamss.android.core.common.AppResult | ||
| import com.gamss.android.core.common.network.ApiException | ||
| import com.gamss.android.data.remote.model.response.ApiResponse | ||
| import com.gamss.android.data.remote.user.UserService | ||
| import com.gamss.android.data.remote.user.model.request.UpdateNicknameRequest | ||
| import com.gamss.android.data.remote.user.model.response.UserInfoResponse | ||
| import com.gamss.android.domain.user.NicknameUpdateException | ||
| import io.mockk.coEvery | ||
| import io.mockk.coVerify | ||
| import io.mockk.mockk | ||
| import kotlinx.coroutines.CancellationException | ||
| import kotlinx.coroutines.test.runTest | ||
| import okhttp3.MediaType.Companion.toMediaType | ||
| import okhttp3.ResponseBody.Companion.toResponseBody | ||
| import org.junit.Assert.assertEquals | ||
| import org.junit.Assert.assertSame | ||
| import org.junit.Assert.assertTrue | ||
| import org.junit.Test | ||
| import retrofit2.HttpException | ||
| import retrofit2.Response | ||
| import java.io.IOException | ||
|
|
||
| class UserRepositoryImplTest { | ||
|
|
||
| private val userService: UserService = mockk() | ||
| private val repository = UserRepositoryImpl(userService) | ||
|
|
||
| @Test | ||
| fun `닉네임 변경 성공 응답을 사용자 프로필로 변환한다`() = runTest { | ||
| coEvery { | ||
| userService.updateNickname(UpdateNicknameRequest(nickname = "새닉네임")) | ||
| } returns ApiResponse( | ||
| success = true, | ||
| data = userInfoResponse(nickname = "새닉네임"), | ||
| ) | ||
|
|
||
| val result = repository.updateNickname("새닉네임") | ||
|
|
||
| val profile = (result as AppResult.Success).data | ||
| assertEquals(1L, profile.id) | ||
| assertEquals("user@gamss.com", profile.email) | ||
| assertEquals("새닉네임", profile.nickname) | ||
| assertEquals("ACTIVE", profile.status) | ||
| assertEquals("2026-08-05T00:00:00Z", profile.createdAt) | ||
| coVerify(exactly = 1) { | ||
| userService.updateNickname(UpdateNicknameRequest(nickname = "새닉네임")) | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
| fun `서버의 잘못된 입력 코드를 닉네임 누락 실패로 변환한다`() = runTest { | ||
| coEvery { userService.updateNickname(any()) } throws httpException("INVALID_INPUT") | ||
|
|
||
| val result = repository.updateNickname("감쓰") | ||
|
|
||
| assertTrue((result as AppResult.Failure).throwable is NicknameUpdateException.MissingNickname) | ||
| } | ||
|
|
||
| @Test | ||
| fun `서버의 잘못된 닉네임 코드를 유효하지 않은 닉네임 실패로 변환한다`() = runTest { | ||
| coEvery { userService.updateNickname(any()) } throws httpException("INVALID_NICKNAME") | ||
|
|
||
| val result = repository.updateNickname("금칙어") | ||
|
|
||
| assertTrue((result as AppResult.Failure).throwable is NicknameUpdateException.InvalidNickname) | ||
| } | ||
|
|
||
| @Test | ||
| fun `알 수 없는 서버 오류 코드는 HTTP 실패로 유지한다`() = runTest { | ||
| coEvery { userService.updateNickname(any()) } throws httpException("UNKNOWN_ERROR") | ||
|
|
||
| val result = repository.updateNickname("감쓰") | ||
|
|
||
| val throwable = (result as AppResult.Failure).throwable | ||
| assertTrue(throwable is ApiException.Http) | ||
| assertEquals("UNKNOWN_ERROR", (throwable as ApiException.Http).code) | ||
| } | ||
|
|
||
| @Test | ||
| fun `네트워크 오류는 네트워크 실패로 유지한다`() = runTest { | ||
| val cause = IOException("offline") | ||
| coEvery { userService.updateNickname(any()) } throws cause | ||
|
|
||
| val result = repository.updateNickname("감쓰") | ||
|
|
||
| val throwable = (result as AppResult.Failure).throwable | ||
| assertTrue(throwable is ApiException.Network) | ||
| assertSame(cause, throwable.cause) | ||
| } | ||
|
|
||
| @Test(expected = CancellationException::class) | ||
| fun `닉네임 변경 취소는 실패로 변환하지 않고 전파한다`() = runTest { | ||
| coEvery { userService.updateNickname(any()) } throws CancellationException() | ||
|
|
||
| repository.updateNickname("감쓰") | ||
| } | ||
|
|
||
| private fun httpException(code: String): HttpException { | ||
| val errorBody = """{"success":false,"error":{"code":"$code","message":"failed"}}""" | ||
| .toResponseBody("application/json".toMediaType()) | ||
| return HttpException( | ||
| Response.error<ApiResponse<UserInfoResponse>>(BAD_REQUEST, errorBody), | ||
| ) | ||
| } | ||
|
|
||
| private fun userInfoResponse(nickname: String) = UserInfoResponse( | ||
| id = 1L, | ||
| email = "user@gamss.com", | ||
| nickname = nickname, | ||
| status = "ACTIVE", | ||
| createdAt = "2026-08-05T00:00:00Z", | ||
| ) | ||
|
|
||
| private companion object { | ||
| const val BAD_REQUEST = 400 | ||
| } | ||
| } |
9 changes: 0 additions & 9 deletions
9
domain/src/main/kotlin/com/gamss/android/domain/repository/UserRepository.kt
This file was deleted.
Oops, something went wrong.
19 changes: 0 additions & 19 deletions
19
domain/src/main/kotlin/com/gamss/android/domain/usecase/SecessionUseCase.kt
This file was deleted.
Oops, something went wrong.
13 changes: 0 additions & 13 deletions
13
domain/src/main/kotlin/com/gamss/android/domain/usecase/UpdateNicknameUseCase.kt
This file was deleted.
Oops, something went wrong.
18 changes: 18 additions & 0 deletions
18
domain/src/main/kotlin/com/gamss/android/domain/user/DeleteUserAccountUseCase.kt
This file contains hidden or 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,18 @@ | ||
| package com.gamss.android.domain.user | ||
|
|
||
| import com.gamss.android.core.common.AppResult | ||
| import com.gamss.android.domain.repository.AuthRepository | ||
| import com.gamss.android.domain.usecase.NoParamUseCase | ||
| import javax.inject.Inject | ||
|
|
||
| class DeleteUserAccountUseCase @Inject constructor( | ||
| private val userRepository: UserRepository, | ||
| private val authRepository: AuthRepository, | ||
| ) : NoParamUseCase<AppResult<Unit>> { | ||
| override suspend fun invoke(): AppResult<Unit> { | ||
| val deleteResult = userRepository.deleteUserAccount() | ||
| if (deleteResult is AppResult.Failure) return deleteResult | ||
| authRepository.logout() | ||
| return AppResult.Success(Unit) | ||
| } | ||
| } |
11 changes: 11 additions & 0 deletions
11
domain/src/main/kotlin/com/gamss/android/domain/user/GetUserInfoUseCase.kt
This file contains hidden or 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,11 @@ | ||
| package com.gamss.android.domain.user | ||
|
|
||
| import com.gamss.android.core.common.AppResult | ||
| import com.gamss.android.domain.usecase.NoParamUseCase | ||
| import javax.inject.Inject | ||
|
|
||
| class GetUserInfoUseCase @Inject constructor( | ||
| private val userRepository: UserRepository, | ||
| ) : NoParamUseCase<AppResult<UserProfile>> { | ||
| override suspend fun invoke(): AppResult<UserProfile> = userRepository.getUserInfo() | ||
| } |
10 changes: 10 additions & 0 deletions
10
domain/src/main/kotlin/com/gamss/android/domain/user/NicknamePolicy.kt
This file contains hidden or 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,10 @@ | ||
| package com.gamss.android.domain.user | ||
|
github-advanced-security[bot] marked this conversation as resolved.
Fixed
|
||
|
|
||
| /** | ||
| * 닉네임 검증 규칙. UseCase와 UI가 함께 참조할 수 있도록 | ||
| * UpdateNicknameUseCase가 아닌 별도 객체로 분리해 둔다. | ||
| */ | ||
| object NicknamePolicy { | ||
| const val MIN_LENGTH = 2 | ||
| const val MAX_LENGTH = 20 | ||
| } | ||
7 changes: 7 additions & 0 deletions
7
domain/src/main/kotlin/com/gamss/android/domain/user/NicknameUpdateException.kt
This file contains hidden or 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,7 @@ | ||
| package com.gamss.android.domain.user | ||
|
|
||
| sealed class NicknameUpdateException(cause: Throwable? = null) : RuntimeException(cause) { | ||
| class MissingNickname(cause: Throwable? = null) : NicknameUpdateException(cause) | ||
| class InvalidLength(cause: Throwable? = null) : NicknameUpdateException(cause) | ||
| class InvalidNickname(cause: Throwable? = null) : NicknameUpdateException(cause) | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.