Skip to content

Commit

Permalink
Merge branch 'develop' into feature/refactor-api-flow-discover-mypage
Browse files Browse the repository at this point in the history
  • Loading branch information
dongx0915 committed Apr 30, 2024
2 parents 09c0633 + 5661733 commit 05fb441
Show file tree
Hide file tree
Showing 11 changed files with 278 additions and 241 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ import com.runnect.runnect.R
import com.runnect.runnect.application.ApiMode
import com.runnect.runnect.application.ApplicationClass
import com.runnect.runnect.application.PreferenceManager
import com.runnect.runnect.data.service.TokenAuthenticator
import com.runnect.runnect.presentation.mypage.setting.accountinfo.MySettingAccountInfoFragment
import com.runnect.runnect.util.custom.toast.RunnectToast
import com.runnect.runnect.util.preference.AuthUtil.getAccessToken
import com.runnect.runnect.util.preference.AuthUtil.getNewToken
import com.runnect.runnect.util.preference.AuthUtil.saveToken
import com.runnect.runnect.util.preference.StatusType.LoginStatus
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
Expand All @@ -44,15 +46,15 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev

private fun initUserInfo() {
val ctx: Context = context ?: return
val accessToken = PreferenceManager.getString(ctx, TokenAuthenticator.TOKEN_KEY_ACCESS) ?: ""
val refreshToken = PreferenceManager.getString(ctx, TokenAuthenticator.TOKEN_KEY_REFRESH) ?: ""
val accessToken = ctx.getAccessToken()
val refreshToken = ctx.getNewToken()

setPreferenceSummary("dev_pref_key_access_token", accessToken)
setPreferenceSummary("dev_pref_key_refresh_token", refreshToken)
}

private fun initApiMode() {
val ctx:Context = context ?: ApplicationClass.appContext
val ctx: Context = context ?: ApplicationClass.appContext
val currentApi = ApiMode.getCurrentApiMode(ctx)

findPreference<ListPreference>("dev_pref_key_api_mode")?.apply {
Expand All @@ -70,10 +72,11 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev

PreferenceManager.apply {
setString(ctx, ApplicationClass.API_MODE, selectItem)
setString(ctx, MySettingAccountInfoFragment.TOKEN_KEY_ACCESS, "none")
setString(ctx, MySettingAccountInfoFragment.TOKEN_KEY_REFRESH, "none")
}

ctx.saveToken(
accessToken = LoginStatus.NONE.value,
refreshToken = LoginStatus.NONE.value
)
destroyApp(ctx)
true
}
Expand All @@ -93,9 +96,15 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev
val naviBarHeight = getNaviBarHeight(windowManager)

with(metrics) {
setPreferenceSummary("dev_pref_display_ratio", "$widthPixels x ${heightPixels + statusBarHeight + naviBarHeight}")
setPreferenceSummary(
"dev_pref_display_ratio",
"$widthPixels x ${heightPixels + statusBarHeight + naviBarHeight}"
)
setPreferenceSummary("dev_pref_display_density", "${densityDpi}dp")
setPreferenceSummary("dev_pref_display_resource_bucket", getDeviceResourseBucket(this))
setPreferenceSummary(
"dev_pref_display_resource_bucket",
getDeviceResourseBucket(this)
)
}
}

