Skip to content
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

feat: 회원 탈퇴 기능 구현 #335

Merged
merged 14 commits into from
Sep 16, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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
@@ -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 {
@@ -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
@@ -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
@@ -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
@@ -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
@@ -17,6 +22,7 @@ class SettingActivity : AppCompatActivity() {
setContentView(binding.root)
initViewModel()
setClickListeners()
subscribe()
}

private fun initViewModel() {
@@ -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()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2]
현재 액티비티를 종료하고 로그인 액티비티로 넘어가게 해두었는데, 아마 디바이스의 뒤로가기를 클릭하면 MyPage가 나올 것 같아요.
만약 그렇다면 수정이 필요해보입니다!
실제로 확인해보지는 못해서 이따가 한번 더 확인해보도록 하겠습니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1]
확인해보았는데 회원탈퇴가 성공적으로 진행된 뒤에 로그인 액티비티로 넘어가지만 디바이스의 뒤로가기를 크릭하면 MyPage가 나옵니다. 이 부분은 수정이 필요할 것 같아요.

Copy link
Collaborator Author

@hyunji1203 hyunji1203 Sep 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵! 크롱 리뷰를 하면서 백스택에 쌓인 액티비티를 리셋해주고 원하는 액티비티를 띄우게 해주는 로직을 보고, 해당 로직 회원 탈퇴에도 적용시켰습니다!
크롱 덕에 빨리 키워드를 찾아 공부하고 수정할 수 있었네요ㅎㅎ 잘 배워갑니다!!!!

}
}

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)
}
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))

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
@@ -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 ->
@@ -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
@@ -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
@@ -6,4 +6,6 @@ interface AuthRepository {
suspend fun getToken(
platformAuth: PlatformAuth,
): Boolean

suspend fun withdrawalMember()
}