Skip to content

Commit

Permalink
[Merge] #55 -> develop
Browse files Browse the repository at this point in the history
[Feat/#55] token interceptor + accessToken 재발급 + token  컨트롤
  • Loading branch information
chattymin authored Jan 10, 2024
2 parents 1dd5f1c + fd9a76c commit f7f71ac
Show file tree
Hide file tree
Showing 21 changed files with 204 additions and 15 deletions.
72 changes: 72 additions & 0 deletions app/src/main/java/com/going/doorip/di/AuthInterceptor.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
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.doorip.BuildConfig.BASE_URL
import dagger.hilt.android.qualifiers.ApplicationContext
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(
private val json: Json,
private val dataStore: GoingDataStore,
@ApplicationContext private val context: Context,
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()

Timber.d("GET ACCESS TOKEN : ${dataStore.accessToken}")

val authRequest = if (dataStore.accessToken.isNotBlank()) {
originalRequest.newAuthBuilder().build()
} else {
originalRequest
}
val response = chain.proceed(authRequest)

when (response.code) {
CODE_TOKEN_EXPIRED -> {
try {
val refreshTokenRequest = originalRequest.newBuilder().post("".toRequestBody())
.url("$BASE_URL/api/users/reissue")
.addHeader(AUTHORIZATION, dataStore.refreshToken)
.build()
val refreshTokenResponse = chain.proceed(refreshTokenRequest)
Timber.d("GET REFRESH TOKEN : $refreshTokenResponse")

if (refreshTokenResponse.isSuccessful) {
val responseToken = json.decodeFromString(
refreshTokenResponse.body?.string().toString(),
) as BaseResponse<AuthTokenModel>

with(dataStore) {
accessToken = responseToken.data.accessToken
refreshToken = responseToken.data.refreshToken
}
refreshTokenResponse.close()
val newRequest = originalRequest.newAuthBuilder().build()
return chain.proceed(newRequest)
}
} catch (t: Throwable) {
Timber.e(t)
}
}
}
return response
}

private fun Request.newAuthBuilder() =
this.newBuilder().addHeader(AUTHORIZATION, "Bearer ${dataStore.accessToken}")

companion object {
private const val CODE_TOKEN_EXPIRED = 401
private const val AUTHORIZATION = "Authorization"
}
}
7 changes: 7 additions & 0 deletions app/src/main/java/com/going/doorip/di/DataSourceModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package com.going.doorip.di

import com.going.data.datasource.AuthDataSource
import com.going.data.datasource.MockDataSource
import com.going.data.datasource.SettingDataSource
import com.going.data.datasourceImpl.AuthDataSourceImpl
import com.going.data.datasourceImpl.MockDataSourceImpl
import com.going.data.datasourceImpl.SettingDataSourceImpl
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -23,4 +25,9 @@ object DataSourceModule {
@Singleton
fun provideAuthDataSource(authDataSourceImpl: AuthDataSourceImpl): AuthDataSource =
authDataSourceImpl

@Provides
@Singleton
fun provideSettingDataSource(settingDataSourceImpl: SettingDataSourceImpl): SettingDataSource =
settingDataSourceImpl
}
2 changes: 1 addition & 1 deletion app/src/main/java/com/going/doorip/di/DataStoreModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package com.going.doorip.di

import android.content.Context
import android.content.SharedPreferences
import com.going.data.local.GoingDataStoreImpl
import com.going.data.local.GoingDataStore
import com.going.data.local.GoingDataStoreImpl
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand Down
11 changes: 9 additions & 2 deletions app/src/main/java/com/going/doorip/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.going.doorip.di

