Skip to content

Commit

Permalink
feat: 회원 탈퇴 기능 구현 (#335)
Browse files Browse the repository at this point in the history
* feat: 서버와 회원 탈퇴 통신을 해주는 service 추가

* feat: 카카오 sdk의 unlink 메서드 추가

* feat: 회원 탈퇴 기능 추기

* feat: 회원탈퇴 버튼 클릭 시 회원 탈퇴가 되도록 하는 기능 구현

* feat: Service의 API 주소 수정

* refactor: Service의 반환 값 수정

* feat: 로그 수정

* refactor: ktlint 수정

* refactor: 메서드 반환 값이 non-nullable 하도록 수정

* refactor: 변수명 변경

* refactor: 에러 코드 상수화

* refactor: 회원 탈퇴 repository 메서드 내 runCatching 삭제

* feat: 회원 탈퇴 후 로그인 창으로 이동 시 백 스택에 쌓인 뷰를 리셋해주는 기능 구현

* feat: 회원 탈퇴 다이얼로그 생성
  • Loading branch information
hyunji1203 authored Sep 16, 2023
1 parent 9b9017e commit 1f9031a
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import com.now.naaga.data.remote.dto.NaagaAuthDto
import com.now.naaga.data.remote.dto.PlatformAuthDto
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.POST

interface AuthService {
@POST("/auth")
suspend fun requestAuth(
@Body platformAuthDto: PlatformAuthDto,
): Response<NaagaAuthDto>

@DELETE("/auth/unlink")
suspend fun withdrawalMember(): Response<Unit>
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import com.now.naaga.data.local.AuthDataSource
import com.now.naaga.data.mapper.toDto
import com.now.naaga.data.remote.retrofit.ServicePool.authService
import com.now.naaga.util.getValueOrThrow
import com.now.naaga.util.unlinkWithKakao
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class DefaultAuthRepository(
private val authDataSource: AuthDataSource,
private val dispatcher: CoroutineDispatcher = Dispatchers.IO
private val dispatcher: CoroutineDispatcher = Dispatchers.IO,
) : AuthRepository {

override suspend fun getToken(platformAuth: PlatformAuth): Boolean {
Expand All @@ -27,4 +28,9 @@ class DefaultAuthRepository(
return@withContext false
}
}

override suspend fun withdrawalMember() {
authService.withdrawalMember()
unlinkWithKakao()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.now.naaga.presentation.login

import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
Expand Down Expand Up @@ -75,5 +77,12 @@ class LoginActivity : AppCompatActivity(), AnalyticsDelegate by DefaultAnalytics
fun getIntent(context: Context): Intent {
return Intent(context, LoginActivity::class.java)
}

fun getIntentWithTop(context: Context): Intent {
return Intent(context, LoginActivity::class.java).apply {
addFlags(FLAG_ACTIVITY_NEW_TASK)
addFlags(FLAG_ACTIVITY_CLEAR_TASK)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ package com.now.naaga.presentation.setting
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import com.now.naaga.R
import com.now.naaga.data.throwable.DataThrowable
import com.now.naaga.databinding.ActivitySettingBinding
import com.now.naaga.presentation.login.LoginActivity
import com.now.naaga.presentation.onadventure.NaagaAlertDialog

class SettingActivity : AppCompatActivity() {
private lateinit var binding: ActivitySettingBinding
Expand All @@ -17,6 +22,7 @@ class SettingActivity : AppCompatActivity() {
setContentView(binding.root)
initViewModel()
setClickListeners()
subscribe()
}

private fun initViewModel() {
Expand All @@ -28,9 +34,54 @@ class SettingActivity : AppCompatActivity() {
binding.ivSettingBack.setOnClickListener {
finish()
}

binding.tvSettingUnlink.setOnClickListener {
showWithdrawalDialog()
}
}

private fun subscribe() {
viewModel.withdrawalStatus.observe(this) { status ->
if (status == true) {
shortToast(getString(R.string.setting_withdrawal_success_message))
navigateLogin()
}
}

viewModel.errorMessage.observe(this) { error: DataThrowable ->
when (error.code) {
WRONG_AUTH_ERROR_CODE -> shortToast(getString(R.string.setting_wrong_error_message))
EXPIRATION_AUTH_ERROR_CODE -> shortToast(getString(R.string.setting_expiration_error_message))
}
}
}

private fun navigateLogin() {
startActivity(LoginActivity.getIntentWithTop(this))
finish()
}

private fun shortToast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

private fun showWithdrawalDialog() {
NaagaAlertDialog.Builder().build(
title = getString(R.string.withdrawal_dialog_title),
description = getString(R.string.withdrawal_dialog_description),
positiveText = getString(R.string.withdrawal_dialog_negative),
negativeText = getString(R.string.withdrawal_dialog_positive),
positiveAction = { },
negativeAction = { viewModel.withdrawalMember() },
).show(supportFragmentManager, WITHDRAWAL)
}

companion object {
private const val WITHDRAWAL = "WITHDRAWAL"

private const val WRONG_AUTH_ERROR_CODE = 101
private const val EXPIRATION_AUTH_ERROR_CODE = 102

fun getIntent(context: Context): Intent {
return Intent(context, SettingActivity::class.java)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@
package com.now.naaga.presentation.setting

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.now.domain.repository.AuthRepository
import com.now.naaga.NaagaApplication.DependencyContainer.authDataSource
import com.now.naaga.data.repository.DefaultAuthRepository
import com.now.naaga.data.throwable.DataThrowable
import kotlinx.coroutines.launch

class SettingViewModel(private val authRepository: AuthRepository) : ViewModel() {

private val _withdrawalStatus = MutableLiveData<Boolean>()
val withdrawalStatus: LiveData<Boolean> = _withdrawalStatus

private val _errorMessage = MutableLiveData<DataThrowable>()
val errorMessage: LiveData<DataThrowable> = _errorMessage

fun withdrawalMember() {
viewModelScope.launch {
runCatching { authRepository.withdrawalMember() }
.onSuccess { _withdrawalStatus.value = true }
.onFailure { _errorMessage.value = it as DataThrowable }
}
}

companion object {
val Factory = SettingFactory(DefaultAuthRepository(authDataSource))

Expand Down
14 changes: 13 additions & 1 deletion android/app/src/main/java/com/now/naaga/util/KakaoLoginUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import com.kakao.sdk.common.model.ClientError
import com.kakao.sdk.common.model.ClientErrorCause
import com.kakao.sdk.user.UserApiClient

private const val KAKAO_LOGIN_LOG_TAG = "kakao login"
const val KAKAO_LOGIN_LOG_TAG = "kakao login"
private const val KAKAO_LOGIN_FAIL_MESSAGE = "카카오계정으로 로그인 실패"
private const val KAKAO_LOGIN_SUCCESS_MESSAGE = "카카오계정으로 로그인 성공"
private const val KAKAO_UNLINK_FAIL_MESSAGE = "연결 끊기 실패"
private const val KAKAO_UNLINK_SUCCESS_MESSAGE = "연결 끊기 성공. SDK에서 토큰 삭제 됨"

private fun getLoginCallback(doNextAction: (token: String) -> Unit): (OAuthToken?, Throwable?) -> Unit {
val callback: (OAuthToken?, Throwable?) -> Unit = { token, error ->
Expand Down Expand Up @@ -50,3 +52,13 @@ fun loginWithKakao(context: Context, doNextAction: (token: String) -> Unit) {
UserApiClient.instance.loginWithKakaoAccount(context, callback = callback)
}
}

fun unlinkWithKakao() {
UserApiClient.instance.unlink { error ->
if (error != null) {
Log.e(KAKAO_LOGIN_LOG_TAG, KAKAO_UNLINK_FAIL_MESSAGE, error)
} else {
Log.i(KAKAO_LOGIN_LOG_TAG, KAKAO_UNLINK_SUCCESS_MESSAGE)
}
}
}
11 changes: 11 additions & 0 deletions android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,15 @@
<string name="upload_error_already_exists_nearby_message">근방에 다른 미션장소가 존재해서 추가할 수 없어요!</string>
<string name="upload_error_post_message">전송에 실패했어요! 다시 시도해주세요!</string>
<string name="upload_error_insufficient_info_message">모든 정보를 입력해주세요.</string>

<!-- SettingActivity -->
<string name="setting_withdrawal_success_message">"성공적으로 회원 탈퇴 되었습니다."</string>
<string name="setting_wrong_error_message">"인증 정보가 잘 못 되었어요!"</string>
<string name="setting_expiration_error_message">"인증 정보가 만료 되었어요!"</string>

<!-- Withdrawal Dialog -->
<string name="withdrawal_dialog_title">정말 회원 탈퇴를 하시겠습니까?</string>
<string name="withdrawal_dialog_description">나아가와 함께 즐거운 모험을 계속해보세요!</string>
<string name="withdrawal_dialog_positive">네</string>
<string name="withdrawal_dialog_negative">아니요</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ interface AuthRepository {
suspend fun getToken(
platformAuth: PlatformAuth,
): Boolean

suspend fun withdrawalMember()
}

0 comments on commit 1f9031a

Please sign in to comment.