diff --git a/data/build.gradle.kts b/data/build.gradle.kts index 9419295..e444f28 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -17,37 +17,15 @@ dependencies { // Android Core implementation(KotlinDependencies.kotlin) implementation(AndroidXDependencies.coreKtx) - implementation(AndroidXDependencies.appCompat) - implementation(AndroidXDependencies.constraintLayout) implementation(AndroidXDependencies.coroutines) - // Material Design - implementation(MaterialDesignDependencies.materialDesign) - // Dagger-Hilt implementation(AndroidXDependencies.hilt) kapt(KaptDependencies.hiltCompiler) - // Jetpack Navigation Component - implementation(AndroidXDependencies.navigationFragment) - implementation(AndroidXDependencies.navigationUI) - // Jetpack Security implementation(AndroidXDependencies.security) - // Jetpack Fragment - implementation(AndroidXDependencies.fragment) - - // Jetpack Lifecycle - implementation(AndroidXDependencies.coroutines) - implementation(AndroidXDependencies.lifeCycleKtx) - implementation(AndroidXDependencies.lifecycleJava8) - - // ImageLoading Library - // Glide for general - implementation(ThirdPartyDependencies.glide) - kapt(KaptDependencies.glideCompiler) - // Http Client Library implementation(ThirdPartyDependencies.retrofit) implementation(platform(ThirdPartyDependencies.okHttpBom)) diff --git a/data/src/main/java/org/mascota/data/EmptyFile.kt b/data/src/main/java/org/mascota/data/EmptyFile.kt deleted file mode 100644 index 00dcba1..0000000 --- a/data/src/main/java/org/mascota/data/EmptyFile.kt +++ /dev/null @@ -1,3 +0,0 @@ -package org.mascota.data - -class EmptyFile diff --git a/data/src/main/java/org/mascota/data/di/LocalPreferencesModule.kt b/data/src/main/java/org/mascota/data/di/LocalPreferencesModule.kt new file mode 100644 index 0000000..90c874b --- /dev/null +++ b/data/src/main/java/org/mascota/data/di/LocalPreferencesModule.kt @@ -0,0 +1,19 @@ +package org.mascota.data.di + +import android.app.Application +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton +import org.mascota.data.local.MascotaSharedPreferences + +@Module +@InstallIn(SingletonComponent::class) +object LocalPreferencesModule { + @Provides + @Singleton + fun providesLocalPreferences(@ApplicationContext context: Application) = + MascotaSharedPreferences(context) +} diff --git a/data/src/main/java/org/mascota/data/di/NetworkModule.kt b/data/src/main/java/org/mascota/data/di/NetworkModule.kt new file mode 100644 index 0000000..188f4f2 --- /dev/null +++ b/data/src/main/java/org/mascota/data/di/NetworkModule.kt @@ -0,0 +1,60 @@ +package org.mascota.data.di + +import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import java.util.concurrent.TimeUnit +import javax.inject.Singleton +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.Json +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.mascota.data.local.MascotaSharedPreferences +import org.mascota.data.network.AuthInterceptor +import retrofit2.Retrofit + +@InstallIn(SingletonComponent::class) +@Module +object NetworkModule { + @Provides + @Singleton + fun provideHttpLoggingInterceptor(): HttpLoggingInterceptor = + HttpLoggingInterceptor().apply { + level = HttpLoggingInterceptor.Level.BODY + } + + @Provides + @Singleton + fun provideAuthInterceptor(preferences: MascotaSharedPreferences) = + AuthInterceptor(preferences) + + @Provides + @Singleton + fun provideOkHttpClient( + httpLoggingInterceptor: HttpLoggingInterceptor, + authInterceptor: AuthInterceptor + ): OkHttpClient = + OkHttpClient.Builder() + .connectTimeout(1, TimeUnit.MINUTES) + .writeTimeout(30, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .addInterceptor(authInterceptor) + .addInterceptor(httpLoggingInterceptor) + .build() + + @ExperimentalSerializationApi + @Provides + @Singleton + fun provideRetrofitObject(okHttpClient: OkHttpClient): Retrofit { + return Retrofit.Builder() + .baseUrl(MASCOTA_URL) + .client(okHttpClient) + .addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) + .build() + } + + private const val MASCOTA_URL = "https://mascota.kr/" +} diff --git a/data/src/main/java/org/mascota/data/local/MascotaSharedPreferences.kt b/data/src/main/java/org/mascota/data/local/MascotaSharedPreferences.kt new file mode 100644 index 0000000..75b091c --- /dev/null +++ b/data/src/main/java/org/mascota/data/local/MascotaSharedPreferences.kt @@ -0,0 +1,30 @@ +package org.mascota.data.local + +import android.content.Context +import androidx.core.content.edit +import androidx.databinding.ktx.BuildConfig +import androidx.security.crypto.EncryptedSharedPreferences +import androidx.security.crypto.MasterKeys +import javax.inject.Inject + +class MascotaSharedPreferences @Inject constructor( + context: Context +) { + private val preferences = if (!BuildConfig.DEBUG) EncryptedSharedPreferences.create( + FILE_NAME, + MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC), + context, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM + ) else context.getSharedPreferences(DEBUG_FILE_NAME, Context.MODE_PRIVATE) + + var userToken: String + set(value) = preferences.edit { putString(USER_TOKEN, value) } + get() = preferences.getString(USER_TOKEN, "") ?: "" + + companion object { + private const val USER_TOKEN = "USER_TOKEN" + private const val FILE_NAME = "MASCOTAAUTH" + const val DEBUG_FILE_NAME = "MASCOTAAUTHDEBUG" + } +} diff --git a/data/src/main/java/org/mascota/data/network/AuthInterceptor.kt b/data/src/main/java/org/mascota/data/network/AuthInterceptor.kt new file mode 100644 index 0000000..d64a405 --- /dev/null +++ b/data/src/main/java/org/mascota/data/network/AuthInterceptor.kt @@ -0,0 +1,20 @@ +package org.mascota.data.network + +import javax.inject.Inject +import okhttp3.Interceptor +import okhttp3.Response +import org.mascota.data.local.MascotaSharedPreferences + +class AuthInterceptor @Inject constructor(private val preferences: MascotaSharedPreferences) : + Interceptor { + + override fun intercept(chain: Interceptor.Chain): Response { + val requestBuilder = chain.request().newBuilder() + + preferences.userToken.let { + requestBuilder.addHeader("x-access-token", it) + } + + return chain.proceed(requestBuilder.build()) + } +} diff --git a/gradle/common.gradle b/gradle/common.gradle index 8e709b4..0e4aaa4 100644 --- a/gradle/common.gradle +++ b/gradle/common.gradle @@ -18,5 +18,8 @@ if (hasLibraryPlugin || hasApplicationPlugin) { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11 + } } }