Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/mz 150 kakao login #19

Merged
merged 60 commits into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from 59 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
d7cf053
chore: Timber Tree 심기
yangsooplus Dec 20, 2023
9e628a0
feat: kakao user sdk 설정
yangsooplus Dec 20, 2023
c7fabab
feat: SplashContract 정의 후 SplashViewModel 구현
yangsooplus Dec 20, 2023
136f96f
feat: kakao login 구현
yangsooplus Dec 21, 2023
2570023
feat: 수수 auth api 인증
yangsooplus Dec 21, 2023
7001066
refactor: domain에 KakaoLoginProvider 인터페이스 추가
yangsooplus Dec 21, 2023
10497e5
fix: 수수 auth 관련 누락 파일 추가
yangsooplus Dec 21, 2023
2f08e65
fix: 잘못 입력한 api 명세 수정
yangsooplus Dec 21, 2023
1af5735
fix: api 변경에 따른 user 프로퍼티 변경
yangsooplus Dec 21, 2023
5c04416
feat: SplashViewModel 수수 토큰 로직 추가
yangsooplus Dec 21, 2023
f7cdfbd
refactor: TokenRepository 저장 시 파라미터로 Token 사용
yangsooplus Dec 21, 2023
a08f9d7
chore: AuthRepository.kt -> AuthRepositoryImpl.kt rename
yangsooplus Dec 21, 2023
323935e
chore: KakaoLoginProvider.kt -> KakaoLoginProviderImpl.kt rename
yangsooplus Dec 21, 2023
732dba5
feat: LoginContract, LoginViewModel 추가
yangsooplus Dec 21, 2023
e6ae3c3
feat: Kakao di Module 추가
yangsooplus Dec 21, 2023
0a42e76
chore: feature plugin에 hilt.navigation.compose 의존성 추가
yangsooplus Dec 21, 2023
230df72
fix: Repository di 불가 오류 해결
yangsooplus Dec 22, 2023
2b9d07e
feat: 카카오 accessToken 접근 코드 추가
yangsooplus Dec 22, 2023
2972865
refactor: Splash와 Login을 Login에 통합
yangsooplus Dec 22, 2023
765bc7f
fix: Authenticator를 token 재발행을 authRepository로 이동함에 따라 수정
yangsooplus Dec 22, 2023
9e17f10
feat: 기능 테스트 UI 추가
yangsooplus Dec 22, 2023
5f72d06
fix: hilt 순환 참조 제거
yangsooplus Dec 22, 2023
6960045
chore: 카카오 로그인 테스트용 로그 추가
yangsooplus Dec 22, 2023
7a2867e
fix: api 명세 형식 틀린 부분 수정
yangsooplus Dec 22, 2023
5bcd5dd
fix: ActivityContext가 필요한 로그인 동작을 분리
yangsooplus Dec 22, 2023
cebb823
fix: token 저장을 완료할 때까지 대기
yangsooplus Dec 26, 2023
7f09a87
refactor: encrpted-datastore로 교체
yangsooplus Dec 26, 2023
2cc691a
fix: kakao token 만료 체크 후 수수 로그인 시도하도록 수정
yangsooplus Dec 26, 2023
5d533b9
feat: ApiService에 수수 회원 탈퇴 추가
yangsooplus Dec 26, 2023
ca2e3f5
feat: login, signup nested navigation 지정
yangsooplus Dec 26, 2023
286ac14
fix: 수수 토큰 헤더 형식 수정
yangsooplus Dec 26, 2023
2c8aad0
feat: 기능 테스트를 위한 임시 UI 코드
yangsooplus Dec 26, 2023
04d9e01
chore: hilt-navigation-compose 의존성 위치 변경
yangsooplus Dec 26, 2023
1a7748d
chore: kakao sdk 관련 파일 social 패키지로 이동
yangsooplus Dec 26, 2023
08dde4e
chore: 기존 암호화 DataStore 코드 삭제
yangsooplus Dec 26, 2023
076999a
chore: detekt 형식 맞춤
yangsooplus Dec 26, 2023
98c82af
chore: gitignore에 report, google-service.json 추가
yangsooplus Dec 26, 2023
3d4db6c
chore: ktlint trailing comma check
yangsooplus Dec 26, 2023
66a84c9
chore: ktlint Import order check
yangsooplus Dec 26, 2023
3a3a014
chore: local.properties로 카카오 앱 키 이동
yangsooplus Dec 31, 2023
74f23eb
fix: merge하며 누락된 plugin 복구
yangsooplus Dec 31, 2023
1dc7860
feat: LoggingInterceptor level 설정 및 di
yangsooplus Dec 31, 2023
84df3e7
refactor: kakao sdk 싱글톤 교체 및 di 코드 삭제
yangsooplus Dec 31, 2023
2e18684
refactor: NetworkModule에서 service 분리
yangsooplus Dec 31, 2023
af6d54f
refactor: Service 네이밍 수정
yangsooplus Dec 31, 2023
5d585ab
chore: Contract 타입 class -> sealed interface
yangsooplus Dec 31, 2023
6128d67
chore: sns -> oauth 네이밍 변경
yangsooplus Dec 31, 2023
9f16e97
chore: gitignore에 idea 폴더 추가
yangsooplus Dec 31, 2023
67a4348
refactor: TokenEntity -> TokenResponse 네이밍 변경과 유효기간 프로퍼티 제거
yangsooplus Jan 2, 2024
449c04c
refactor: UserEntity -> UserRequest
yangsooplus Jan 2, 2024
4ad776b
refactor: AuthRepository를 Login과 SignUp으로 분리
yangsooplus Jan 2, 2024
722b085
refactor: 로그인/회원가입 동작 관련 Usecase 추가
yangsooplus Jan 2, 2024
60675d5
feat: SplashScreen Api 적용
yangsooplus Jan 2, 2024
5f5b40e
feat: 앱 실행 데이터 작업 중에 SplashScreen을 계속 보이도록 설정
yangsooplus Jan 2, 2024
e21b8a0
feat: Splash를 보여주고 난 뒤, 유저 데이터에 따라 화면 이동
yangsooplus Jan 2, 2024
8928f59
refactor: TestScreen의 동작을 MyPage로 옮김
yangsooplus Jan 2, 2024
846ade5
feat: 카카오 로그인 후 회원가입 이탈 유저는 회원가입 화면으로 이동
yangsooplus Jan 2, 2024
d4e1d00
chore: detekt가 apiKey를 불러올 때 null check 무시
yangsooplus Jan 2, 2024
d0c87bb
fix: 카카오계정 로그인 후 진행 안되는 문제 수정
yangsooplus Jan 2, 2024
d6f69ac
chore: detekt 수정사항 반영
yangsooplus Jan 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
}
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">
yangsooplus marked this conversation as resolved.
Show resolved Hide resolved
<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()
yangsooplus marked this conversation as resolved.
Show resolved Hide resolved

@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.UserService
import com.susu.data.network.service.TokenService
import com.susu.data.network.service.SignUpService
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
Loading