Skip to content

Commit 5661733

Browse files
authored
Merge pull request #340 from Runnect/feature/refactor-data
[REFACTOR] 데이터 레이어 다른 계층 참조하지 않도록 코드 분리
2 parents 17abeac + 7315ecc commit 5661733

File tree

11 files changed

+278
-241
lines changed

11 files changed

+278
-241
lines changed

app/src/debug/java/com/runnect/runnect/developer/RunnectDeveloperActivity.kt

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ import com.runnect.runnect.R
1717
import com.runnect.runnect.application.ApiMode
1818
import com.runnect.runnect.application.ApplicationClass
1919
import com.runnect.runnect.application.PreferenceManager
20-
import com.runnect.runnect.data.service.TokenAuthenticator
21-
import com.runnect.runnect.presentation.mypage.setting.accountinfo.MySettingAccountInfoFragment
2220
import com.runnect.runnect.util.custom.toast.RunnectToast
21+
import com.runnect.runnect.util.preference.AuthUtil.getAccessToken
22+
import com.runnect.runnect.util.preference.AuthUtil.getNewToken
23+
import com.runnect.runnect.util.preference.AuthUtil.saveToken
24+
import com.runnect.runnect.util.preference.StatusType.LoginStatus
2325
import kotlinx.coroutines.Dispatchers
2426
import kotlinx.coroutines.delay
2527
import kotlinx.coroutines.launch
@@ -44,15 +46,15 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev
4446

4547
private fun initUserInfo() {
4648
val ctx: Context = context ?: return
47-
val accessToken = PreferenceManager.getString(ctx, TokenAuthenticator.TOKEN_KEY_ACCESS) ?: ""
48-
val refreshToken = PreferenceManager.getString(ctx, TokenAuthenticator.TOKEN_KEY_REFRESH) ?: ""
49+
val accessToken = ctx.getAccessToken()
50+
val refreshToken = ctx.getNewToken()
4951

5052
setPreferenceSummary("dev_pref_key_access_token", accessToken)
5153
setPreferenceSummary("dev_pref_key_refresh_token", refreshToken)
5254
}
5355

5456
private fun initApiMode() {
55-
val ctx:Context = context ?: ApplicationClass.appContext
57+
val ctx: Context = context ?: ApplicationClass.appContext
5658
val currentApi = ApiMode.getCurrentApiMode(ctx)
5759

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

7173
PreferenceManager.apply {
7274
setString(ctx, ApplicationClass.API_MODE, selectItem)
73-
setString(ctx, MySettingAccountInfoFragment.TOKEN_KEY_ACCESS, "none")
74-
setString(ctx, MySettingAccountInfoFragment.TOKEN_KEY_REFRESH, "none")
7575
}
76-
76+
ctx.saveToken(
77+
accessToken = LoginStatus.NONE.value,
78+
refreshToken = LoginStatus.NONE.value
79+
)
7780
destroyApp(ctx)
7881
true
7982
}
@@ -93,9 +96,15 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev
9396
val naviBarHeight = getNaviBarHeight(windowManager)
9497

9598
with(metrics) {
96-
setPreferenceSummary("dev_pref_display_ratio", "$widthPixels x ${heightPixels + statusBarHeight + naviBarHeight}")
99+
setPreferenceSummary(
100+
"dev_pref_display_ratio",
101+
"$widthPixels x ${heightPixels + statusBarHeight + naviBarHeight}"
102+
)
97103
setPreferenceSummary("dev_pref_display_density", "${densityDpi}dp")
98-
setPreferenceSummary("dev_pref_display_resource_bucket", getDeviceResourseBucket(this))
104+
setPreferenceSummary(
105+
"dev_pref_display_resource_bucket",
106+
getDeviceResourseBucket(this)
107+
)
99108
}
100109
}
101110

