From f7f5200b3f8f78e7ce68f6814958af09095f53a8 Mon Sep 17 00:00:00 2001 From: Dongmin Date: Wed, 10 Jan 2024 21:11:15 +0900 Subject: [PATCH 1/8] =?UTF-8?q?[CHORE/#64]=20=EC=A4=84=EB=B0=94=EA=BF=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/going/doorip/di/AuthInterceptor.kt | 1 + app/src/main/java/com/going/doorip/di/RetrofitModule.kt | 3 +-- .../main/kotlin/com/going/domain/repository/TokenRepository.kt | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/going/doorip/di/AuthInterceptor.kt b/app/src/main/java/com/going/doorip/di/AuthInterceptor.kt index fe73f8b8..4d4eff11 100644 --- a/app/src/main/java/com/going/doorip/di/AuthInterceptor.kt +++ b/app/src/main/java/com/going/doorip/di/AuthInterceptor.kt @@ -19,6 +19,7 @@ class AuthInterceptor @Inject constructor( private val dataStore: GoingDataStore, @ApplicationContext private val context: Context, ) : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() diff --git a/app/src/main/java/com/going/doorip/di/RetrofitModule.kt b/app/src/main/java/com/going/doorip/di/RetrofitModule.kt index 435739aa..6ef017de 100644 --- a/app/src/main/java/com/going/doorip/di/RetrofitModule.kt +++ b/app/src/main/java/com/going/doorip/di/RetrofitModule.kt @@ -1,8 +1,7 @@ package com.going.doorip.di import com.going.doorip.BuildConfig.BASE_URL -import com.going.going.di.AuthInterceptor -import com.going.going.di.qualifier.JWT +import com.going.doorip.di.qualifier.JWT import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import dagger.Module import dagger.Provides diff --git a/domain/src/main/kotlin/com/going/domain/repository/TokenRepository.kt b/domain/src/main/kotlin/com/going/domain/repository/TokenRepository.kt index 45d8a7be..1a069869 100644 --- a/domain/src/main/kotlin/com/going/domain/repository/TokenRepository.kt +++ b/domain/src/main/kotlin/com/going/domain/repository/TokenRepository.kt @@ -6,5 +6,6 @@ interface TokenRepository { fun getRefreshToken(): String fun setTokens(accessToken: String, refreshToken: String) + fun clearTokens() } From b24e92fdbb1cd3f878fd0e8df7cdd9ba674683e7 Mon Sep 17 00:00:00 2001 From: Dongmin Date: Wed, 10 Jan 2024 21:11:48 +0900 Subject: [PATCH 2/8] =?UTF-8?q?[CHORE/#64]=20=EB=B0=91=EC=A4=84=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- presentation/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 530d9ad8..ca66fd7e 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -12,7 +12,7 @@ 해당 기능은 추후 업데이트 예정이에요 :) 여행을 시작해보세요 - 개인정보처리방침 + 개인정보처리방침 %1$d/%2$d From 8305a4dbdf2b35a541ade7972458508683225496 Mon Sep 17 00:00:00 2001 From: Dongmin Date: Wed, 10 Jan 2024 22:32:35 +0900 Subject: [PATCH 3/8] =?UTF-8?q?[CHORE/#64]=20error=20code=20=ED=8C=8C?= =?UTF-8?q?=EC=8B=B1=20=ED=95=A8=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onboarding/splash/SplashViewModel.kt | 2 -- .../java/com/going/presentation/util/JsonExt.kt | 14 ++++++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashViewModel.kt b/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashViewModel.kt index fae8ed79..4858299c 100644 --- a/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashViewModel.kt +++ b/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashViewModel.kt @@ -10,6 +10,4 @@ class SplashViewModel @Inject constructor( private val tokenRepository: TokenRepository, ) : ViewModel() { fun getHasAccessToken(): Boolean = tokenRepository.getAccessToken().isNotBlank() - - fun clearTokens() = tokenRepository.clearTokens() } diff --git a/presentation/src/main/java/com/going/presentation/util/JsonExt.kt b/presentation/src/main/java/com/going/presentation/util/JsonExt.kt index 65e7d6b6..bf9a160e 100644 --- a/presentation/src/main/java/com/going/presentation/util/JsonExt.kt +++ b/presentation/src/main/java/com/going/presentation/util/JsonExt.kt @@ -1,17 +1,15 @@ package com.going.presentation.util -import android.util.Log -import org.json.JSONObject import retrofit2.HttpException fun toErrorCode(throwable: Throwable): String = if (throwable is HttpException) { val jsonTemp = throwable.response()?.errorBody()?.byteString().toString() - Log.e("TAG", "toErrorCode: $jsonTemp", ) - val json = jsonTemp.slice(6 until jsonTemp.length - 2) + "}" - Log.e("TAG", "toErrorCode: $json", ) - JSONObject(json).getString("code") + val codeIndex = jsonTemp.indexOf("code") + var errorCode = jsonTemp.slice(codeIndex + 7..codeIndex + 12) + + if (errorCode.endsWith('\"')) errorCode = errorCode.slice(0 until errorCode.length - 1) + + errorCode } else { "NOT_HTTP" } - -// 기능 오류 발견!!!! 반드시 수정 필요!!!!!! From 3c90e6e1a38e5cfdb3b6fcb4ae834840915200f4 Mon Sep 17 00:00:00 2001 From: Dongmin Date: Wed, 10 Jan 2024 22:42:24 +0900 Subject: [PATCH 4/8] =?UTF-8?q?[CHORE/#64]=20=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?=EB=B6=84=EA=B8=B0=EC=B2=98=EB=A6=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/going/presentation/onboarding/signin/SignInActivity.kt | 3 ++- .../com/going/presentation/onboarding/splash/SplashActivity.kt | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/presentation/src/main/java/com/going/presentation/onboarding/signin/SignInActivity.kt b/presentation/src/main/java/com/going/presentation/onboarding/signin/SignInActivity.kt index 40de59c6..1aa7b4be 100644 --- a/presentation/src/main/java/com/going/presentation/onboarding/signin/SignInActivity.kt +++ b/presentation/src/main/java/com/going/presentation/onboarding/signin/SignInActivity.kt @@ -10,6 +10,7 @@ import com.going.presentation.R import com.going.presentation.databinding.ActivitySigninBinding import com.going.presentation.onboarding.signup.OnboardingProfileSettingActivity import com.going.presentation.tendencytest.TendencyTestActivity +import com.going.presentation.tendencytest.TendencyTestSplashActivity import com.going.ui.base.BaseActivity import com.going.ui.extension.setOnSingleClickListener import com.going.ui.extension.toast @@ -84,7 +85,7 @@ class SignInActivity : BaseActivity(R.layout.activity_sig } private fun navigateToTendencyScreen() { - Intent(this, TendencyTestActivity::class.java).apply { + Intent(this, TendencyTestSplashActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) startActivity(this) } diff --git a/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashActivity.kt b/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashActivity.kt index 31f83c8d..0f77897d 100644 --- a/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashActivity.kt +++ b/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashActivity.kt @@ -35,6 +35,7 @@ class SplashActivity : BaseActivity(R.layout.activity_spl if (viewModel.getHasAccessToken()) { navigateToMainScreen() } else { + // api 호출로 변경 예정 navigateToSignInScreen() } }, 3000) From 78b5dfa03b270b73b75c393636c9666485877677 Mon Sep 17 00:00:00 2001 From: Dongmin Date: Thu, 11 Jan 2024 00:06:02 +0900 Subject: [PATCH 5/8] =?UTF-8?q?[CHORE/#64]=20=EC=9D=B8=ED=84=B0=EC=85=89?= =?UTF-8?q?=ED=84=B0=20=EC=B5=9C=EC=A2=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/going/doorip/di/AuthInterceptor.kt | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/going/doorip/di/AuthInterceptor.kt b/app/src/main/java/com/going/doorip/di/AuthInterceptor.kt index 4d4eff11..0e384816 100644 --- a/app/src/main/java/com/going/doorip/di/AuthInterceptor.kt +++ b/app/src/main/java/com/going/doorip/di/AuthInterceptor.kt @@ -1,11 +1,9 @@ package com.going.doorip.di -import android.content.Context import com.going.data.dto.BaseResponse -import com.going.data.local.GoingDataStore import com.going.domain.entity.response.AuthTokenModel +import com.going.domain.repository.TokenRepository import com.going.doorip.BuildConfig.BASE_URL -import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.serialization.json.Json import okhttp3.Interceptor import okhttp3.Request @@ -16,16 +14,17 @@ import javax.inject.Inject class AuthInterceptor @Inject constructor( private val json: Json, - private val dataStore: GoingDataStore, - @ApplicationContext private val context: Context, + private val tokenRepository: TokenRepository, ) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() - Timber.d("GET ACCESS TOKEN : ${dataStore.accessToken}") + Timber.d("GET ACCESS TOKEN : ${tokenRepository.getAccessToken()}") - val authRequest = if (dataStore.accessToken.isNotBlank()) { + val authRequest = if (tokenRepository.getAccessToken() + .isNotBlank() + ) { originalRequest.newAuthBuilder().build() } else { originalRequest @@ -35,9 +34,17 @@ class AuthInterceptor @Inject constructor( when (response.code) { CODE_TOKEN_EXPIRED -> { try { + // refreshToken을 얻기 위해서 인터셉터 내부에서 직접적으로 통신을 하는게 맞을까? + // app 레이어에서 data layer에 직접 접근하는 것도 맘에 안들고, 직접 통신하는게 아키텍쳐 구조를 헤친다는 생각이 듦 + // 속도를 측정해보고 repository를 사용한 통신방법이 속도가 느리지 않다면 + // 추후 repository를 활용한 통신으로 수정할 예정 + // 앱잼 기간내에 수정하는게 목표라 주석을 남겨두겠습니다. 수정 못할거 같으면 주석만 지울게용 val refreshTokenRequest = originalRequest.newBuilder().post("".toRequestBody()) .url("$BASE_URL/api/users/reissue") - .addHeader(AUTHORIZATION, dataStore.refreshToken) + .addHeader( + AUTHORIZATION, + tokenRepository.getRefreshToken(), + ) .build() val refreshTokenResponse = chain.proceed(refreshTokenRequest) Timber.d("GET REFRESH TOKEN : $refreshTokenResponse") @@ -47,15 +54,21 @@ class AuthInterceptor @Inject constructor( refreshTokenResponse.body?.string().toString(), ) as BaseResponse - with(dataStore) { - accessToken = responseToken.data.accessToken - refreshToken = responseToken.data.refreshToken - } + tokenRepository.setTokens( + accessToken = responseToken.data.accessToken, + refreshToken = responseToken.data.refreshToken, + ) refreshTokenResponse.close() val newRequest = originalRequest.newAuthBuilder().build() return chain.proceed(newRequest) } + + tokenRepository.clearTokens() + + // refreshToken 만료 처리를 위한 리프레시 토큰 만료 코드 포함 리스폰스 리턴 + return refreshTokenResponse } catch (t: Throwable) { + tokenRepository.clearTokens() Timber.e(t) } } @@ -64,10 +77,11 @@ class AuthInterceptor @Inject constructor( } private fun Request.newAuthBuilder() = - this.newBuilder().addHeader(AUTHORIZATION, "Bearer ${dataStore.accessToken}") + this.newBuilder().addHeader(AUTHORIZATION, "$BEARER ${tokenRepository.getAccessToken()}") companion object { private const val CODE_TOKEN_EXPIRED = 401 + private const val BEARER = "Bearer" private const val AUTHORIZATION = "Authorization" } } From 5d83053ab34e03cc0185a94c1ea098e8668b8972 Mon Sep 17 00:00:00 2001 From: Dongmin Date: Thu, 11 Jan 2024 00:10:25 +0900 Subject: [PATCH 6/8] =?UTF-8?q?[CHORE/#64]=20TendencyTestSplashActivity=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tendencytest/TendencyTestSplashActivity.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/presentation/src/main/java/com/going/presentation/tendencytest/TendencyTestSplashActivity.kt b/presentation/src/main/java/com/going/presentation/tendencytest/TendencyTestSplashActivity.kt index dfe41565..4220002d 100644 --- a/presentation/src/main/java/com/going/presentation/tendencytest/TendencyTestSplashActivity.kt +++ b/presentation/src/main/java/com/going/presentation/tendencytest/TendencyTestSplashActivity.kt @@ -1,5 +1,6 @@ package com.going.presentation.tendencytest +import android.content.Intent import android.os.Bundle import com.going.presentation.R import com.going.presentation.databinding.ActivityTendencyTestSplashBinding @@ -16,7 +17,13 @@ class TendencyTestSplashActivity : private fun initStartBtnClickListener() { binding.btnTendencySplashStart.setOnSingleClickListener { - // 페이지 이동~ + navigateToTendencyTestScreen() + } + } + + private fun navigateToTendencyTestScreen() { + Intent(this, TendencyTestActivity::class.java).apply { + startActivity(this) } } } From 3f5c1df4613bd2fd59d291fe2f5684d713181fa3 Mon Sep 17 00:00:00 2001 From: Dongmin Date: Thu, 11 Jan 2024 01:10:41 +0900 Subject: [PATCH 7/8] =?UTF-8?q?[CHORE/#64]=20StringExt=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/going/doorip/di/RetrofitModule.kt | 5 ++--- core-ui/src/main/java/com/going/ui/extension/StringExt.kt | 5 +++++ 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 core-ui/src/main/java/com/going/ui/extension/StringExt.kt diff --git a/app/src/main/java/com/going/doorip/di/RetrofitModule.kt b/app/src/main/java/com/going/doorip/di/RetrofitModule.kt index 6ef017de..22d2396e 100644 --- a/app/src/main/java/com/going/doorip/di/RetrofitModule.kt +++ b/app/src/main/java/com/going/doorip/di/RetrofitModule.kt @@ -2,6 +2,8 @@ package com.going.doorip.di import com.going.doorip.BuildConfig.BASE_URL import com.going.doorip.di.qualifier.JWT +import com.going.ui.extension.isJsonArray +import com.going.ui.extension.isJsonObject import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import dagger.Module import dagger.Provides @@ -79,6 +81,3 @@ object RetrofitModule { .addConverterFactory(factory) .build() } - -fun String?.isJsonObject(): Boolean = this?.startsWith("{") == true && this.endsWith("}") -fun String?.isJsonArray(): Boolean = this?.startsWith("[") == true && this.endsWith("]") diff --git a/core-ui/src/main/java/com/going/ui/extension/StringExt.kt b/core-ui/src/main/java/com/going/ui/extension/StringExt.kt new file mode 100644 index 00000000..7a01400c --- /dev/null +++ b/core-ui/src/main/java/com/going/ui/extension/StringExt.kt @@ -0,0 +1,5 @@ +package com.going.ui.extension + +fun String?.isJsonObject(): Boolean = this?.startsWith("{") == true && this.endsWith("}") + +fun String?.isJsonArray(): Boolean = this?.startsWith("[") == true && this.endsWith("]") From b4058d0eec9f982398857acef8296e1338a12516 Mon Sep 17 00:00:00 2001 From: Dongmin Date: Thu, 11 Jan 2024 01:49:19 +0900 Subject: [PATCH 8/8] =?UTF-8?q?[REFACTOR/#64]=20AuthInterceptor=20data=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=EB=A1=9C=20=EC=9D=B4=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/going/doorip/di/RetrofitModule.kt | 1 + data/build.gradle.kts | 9 +++- .../data/interceptor}/AuthInterceptor.kt | 45 +++++++++++-------- 3 files changed, 35 insertions(+), 20 deletions(-) rename {app/src/main/java/com/going/doorip/di => data/src/main/java/com/going/data/interceptor}/AuthInterceptor.kt (69%) diff --git a/app/src/main/java/com/going/doorip/di/RetrofitModule.kt b/app/src/main/java/com/going/doorip/di/RetrofitModule.kt index 22d2396e..8d05ffd3 100644 --- a/app/src/main/java/com/going/doorip/di/RetrofitModule.kt +++ b/app/src/main/java/com/going/doorip/di/RetrofitModule.kt @@ -1,5 +1,6 @@ package com.going.doorip.di +import com.going.data.interceptor.AuthInterceptor import com.going.doorip.BuildConfig.BASE_URL import com.going.doorip.di.qualifier.JWT import com.going.ui.extension.isJsonArray diff --git a/data/build.gradle.kts b/data/build.gradle.kts index c9db34c0..deccb206 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -14,6 +14,13 @@ android { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") + + buildConfigField( + "String", + "BASE_URL", + com.android.build.gradle.internal.cxx.configure.gradleLocalProperties(rootDir) + .getProperty("base.url"), + ) } compileOptions { @@ -60,4 +67,4 @@ dependencies { androidTestImplementation(androidTest) androidTestImplementation(espresso) } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/going/doorip/di/AuthInterceptor.kt b/data/src/main/java/com/going/data/interceptor/AuthInterceptor.kt similarity index 69% rename from app/src/main/java/com/going/doorip/di/AuthInterceptor.kt rename to data/src/main/java/com/going/data/interceptor/AuthInterceptor.kt index 0e384816..42bb13c1 100644 --- a/app/src/main/java/com/going/doorip/di/AuthInterceptor.kt +++ b/data/src/main/java/com/going/data/interceptor/AuthInterceptor.kt @@ -1,9 +1,9 @@ -package com.going.doorip.di +package com.going.data.interceptor +import com.going.data.BuildConfig.BASE_URL import com.going.data.dto.BaseResponse +import com.going.data.local.GoingDataStore import com.going.domain.entity.response.AuthTokenModel -import com.going.domain.repository.TokenRepository -import com.going.doorip.BuildConfig.BASE_URL import kotlinx.serialization.json.Json import okhttp3.Interceptor import okhttp3.Request @@ -14,17 +14,15 @@ import javax.inject.Inject class AuthInterceptor @Inject constructor( private val json: Json, - private val tokenRepository: TokenRepository, + private val dataStore: GoingDataStore, ) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() - Timber.d("GET ACCESS TOKEN : ${tokenRepository.getAccessToken()}") + Timber.d("GET ACCESS TOKEN : ${dataStore.accessToken}") - val authRequest = if (tokenRepository.getAccessToken() - .isNotBlank() - ) { + val authRequest = if (dataStore.accessToken.isNotBlank()) { originalRequest.newAuthBuilder().build() } else { originalRequest @@ -35,15 +33,15 @@ class AuthInterceptor @Inject constructor( CODE_TOKEN_EXPIRED -> { try { // refreshToken을 얻기 위해서 인터셉터 내부에서 직접적으로 통신을 하는게 맞을까? - // app 레이어에서 data layer에 직접 접근하는 것도 맘에 안들고, 직접 통신하는게 아키텍쳐 구조를 헤친다는 생각이 듦 - // 속도를 측정해보고 repository를 사용한 통신방법이 속도가 느리지 않다면 - // 추후 repository를 활용한 통신으로 수정할 예정 + // 직접 통신하는게 기존의 통신방법과 차이가 있기 때문에 통일성을 해친다는 생각이 듦 + // 그리고 이렇게 되면 Base Url이 App모듈에도 필요하고, Data모듈에도 필요함 + // 그래서 지금 생각으론 Retrofit 관련 모듈이 data 모듈에 있어야 할 것 같음 // 앱잼 기간내에 수정하는게 목표라 주석을 남겨두겠습니다. 수정 못할거 같으면 주석만 지울게용 val refreshTokenRequest = originalRequest.newBuilder().post("".toRequestBody()) .url("$BASE_URL/api/users/reissue") .addHeader( AUTHORIZATION, - tokenRepository.getRefreshToken(), + dataStore.refreshToken, ) .build() val refreshTokenResponse = chain.proceed(refreshTokenRequest) @@ -54,21 +52,30 @@ class AuthInterceptor @Inject constructor( refreshTokenResponse.body?.string().toString(), ) as BaseResponse - tokenRepository.setTokens( - accessToken = responseToken.data.accessToken, - refreshToken = responseToken.data.refreshToken, - ) + dataStore.apply { + accessToken = responseToken.data.accessToken + refreshToken = responseToken.data.refreshToken + } + refreshTokenResponse.close() + val newRequest = originalRequest.newAuthBuilder().build() return chain.proceed(newRequest) } - tokenRepository.clearTokens() + dataStore.apply { + accessToken = "" + refreshToken = "" + } // refreshToken 만료 처리를 위한 리프레시 토큰 만료 코드 포함 리스폰스 리턴 return refreshTokenResponse } catch (t: Throwable) { - tokenRepository.clearTokens() + dataStore.apply { + accessToken = "" + refreshToken = "" + } + Timber.e(t) } } @@ -77,7 +84,7 @@ class AuthInterceptor @Inject constructor( } private fun Request.newAuthBuilder() = - this.newBuilder().addHeader(AUTHORIZATION, "$BEARER ${tokenRepository.getAccessToken()}") + this.newBuilder().addHeader(AUTHORIZATION, "$BEARER ${dataStore.accessToken}") companion object { private const val CODE_TOKEN_EXPIRED = 401