Expand All @@ -116,7 +125,8 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev
private fun getStatusBarHeight(windowManager: WindowManager): Int {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val windowMetrics = windowManager.currentWindowMetrics
val insets = windowMetrics.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.statusBars())
val insets =
windowMetrics.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.statusBars())
insets.top
} else {
0
Expand All @@ -126,7 +136,8 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev
private fun getNaviBarHeight(windowManager: WindowManager): Int {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val windowMetrics = windowManager.currentWindowMetrics
val insets = windowMetrics.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars())
val insets =
windowMetrics.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars())
insets.bottom
} else {
0
Expand Down Expand Up @@ -157,7 +168,8 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev

private fun destroyApp(context: Context) {
lifecycleScope.launch(Dispatchers.Main) {
RunnectToast.createToast(context, getString(R.string.dev_mode_require_restart)).show()
RunnectToast.createToast(context, getString(R.string.dev_mode_require_restart))
.show()
delay(3000)

activity?.finishAffinity() //루트액티비티 종료
Expand Down

This file was deleted.

127 changes: 127 additions & 0 deletions app/src/main/java/com/runnect/runnect/data/service/AuthInterceptor.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package com.runnect.runnect.data.service

import android.content.Context
import com.runnect.runnect.application.ApplicationClass
import com.runnect.runnect.data.dto.response.ResponseGetRefreshToken
import com.runnect.runnect.data.dto.response.base.BaseResponse
import com.runnect.runnect.util.preference.AuthUtil.getAccessToken
import com.runnect.runnect.util.preference.AuthUtil.getNewToken
import com.runnect.runnect.util.preference.AuthUtil.saveToken
import com.runnect.runnect.util.preference.StatusType.LoginStatus
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import timber.log.Timber
import javax.inject.Inject

class AuthInterceptor @Inject constructor(
@ApplicationContext private val context: Context,
private val json: Json
) : Interceptor {
// access Header 에 보내고 이때 401(토큰 만료) 뜨면 액세스 재발급 요청
// 재발급 성공 : 저장
// 재발급 실패 : 재 로그인 토스트 메시지 띄우고 preference 빈 값 넣고 로그인 화면 이동
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()

val headerRequest = originalRequest.newAuthTokenBuilder()
.build()

val response = headerRequest.let { chain.proceed(it) }

return if (response.code == CODE_TOKEN_EXPIRED) {
try {
Timber.e("Access Token Expired: getNewAccessToken")
response.close()
handleTokenExpired(chain, originalRequest, headerRequest)
} catch (t: Throwable) {
Timber.e("Exception: ${t.message}")
context.saveToken(
accessToken = LoginStatus.EXPIRED.value,
refreshToken = LoginStatus.EXPIRED.value
)
response
}
} else {
response
}
}

private fun Request.newAuthTokenBuilder(): Request.Builder {
val accessToken = context.getAccessToken()
val refreshToken = context.getNewToken()
return newBuilder().apply {
addHeader(ACCESS_TOKEN, accessToken)
addHeader(REFRESH_TOKEN, refreshToken)
}
}


private fun handleTokenExpired(
chain: Interceptor.Chain,
originalRequest: Request,
headerRequest: Request
): Response {
val refreshTokenResponse = getNewToken(originalRequest, chain)
return if (refreshTokenResponse.isSuccessful) {
handleGetRefreshTokenSuccess(refreshTokenResponse, originalRequest, chain)
} else {
handleGetNewTokenFailure(refreshTokenResponse, headerRequest, chain)
}
}

private fun getNewToken(originalRequest: Request, chain: Interceptor.Chain): Response {
val baseUrl = ApplicationClass.getBaseUrl()
val refreshToken = context.getNewToken()
val refreshTokenRequest = originalRequest.newBuilder().post("".toRequestBody())
.url("$baseUrl/api/auth/getNewToken")
.addHeader(REFRESH_TOKEN, refreshToken)
.build()

return chain.proceed(refreshTokenRequest)
}

private fun handleGetRefreshTokenSuccess(
refreshTokenResponse: Response,
originalRequest: Request,
chain: Interceptor.Chain
): Response {
refreshTokenResponse.use { response ->
val responseToken = json.decodeFromString<BaseResponse<ResponseGetRefreshToken>>(
response.body?.string().orEmpty()
)
responseToken.data?.data?.let {
Timber.e("New Refresh Token Success: ${it.refreshToken}")
context.saveToken(it.accessToken, it.refreshToken)
}
}

val newRequest = originalRequest.newAuthTokenBuilder().build()
return chain.proceed(newRequest)
}

private fun handleGetNewTokenFailure(
refreshTokenResponse: Response,
headerRequest: Request,
chain: Interceptor.Chain
): Response {
Timber.e("New Refresh Token Failure: ${refreshTokenResponse.code}")
context.saveToken(
accessToken = LoginStatus.EXPIRED.value,
refreshToken = LoginStatus.EXPIRED.value
)
return chain.proceed(headerRequest)
}


companion object {
private const val ACCESS_TOKEN = "accessToken"
private const val CODE_TOKEN_EXPIRED = 401
private const val REFRESH_TOKEN = "refreshToken"
}

}

This file was deleted.

Loading

0 comments on commit 05fb441

Please sign in to comment.