Skip to content

Commit

Permalink
Merge pull request #19 from YAPP-Github/feature/MZ-150-kakao-login
Browse files Browse the repository at this point in the history
Feature/mz 150 kakao login
  • Loading branch information
yangsooplus authored Jan 3, 2024
2 parents 1387897 + d6f69ac commit 89dd447
Show file tree
Hide file tree
Showing 68 changed files with 1,202 additions and 216 deletions.
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ obj/
/out/

# User-specific configurations
/.idea
.idea/caches/
.idea/libraries/
.idea/shelf/
Expand Down Expand Up @@ -153,4 +154,7 @@ fabric.properties

!/gradle/wrapper/gradle-wrapper.jar

# End of https://www.toptal.com/developers/gitignore/api/androidstudio,kotlin
# Compose-Report
/report

# End of https://www.toptal.com/developers/gitignore/api/androidstudio,kotlin
3 changes: 2 additions & 1 deletion app/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/build
/build
google-services.json
15 changes: 15 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties

@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
plugins {
alias(libs.plugins.susu.android.application)
Expand All @@ -13,15 +15,28 @@ android {
applicationId = "com.oksusu.susu"
versionCode = 1
versionName = "1.0"
buildConfigField("String", "KAKAO_APP_KEY", getApiKey("KAKAO_APP_KEY"))
manifestPlaceholders["KAKAO_APP_KEY"] = "kakao${getApiKey("KAKAO_REDIRECT_KEY")}"
}

buildFeatures {
buildConfig = true
}
}

dependencies {
implementation(projects.feature.navigator)
implementation(projects.data)
implementation(libs.kakao.sdk.user)

implementation(platform(libs.firebase.bom))
implementation(libs.firebase.crashlytics)
implementation(libs.firebase.analytics)

implementation(libs.timber)
}

@Suppress
fun getApiKey(propertyKey: String): String {
return gradleLocalProperties(rootDir).getProperty(propertyKey) ?: "default"
}
17 changes: 15 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
xmlns:tools="http://schemas.android.com/tools"
package="com.oksusu.susu">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:name=".SUSUApplication"
Expand All @@ -12,6 +13,18 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
tools:replace="android:allowBackup"
tools:targetApi="s"/>
tools:targetApi="s">
<activity
android:name="com.kakao.sdk.auth.AuthCodeHandlerActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="oauth"
android:scheme="${KAKAO_APP_KEY}" />
</intent-filter>
</activity>
</application>

</manifest>
9 changes: 9 additions & 0 deletions app/src/main/java/com/oksusu/susu/CustomTimberTree.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.oksusu.susu

import timber.log.Timber

class CustomTimberTree : Timber.DebugTree() {
override fun createStackElementTag(element: StackTraceElement): String? {
return "${element.className}:${element.lineNumber}#${element.methodName}"
}
}
14 changes: 13 additions & 1 deletion app/src/main/java/com/oksusu/susu/SUSUApplication.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
package com.oksusu.susu

import android.app.Application
import com.kakao.sdk.common.KakaoSdk
import dagger.hilt.android.HiltAndroidApp
import timber.log.Timber

@HiltAndroidApp
class SUSUApplication : Application()
class SUSUApplication : Application() {
override fun onCreate() {
super.onCreate()

if (BuildConfig.DEBUG) {
Timber.plant(CustomTimberTree())
}

KakaoSdk.init(this, BuildConfig.KAKAO_APP_KEY)
}
}
6 changes: 6 additions & 0 deletions core/model/src/main/java/com/susu/core/model/Token.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.susu.core.model

data class Token(
val accessToken: String,
val refreshToken: String,
)
7 changes: 7 additions & 0 deletions core/model/src/main/java/com/susu/core/model/User.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.susu.core.model

data class User(
val name: String,
val gender: String,
val birth: Int,
)
27 changes: 27 additions & 0 deletions data/src/main/java/com/susu/data/di/DataStoreModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.emptyPreferences
import androidx.datastore.preferences.preferencesDataStoreFile
import com.susu.data.security.SecurityPreferences
import com.susu.data.security.generateSecurityPreferences
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import tech.thdev.useful.encrypted.data.store.preferences.security.generateUsefulSecurity
import javax.inject.Qualifier
import javax.inject.Singleton

@InstallIn(SingletonComponent::class)
Expand All @@ -29,5 +33,28 @@ object DataStoreModule {
)
}

@EncryptedDataStore
@Singleton
@Provides
fun providedEncryptedDataStore(@ApplicationContext context: Context): DataStore<Preferences> {
return PreferenceDataStoreFactory.create(
corruptionHandler = ReplaceFileCorruptionHandler(
produceNewData = { emptyPreferences() },
),
produceFile = { context.preferencesDataStoreFile(ENCRYPTED_DATASTORE_NAME) },
)
}

@Singleton
@Provides
fun provideSecurityPreference(
@EncryptedDataStore dataStore: DataStore<Preferences>,
): SecurityPreferences = dataStore.generateSecurityPreferences(generateUsefulSecurity())

private const val DATASTORE_NAME = "susu-datastore"
private const val ENCRYPTED_DATASTORE_NAME = "susu-datastore-encrypted"
}

