Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into feature/mod-board-piece
Browse files Browse the repository at this point in the history
  • Loading branch information
eshc123 committed Oct 29, 2024
2 parents feffe16 + 00cc90b commit 5bd1e4a
Show file tree
Hide file tree
Showing 23 changed files with 348 additions and 108 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ android {
applicationId = "com.goalpanzi.mission_mate"
minSdk = 26
targetSdk = 34
versionCode = 4
versionName = "1.0.1"
versionCode = 5
versionName = "1.0.2"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
Expand Down
1 change: 1 addition & 0 deletions core/data/auth/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,5 @@ dependencies {
implementation(project(":core:domain:auth"))
implementation(project(":core:network"))
implementation(project(":core:datastore"))
implementation(project(":core:navigation"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.goalpanzi.mission_mate.core.data.auth

import com.goalpanzi.mission_mate.core.datastore.datasource.AuthDataSource
import com.goalpanzi.mission_mate.core.datastore.datasource.DefaultDataSource
import com.goalpanzi.mission_mate.core.datastore.datasource.MissionDataSource
import com.goalpanzi.mission_mate.core.navigation.NavigationEventHandler
import com.goalpanzi.mission_mate.core.navigation.di.AuthNavigation
import com.goalpanzi.mission_mate.core.network.TokenExpirationHandler
import kotlinx.coroutines.flow.collect
import javax.inject.Inject

class AuthTokenExpirationHandler @Inject constructor(
private val authDataSource: AuthDataSource,
private val defaultDataSource: DefaultDataSource,
private val missionDataSource: MissionDataSource,
@AuthNavigation private val authNavigationEventHandler: NavigationEventHandler
) : TokenExpirationHandler {

override suspend fun handleRefreshTokenExpiration() {
clearCachedData()
authNavigationEventHandler.triggerRouteToNavigate("RouteModel.Login")
}

private suspend fun clearCachedData(){
authDataSource.setAccessToken("")
authDataSource.setRefreshToken("")
defaultDataSource.clearUserData().collect()
missionDataSource.clearMissionData().collect()
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.goalpanzi.mission_mate.core.data.auth.di

import com.goalpanzi.mission_mate.core.data.auth.AuthTokenExpirationHandler
import com.goalpanzi.mission_mate.core.data.auth.AuthTokenProvider
import com.goalpanzi.mission_mate.core.data.auth.repository.AuthRepositoryImpl
import com.goalpanzi.mission_mate.core.domain.auth.repository.AuthRepository
import com.goalpanzi.mission_mate.core.network.TokenExpirationHandler
import com.goalpanzi.mission_mate.core.network.TokenProvider
import dagger.Binds
import dagger.Module
Expand All @@ -18,4 +20,7 @@ internal abstract class AuthDataModule {

@Binds
abstract fun bindTokenProvider(impl : AuthTokenProvider) : TokenProvider

@Binds
abstract fun bindTokenExpirationHandler(impl : AuthTokenExpirationHandler) : TokenExpirationHandler
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ fun CreateMissionBody.toRequest() : CreateMissionRequest {
fun MissionResponse.toModel() : Mission {
return Mission(
missionId = missionId,
description = description
description = description,
missionStatus = missionStatus
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ package com.goalpanzi.mission_mate.core.domain.onboarding.model

data class Mission(
val missionId : Long,
val description : String
val description : String,
val missionStatus : String
)
7 changes: 6 additions & 1 deletion core/navigation/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.jetbrains.kotlin.android)
alias(libs.plugins.kotlin.plugin.serialization)
alias(libs.plugins.kotlin.ksp)
alias(libs.plugins.hilt.android)
}

android {
Expand Down Expand Up @@ -37,4 +39,7 @@ android {

dependencies {
implementation(libs.kotlin.serialization.json)
}
implementation(libs.bundles.coroutines)
implementation(libs.hilt.android)
ksp(libs.hilt.compiler)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.goalpanzi.mission_mate.core.navigation

import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import javax.inject.Inject

class AuthNavigationEventHandler @Inject constructor() : NavigationEventHandler {

private val _routeToNavigate = MutableSharedFlow<String>()
override val routeToNavigate: SharedFlow<String> = _routeToNavigate.asSharedFlow()

override suspend fun triggerRouteToNavigate(route: String) {
_routeToNavigate.emit(route)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.goalpanzi.mission_mate.core.navigation

import kotlinx.coroutines.flow.SharedFlow

interface NavigationEventHandler {
val routeToNavigate : SharedFlow<String>

suspend fun triggerRouteToNavigate(route : String)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.goalpanzi.mission_mate.core.navigation.di

import com.goalpanzi.mission_mate.core.navigation.AuthNavigationEventHandler
import com.goalpanzi.mission_mate.core.navigation.NavigationEventHandler
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Qualifier
import javax.inject.Singleton

@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class AuthNavigation

@Module
@InstallIn(SingletonComponent::class)
abstract class NavigationModule {

@AuthNavigation
@Binds
@Singleton
abstract fun bindAuthNavigationEventHandler(
impl : AuthNavigationEventHandler
) : NavigationEventHandler
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.goalpanzi.mission_mate.core.network

interface TokenExpirationHandler {
suspend fun handleRefreshTokenExpiration()
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.goalpanzi.mission_mate.core.network.di

import com.goalpanzi.mission_mate.core.network.BuildConfig
import com.goalpanzi.mission_mate.core.network.TokenInterceptor
import com.goalpanzi.mission_mate.core.network.interceptor.TokenInterceptor
import com.goalpanzi.mission_mate.core.network.interceptor.TokenReissueInterceptor
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -13,8 +14,25 @@ import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Converter
import retrofit2.Retrofit
import retrofit2.converter.kotlinx.serialization.asConverterFactory
import javax.inject.Qualifier
import javax.inject.Singleton

@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class TokenInterceptorHttpClient

@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class TokenReissueInterceptorHttpClient

@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class TokenRetrofit

@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class TokenReissueRetrofit

@Module
@InstallIn(SingletonComponent::class)
internal object NetworkModule {
Expand All @@ -25,19 +43,32 @@ internal object NetworkModule {
return HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }
}

@TokenInterceptorHttpClient
@Provides
@Singleton
fun provideOkhttpClient(
fun provideTokenInterceptorHttpClient(
httpLoggingInterceptor: HttpLoggingInterceptor,
tokenInterceptor: TokenInterceptor
): OkHttpClient {

return OkHttpClient.Builder()
.addInterceptor(tokenInterceptor)
.addInterceptor(httpLoggingInterceptor)
.build()
}

@TokenReissueInterceptorHttpClient
@Provides
@Singleton
fun provideTokenReissueInterceptorHttpClient(
httpLoggingInterceptor: HttpLoggingInterceptor,
tokenReissueInterceptor: TokenReissueInterceptor
): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(tokenReissueInterceptor)
.addInterceptor(httpLoggingInterceptor)
.build()
}

@Provides
@Singleton
fun provideJson(): Json = Json {
Expand All @@ -53,10 +84,25 @@ internal object NetworkModule {
return json.asConverterFactory("application/json".toMediaType())
}

@TokenRetrofit
@Provides
@Singleton
fun provideTokenRetrofit(
@TokenInterceptorHttpClient okHttpClient: OkHttpClient,
converterFactory: Converter.Factory
) : Retrofit {
return Retrofit.Builder()
.client(okHttpClient)
.baseUrl(BuildConfig.BASE_URL)
.addConverterFactory(converterFactory)
.build()
}

@TokenReissueRetrofit
@Provides
@Singleton
fun provideRetrofit(
okHttpClient: OkHttpClient,
fun provideTokenReissueRetrofit(
@TokenReissueInterceptorHttpClient okHttpClient: OkHttpClient,
converterFactory: Converter.Factory
) : Retrofit {
return Retrofit.Builder()
Expand All @@ -65,4 +111,4 @@ internal object NetworkModule {
.addConverterFactory(converterFactory)
.build()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.goalpanzi.mission_mate.core.network.di

import com.goalpanzi.mission_mate.core.network.BuildConfig
import com.goalpanzi.mission_mate.core.network.TokenProvider
import com.goalpanzi.mission_mate.core.network.service.LoginService
import com.goalpanzi.mission_mate.core.network.service.MissionService
import com.goalpanzi.mission_mate.core.network.service.OnboardingService
Expand All @@ -11,11 +9,6 @@ import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.runBlocking
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Converter
import retrofit2.Retrofit
import javax.inject.Singleton

Expand All @@ -25,56 +18,41 @@ object ServiceModule {

@Provides
@Singleton
fun provideLoginService(retrofit: Retrofit): LoginService {
fun provideLoginService(
@TokenRetrofit retrofit: Retrofit
): LoginService {
return retrofit.create(LoginService::class.java)
}

@Provides
@Singleton
fun provideProfileService(retrofit: Retrofit): ProfileService {
fun provideProfileService(
@TokenRetrofit retrofit: Retrofit
): ProfileService {
return retrofit.create(ProfileService::class.java)
}

@Provides
@Singleton
fun provideOnboardingService(retrofit: Retrofit): OnboardingService {
fun provideOnboardingService(
@TokenRetrofit retrofit: Retrofit
): OnboardingService {
return retrofit.create(OnboardingService::class.java)
}

@Provides
@Singleton
fun provideMissionService(retrofit: Retrofit): MissionService {
fun provideMissionService(
@TokenRetrofit retrofit: Retrofit)
: MissionService {
return retrofit.create(MissionService::class.java)
}

@Provides
@Singleton
fun provideTokenService(
httpLoggingInterceptor: HttpLoggingInterceptor,
converterFactory: Converter.Factory,
tokenProvider: TokenProvider
): TokenService {
val tokenReissueInterceptor = Interceptor { chain ->
val newRequest = chain.request().newBuilder().apply {
runBlocking {
val token = tokenProvider.getAccessToken()
token?.let {
addHeader("Authorization", "Bearer $it")
}
}
}
chain.proceed(newRequest.build())
}
val retrofit = Retrofit.Builder()
.client(
OkHttpClient.Builder()
.addInterceptor(tokenReissueInterceptor)
.addInterceptor(httpLoggingInterceptor)
.build()
)
.baseUrl(BuildConfig.BASE_URL)
.addConverterFactory(converterFactory)
.build()
@TokenReissueRetrofit retrofit: Retrofit
) : TokenService {
return retrofit.create(TokenService::class.java)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.goalpanzi.mission_mate.core.network
package com.goalpanzi.mission_mate.core.network.interceptor

import com.goalpanzi.mission_mate.core.network.TokenProvider
import com.goalpanzi.mission_mate.core.network.model.request.TokenReissueRequest
import com.goalpanzi.mission_mate.core.network.service.TokenService
import kotlinx.coroutines.CoroutineScope
Expand Down
Loading

0 comments on commit 5bd1e4a

Please sign in to comment.