Skip to content

Commit

Permalink
Merge branch 'develop' into feature/improve-developer-mode
Browse files Browse the repository at this point in the history
  • Loading branch information
dongx0915 committed Apr 30, 2024
2 parents 2aed46b + 1283dc7 commit aa8ddfe
Show file tree
Hide file tree
Showing 11 changed files with 268 additions and 238 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ 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.developer.enum.ServerStatus
import com.runnect.runnect.developer.presentation.custom.ServerStatusPreference
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 com.runnect.runnect.util.extension.repeatOnStarted
import com.runnect.runnect.util.extension.setStatusBarColor
import dagger.hilt.android.AndroidEntryPoint
Expand Down Expand Up @@ -85,8 +87,8 @@ 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()
val combinedToken = "[Access Token]: $accessToken\n\n---\n\n[Refresh Token]: $refreshToken"

setPreferenceSummary("dev_pref_key_access_token", accessToken)
Expand All @@ -103,7 +105,7 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev
}

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 @@ -119,13 +121,16 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev
val selectItem = newValue.toString()
this.title = selectItem

PreferenceManager.apply {
setString(ctx, ApplicationClass.API_MODE, selectItem)
setString(ctx, MySettingAccountInfoFragment.TOKEN_KEY_ACCESS, "none")
setString(ctx, MySettingAccountInfoFragment.TOKEN_KEY_REFRESH, "none")
with(ctx) {
PreferenceManager.setString(this, ApplicationClass.API_MODE, selectItem)
saveToken(
accessToken = LoginStatus.NONE.value,
refreshToken = LoginStatus.NONE.value
)

restartApplication(this)
}

restartApplication(ctx)
true
}
}
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 aa8ddfe

Please sign in to comment.