@Qualifier
@Retention(AnnotationRetention.BINARY)
internal annotation class EncryptedDataStore
67 changes: 45 additions & 22 deletions data/src/main/java/com/susu/data/di/NetworkModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,36 +23,38 @@ import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
object NetworkModule {

private const val BASE_URL = ""
private const val BASE_URL = "https://api.oksusu.site/api/v1/"

@Singleton
@Provides
fun provideOkHttpClient(
tokenInterceptor: TokenInterceptor,
tokenAuthenticator: TokenAuthenticator,
fun provideLoggingInterceptor(
json: Json,
): OkHttpClient {
val loggingInterceptor = HttpLoggingInterceptor { message ->
when {
!message.isJsonObject() && !message.isJsonArray() ->
Timber.tag(RETROFIT_TAG).d("CONNECTION INFO -> $message")
): HttpLoggingInterceptor = HttpLoggingInterceptor { message ->
when {
!message.isJsonObject() && !message.isJsonArray() ->
Timber.tag(RETROFIT_TAG).d("CONNECTION INFO -> $message")

else -> kotlin.runCatching {
json.encodeToString(Json.parseToJsonElement(message))
}.onSuccess {
Timber.tag(RETROFIT_TAG).d(it)
}.onFailure {
Timber.tag(RETROFIT_TAG).d(message)
}
else -> kotlin.runCatching {
json.encodeToString(Json.parseToJsonElement(message))
}.onSuccess {
Timber.tag(RETROFIT_TAG).d(it)
}.onFailure {
Timber.tag(RETROFIT_TAG).d(message)
}
}
}.apply { level = HttpLoggingInterceptor.Level.BODY }

return OkHttpClient.Builder()
.addInterceptor(tokenInterceptor)
.addInterceptor(loggingInterceptor)
.authenticator(tokenAuthenticator)
.build()
}
@Singleton
@Provides
fun provideOkHttpClient(
tokenInterceptor: TokenInterceptor,
tokenAuthenticator: TokenAuthenticator,
loggingInterceptor: HttpLoggingInterceptor,
): OkHttpClient = OkHttpClient.Builder()
.addInterceptor(tokenInterceptor)
.addInterceptor(loggingInterceptor)
.authenticator(tokenAuthenticator)
.build()

@Singleton
@Provides
Expand All @@ -65,6 +67,27 @@ object NetworkModule {
.client(okHttpClient)
.build()

@Singleton
@Provides
@AuthOkHttpClient
fun provideAuthOkHttpClient(
loggingInterceptor: HttpLoggingInterceptor,
): OkHttpClient = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.build()

@Singleton
@Provides
@AuthRetrofit
fun provideAuthRetrofit(
@AuthOkHttpClient okHttpClient: OkHttpClient,
json: Json,
): Retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
.client(okHttpClient)
.build()

@Singleton
@Provides
fun provideJson(): Json {
Expand Down
11 changes: 11 additions & 0 deletions data/src/main/java/com/susu/data/di/Qualifier.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.susu.data.di

import javax.inject.Qualifier

@Qualifier
@Retention(AnnotationRetention.BINARY)
internal annotation class AuthOkHttpClient

@Qualifier
@Retention(AnnotationRetention.BINARY)
internal annotation class AuthRetrofit
14 changes: 14 additions & 0 deletions data/src/main/java/com/susu/data/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.susu.data.di

import com.susu.data.repository.LoginRepositoryImpl
import com.susu.data.repository.SignUpRepositoryImpl
import com.susu.data.repository.TokenRepositoryImpl
import com.susu.domain.repository.LoginRepository
import com.susu.domain.repository.SignUpRepository
import com.susu.domain.repository.TokenRepository
import dagger.Binds
import dagger.Module
Expand All @@ -15,4 +19,14 @@ abstract class RepositoryModule {
abstract fun bindTokenRepository(
tokenRepositoryImpl: TokenRepositoryImpl,
): TokenRepository

@Binds
abstract fun bindSignUpRepository(
signUpRepositoryImpl: SignUpRepositoryImpl,
): SignUpRepository

@Binds
abstract fun bindLoginRepository(
loginRepositoryImpl: LoginRepositoryImpl,
): LoginRepository
}
34 changes: 34 additions & 0 deletions data/src/main/java/com/susu/data/di/ServiceModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.susu.data.di

import com.susu.data.network.service.SignUpService
import com.susu.data.network.service.TokenService
import com.susu.data.network.service.UserService
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object ServiceModule {

@Singleton
@Provides
fun provideUserService(retrofit: Retrofit): UserService {
return retrofit.create(UserService::class.java)
}

@Singleton
@Provides
fun provideSignUpService(retrofit: Retrofit): SignUpService {
return retrofit.create(SignUpService::class.java)
}

@Singleton
@Provides
fun provideTokenService(@AuthRetrofit retrofit: Retrofit): TokenService {
return retrofit.create(TokenService::class.java)
}
}
35 changes: 0 additions & 35 deletions data/src/main/java/com/susu/data/extension/DataStoreExtension.kt

This file was deleted.

5 changes: 5 additions & 0 deletions data/src/main/java/com/susu/data/model/SnsProviders.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.susu.data.model

enum class SnsProviders(val path: String) {
Kakao("KAKAO"),
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.susu.data.model.request

import kotlinx.serialization.Serializable

@Serializable
data class AccessTokenRequest(
val accessToken: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.susu.data.model.request

import kotlinx.serialization.Serializable

@Serializable
data class RefreshTokenRequest(
val refreshToken: String,
)
Loading

0 comments on commit 89dd447

Please sign in to comment.