import com.going.data.repositoryImpl.TokenRepositoryImpl
import com.going.data.repositoryImpl.AuthRepositoryImpl
import com.going.data.repositoryImpl.MockRepositoryImpl
import com.going.domain.repository.TokenRepository
import com.going.data.repositoryImpl.SettingRepositoryImpl
import com.going.data.repositoryImpl.TokenRepositoryImpl
import com.going.domain.repository.AuthRepository
import com.going.domain.repository.MockRepository
import com.going.domain.repository.SettingRepository
import com.going.domain.repository.TokenRepository
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -30,4 +32,9 @@ object RepositoryModule {
@Singleton
fun provideTokenRepository(tokenRepositoryImpl: TokenRepositoryImpl): TokenRepository =
tokenRepositoryImpl

@Provides
@Singleton
fun provideSettingRepository(settingRepositoryImpl: SettingRepositoryImpl): SettingRepository =
settingRepositoryImpl
}
13 changes: 11 additions & 2 deletions app/src/main/java/com/going/doorip/di/RetrofitModule.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
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.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import dagger.Module
import dagger.Provides
Expand Down Expand Up @@ -54,15 +56,22 @@ object RetrofitModule {

@Provides
@Singleton
fun provideOkHttpClient(
@JWT
fun provideAuthInterceptor(authInterceptor: AuthInterceptor): Interceptor = authInterceptor

@Provides
@Singleton
fun provideJWTOkHttpClient(
loggingInterceptor: Interceptor,
@JWT authInterceptor: Interceptor,
): OkHttpClient = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.addInterceptor(authInterceptor)
.build()

@Provides
@Singleton
fun provideRetrofit(
fun provideJWTRetrofit(
client: OkHttpClient,
factory: Converter.Factory,
): Retrofit = Retrofit.Builder()
Expand Down
8 changes: 7 additions & 1 deletion app/src/main/java/com/going/doorip/di/ServiceModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.going.doorip.di

import com.going.data.service.AuthService
import com.going.data.service.MockService
import com.going.data.service.SettingService
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -20,6 +21,11 @@ object ServiceModule {

@Provides
@Singleton
fun provideLoginService(retrofit: Retrofit): AuthService =
fun provideAuthService(retrofit: Retrofit): AuthService =
retrofit.create(AuthService::class.java)

@Provides
@Singleton
fun provideSettingService(retrofit: Retrofit): SettingService =
retrofit.create(SettingService::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.going.doorip.di.qualifier

import javax.inject.Qualifier

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class JWT
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.going.data.datasource

import com.going.data.dto.response.SignOutResponseDto

interface SettingDataSource {
suspend fun patchSignOut(): SignOutResponseDto
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.going.data.datasourceImpl

import com.going.data.datasource.SettingDataSource
import com.going.data.dto.response.SignOutResponseDto
import com.going.data.service.SettingService
import javax.inject.Inject

class SettingDataSourceImpl @Inject constructor(
private val settingService: SettingService,
) : SettingDataSource {
override suspend fun patchSignOut(): SignOutResponseDto = settingService.patchSignOut()
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package com.going.data.dto.request

import com.going.domain.entity.request.RequestSignInModel
import com.going.domain.entity.request.RequestSignUpModel
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class SignInRequestDto(
@SerialName("platform")
val platform: String
val platform: String,
)

fun RequestSignInModel.toSignInRequestDto(): SignInRequestDto =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.going.data.dto.response

import com.going.domain.entity.response.SignOutModel
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class SignOutResponseDto(
@SerialName("status")
val status: Int,
@SerialName("message")
val message: String,
) {
fun toSignOutModel() =
SignOutModel(status, message)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.going.data.repositoryImpl

import com.going.data.datasource.SettingDataSource
import com.going.domain.entity.response.SignOutModel
import com.going.domain.repository.SettingRepository
import javax.inject.Inject

class SettingRepositoryImpl @Inject constructor(
private val settingDataSource: SettingDataSource,
) : SettingRepository {
override suspend fun patchSignOut(): Result<SignOutModel> = runCatching {
settingDataSource.patchSignOut().toSignOutModel()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ class TokenRepositoryImpl @Inject constructor(
private val goingDataStore: GoingDataStore,
) : TokenRepository {
override fun getAccessToken(): String = goingDataStore.accessToken
override fun getRefreshToken(): String = goingDataStore.refreshToken

override fun setTokens(accessToken: String, refreshToken: String) {
goingDataStore.accessToken = accessToken
goingDataStore.refreshToken = refreshToken
}

override fun getRefreshToken(): String = goingDataStore.refreshToken
override fun clearTokens() {
goingDataStore.accessToken = ""
goingDataStore.refreshToken = ""
}
}
9 changes: 9 additions & 0 deletions data/src/main/java/com/going/data/service/SettingService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.going.data.service

import com.going.data.dto.response.SignOutResponseDto
import retrofit2.http.PATCH

interface SettingService {
@PATCH("api/users/signout")
suspend fun patchSignOut(): SignOutResponseDto
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.going.domain.entity.response

data class SignOutModel(
val status: Int,
val message: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.going.domain.repository

import com.going.domain.entity.response.SignOutModel

interface SettingRepository {
suspend fun patchSignOut(): Result<SignOutModel>
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ interface TokenRepository {
fun getRefreshToken(): String

fun setTokens(accessToken: String, refreshToken: String)
fun clearTokens()
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ import javax.inject.Inject
class SplashViewModel @Inject constructor(
private val tokenRepository: TokenRepository,
) : ViewModel() {
fun getHasAccessToken(): Boolean = tokenRepository.getAccessToken() != ""
fun getHasAccessToken(): Boolean = tokenRepository.getAccessToken().isNotBlank()

fun clearTokens() = tokenRepository.clearTokens()
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.going.presentation.tendencytest.result

import android.media.SubtitleData
import android.os.Bundle
import android.text.SpannableString
import android.text.Spanned
Expand All @@ -26,7 +27,7 @@ class TendencyTestResultActivity :
with(binding) {
tvTendencyTestResultTitle.text = getString(R.string.tendency_test_result_title, "찐두릅")

viewModel?.mockTendencyResult?.apply {
viewModel.mockTendencyResult.apply {
tvTendencyTestResultType.text = profileTitle
tvTendencyTestResultSubType.text = profileSubTitle

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
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()
val json = jsonTemp.slice(6 until jsonTemp.length)
Log.e("TAG", "toErrorCode: $jsonTemp", )
val json = jsonTemp.slice(6 until jsonTemp.length - 2) + "}"
Log.e("TAG", "toErrorCode: $json", )
JSONObject(json).getString("code")
} else {
"NOT_HTTP"
}

// 기능 오류 발견!!!! 반드시 수정 필요!!!!!!
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto">

<data>
<variable
name="viewModel"
type="com.going.presentation.tendencytest.result.TendencyTestResultViewModel" />

</data>

<androidx.constraintlayout.widget.ConstraintLayout
Expand Down

0 comments on commit f7f71ac

Please sign in to comment.