@@ -116,7 +125,8 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev
116125
private fun getStatusBarHeight(windowManager: WindowManager): Int {
117126
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
118127
val windowMetrics = windowManager.currentWindowMetrics
119-
val insets = windowMetrics.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.statusBars())
128+
val insets =
129+
windowMetrics.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.statusBars())
120130
insets.top
121131
} else {
122132
0
@@ -126,7 +136,8 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev
126136
private fun getNaviBarHeight(windowManager: WindowManager): Int {
127137
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
128138
val windowMetrics = windowManager.currentWindowMetrics
129-
val insets = windowMetrics.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars())
139+
val insets =
140+
windowMetrics.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars())
130141
insets.bottom
131142
} else {
132143
0
@@ -157,7 +168,8 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev
157168

158169
private fun destroyApp(context: Context) {
159170
lifecycleScope.launch(Dispatchers.Main) {
160-
RunnectToast.createToast(context, getString(R.string.dev_mode_require_restart)).show()
171+
RunnectToast.createToast(context, getString(R.string.dev_mode_require_restart))
172+
.show()
161173
delay(3000)
162174

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

app/src/main/java/com/runnect/runnect/data/service/AppInterceptor.kt

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package com.runnect.runnect.data.service
2+
3+
import android.content.Context
4+
import com.runnect.runnect.application.ApplicationClass
5+
import com.runnect.runnect.data.dto.response.ResponseGetRefreshToken
6+
import com.runnect.runnect.data.dto.response.base.BaseResponse
7+
import com.runnect.runnect.util.preference.AuthUtil.getAccessToken
8+
import com.runnect.runnect.util.preference.AuthUtil.getNewToken
9+
import com.runnect.runnect.util.preference.AuthUtil.saveToken
10+
import com.runnect.runnect.util.preference.StatusType.LoginStatus
11+
import dagger.hilt.android.qualifiers.ApplicationContext
12+
import kotlinx.serialization.decodeFromString
13+
import kotlinx.serialization.json.Json
14+
import okhttp3.Interceptor
15+
import okhttp3.Request
16+
import okhttp3.RequestBody.Companion.toRequestBody
17+
import okhttp3.Response
18+
import timber.log.Timber
19+
import javax.inject.Inject
20+
21+
class AuthInterceptor @Inject constructor(
22+
@ApplicationContext private val context: Context,
23+
private val json: Json
24+
) : Interceptor {
25+
// access Header 에 보내고 이때 401(토큰 만료) 뜨면 액세스 재발급 요청
26+
// 재발급 성공 : 저장
27+
// 재발급 실패 : 재 로그인 토스트 메시지 띄우고 preference 빈 값 넣고 로그인 화면 이동
28+
override fun intercept(chain: Interceptor.Chain): Response {
29+
val originalRequest = chain.request()
30+
31+
val headerRequest = originalRequest.newAuthTokenBuilder()
32+
.build()
33+
34+
val response = headerRequest.let { chain.proceed(it) }
35+
36+
return if (response.code == CODE_TOKEN_EXPIRED) {
37+
try {
38+
Timber.e("Access Token Expired: getNewAccessToken")
39+
response.close()
40+
handleTokenExpired(chain, originalRequest, headerRequest)
41+
} catch (t: Throwable) {
42+
Timber.e("Exception: ${t.message}")
43+
context.saveToken(
44+
accessToken = LoginStatus.EXPIRED.value,
45+
refreshToken = LoginStatus.EXPIRED.value
46+
)
47+
response
48+
}
49+
} else {
50+
response
51+
}
52+
}
53+
54+
private fun Request.newAuthTokenBuilder(): Request.Builder {
55+
val accessToken = context.getAccessToken()
56+
val refreshToken = context.getNewToken()
57+
return newBuilder().apply {
58+
addHeader(ACCESS_TOKEN, accessToken)
59+
addHeader(REFRESH_TOKEN, refreshToken)
60+
}
61+
}
62+
63+
64+
private fun handleTokenExpired(
65+
chain: Interceptor.Chain,
66+
originalRequest: Request,
67+
headerRequest: Request
68+
): Response {
69+
val refreshTokenResponse = getNewToken(originalRequest, chain)
70+
return if (refreshTokenResponse.isSuccessful) {
71+
handleGetRefreshTokenSuccess(refreshTokenResponse, originalRequest, chain)
72+
} else {
73+
handleGetNewTokenFailure(refreshTokenResponse, headerRequest, chain)
74+
}
75+
}
76+
77+
private fun getNewToken(originalRequest: Request, chain: Interceptor.Chain): Response {
78+
val baseUrl = ApplicationClass.getBaseUrl()
79+
val refreshToken = context.getNewToken()
80+
val refreshTokenRequest = originalRequest.newBuilder().post("".toRequestBody())
81+
.url("$baseUrl/api/auth/getNewToken")
82+
.addHeader(REFRESH_TOKEN, refreshToken)
83+
.build()
84+
85+
return chain.proceed(refreshTokenRequest)
86+
}
87+
88+
private fun handleGetRefreshTokenSuccess(
89+
refreshTokenResponse: Response,
90+
originalRequest: Request,
91+
chain: Interceptor.Chain
92+
): Response {
93+
refreshTokenResponse.use { response ->
94+
val responseToken = json.decodeFromString<BaseResponse<ResponseGetRefreshToken>>(
95+
response.body?.string().orEmpty()
96+
)
97+
responseToken.data?.data?.let {
98+
Timber.e("New Refresh Token Success: ${it.refreshToken}")
99+
context.saveToken(it.accessToken, it.refreshToken)
100+
}
101+
}
102+
103+
val newRequest = originalRequest.newAuthTokenBuilder().build()
104+
return chain.proceed(newRequest)
105+
}
106+
107+
private fun handleGetNewTokenFailure(
108+
refreshTokenResponse: Response,
109+
headerRequest: Request,
110+
chain: Interceptor.Chain
111+
): Response {
112+
Timber.e("New Refresh Token Failure: ${refreshTokenResponse.code}")
113+
context.saveToken(
114+
accessToken = LoginStatus.EXPIRED.value,
115+
refreshToken = LoginStatus.EXPIRED.value
116+
)
117+
return chain.proceed(headerRequest)
118+
}
119+
120+
121+
companion object {
122+
private const val ACCESS_TOKEN = "accessToken"
123+
private const val CODE_TOKEN_EXPIRED = 401
124+
private const val REFRESH_TOKEN = "refreshToken"
125+
}
126+
127+
}

app/src/main/java/com/runnect/runnect/data/service/TokenAuthenticator.kt

Lines changed: 0 additions & 126 deletions
This file was deleted.

0 commit comments

Comments
 (0)