From b25ac87de49fd6326cb954fbf2ab5124ce88ae64 Mon Sep 17 00:00:00 2001 From: gaeun Date: Mon, 4 Sep 2023 20:08:01 +0900 Subject: [PATCH 1/9] =?UTF-8?q?[ADD]=20implement=20dataStore=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index b469ce5b..9b458149 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -108,6 +108,10 @@ dependencies { implementation "com.kakao.sdk:v2-share:2.15.0" // 메시지(카카오톡 공유) //EncryptedSharedPreference implementation "androidx.security:security-crypto-ktx:1.1.0-alpha06" + // dataStore + implementation "androidx.datastore:datastore-preferences-core:1.0.0" + + } // hilt dependency와 함께 추가 kapt { From 54852af8f78ba8710437fbb4c218681168186f40 Mon Sep 17 00:00:00 2001 From: gaeun Date: Tue, 5 Sep 2023 22:00:59 +0900 Subject: [PATCH 2/9] =?UTF-8?q?[FEAT]=20KeyStore=EB=A5=BC=20=EC=9D=B4?= =?UTF-8?q?=EC=9A=A9=ED=95=9C=20=EC=95=94=ED=98=B8=ED=99=94=20service=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../puzzlingaos/data/service/CryptoService.kt | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 app/src/main/java/com/puzzling/puzzlingaos/data/service/CryptoService.kt diff --git a/app/src/main/java/com/puzzling/puzzlingaos/data/service/CryptoService.kt b/app/src/main/java/com/puzzling/puzzlingaos/data/service/CryptoService.kt new file mode 100644 index 00000000..33343104 --- /dev/null +++ b/app/src/main/java/com/puzzling/puzzlingaos/data/service/CryptoService.kt @@ -0,0 +1,83 @@ +package com.puzzling.puzzlingaos.data.service + +import android.os.Build +import android.security.keystore.KeyGenParameterSpec +import android.security.keystore.KeyProperties +import androidx.annotation.RequiresApi +import java.io.InputStream +import java.io.OutputStream +import java.security.KeyStore +import javax.crypto.Cipher +import javax.crypto.KeyGenerator +import javax.crypto.SecretKey +import javax.crypto.spec.IvParameterSpec + +@RequiresApi(Build.VERSION_CODES.M) +class CryptoService { + + private val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { + load(null) + } + + private val encryptCipher = Cipher.getInstance(TRANSFORMATION).apply { + init(Cipher.ENCRYPT_MODE, getKey()) + } + + private fun getDecryptCipher(iv: ByteArray): Cipher { + return Cipher.getInstance(TRANSFORMATION).apply { + init(Cipher.DECRYPT_MODE, getKey(), IvParameterSpec(iv)) + } + } + + private fun getKey(): SecretKey { + val existingKey = keyStore.getEntry("secret", null) as? KeyStore.SecretKeyEntry + return existingKey?.secretKey ?: createKey() + } + + private fun createKey(): SecretKey { + return KeyGenerator.getInstance(ALGORITHM).apply { + init( + KeyGenParameterSpec.Builder( + "secret", + KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT, + ).setBlockModes(BLOCK_MODE).setEncryptionPaddings( + PADDING, + ).setUserAuthenticationRequired(false) // 지문인식 같은거 false + .setRandomizedEncryptionRequired(true).build(), + ) + }.generateKey() + } + + fun encrypt(bytes: ByteArray, outputStream: OutputStream): ByteArray { + val encryptedBytes = encryptCipher.doFinal(bytes) + outputStream.use { + it.write(encryptCipher.iv.size) + it.write(encryptCipher.iv) + it.write(encryptedBytes.size) + it.write(encryptedBytes) + } + + return encryptedBytes + } + + fun decrypt(inputStream: InputStream): ByteArray { + return inputStream.use { + val ivSize = it.read() + val iv = ByteArray(ivSize) + it.read(iv) + + val encryptedBytesSize = it.read() + val encryptedBytes = ByteArray(encryptedBytesSize) + it.read(encryptedBytes) + + getDecryptCipher(iv).doFinal(encryptedBytes) + } + } + + companion object { + private const val ALGORITHM = KeyProperties.KEY_ALGORITHM_AES + private const val BLOCK_MODE = KeyProperties.BLOCK_MODE_CBC + private const val PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7 + private const val TRANSFORMATION = "$ALGORITHM/$BLOCK_MODE/$PADDING" + } +} From f54a1390cc4a7e2fe7b0c7817ef264de13bf5afd Mon Sep 17 00:00:00 2001 From: gaeun Date: Wed, 6 Sep 2023 15:23:34 +0900 Subject: [PATCH 3/9] =?UTF-8?q?[FIX]=20import=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 9b458149..ce889540 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -109,7 +109,7 @@ dependencies { //EncryptedSharedPreference implementation "androidx.security:security-crypto-ktx:1.1.0-alpha06" // dataStore - implementation "androidx.datastore:datastore-preferences-core:1.0.0" + implementation "androidx.datastore:datastore-preferences:1.0.0" } From 94b2f520874bf2092af01dee05810112d7ca1e8e Mon Sep 17 00:00:00 2001 From: gaeun Date: Wed, 6 Sep 2023 15:27:48 +0900 Subject: [PATCH 4/9] =?UTF-8?q?[ADD/#40]=20Token=20entity=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/puzzling/puzzlingaos/data/entity/Token.kt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 app/src/main/java/com/puzzling/puzzlingaos/data/entity/Token.kt diff --git a/app/src/main/java/com/puzzling/puzzlingaos/data/entity/Token.kt b/app/src/main/java/com/puzzling/puzzlingaos/data/entity/Token.kt new file mode 100644 index 00000000..8e9e57fc --- /dev/null +++ b/app/src/main/java/com/puzzling/puzzlingaos/data/entity/Token.kt @@ -0,0 +1,8 @@ +package com.puzzling.puzzlingaos.data.entity + +import kotlinx.serialization.Serializable + +@Serializable +data class Token( + val accessToken: String? = null, +) From 48175958ac51e98c352306bcaeee30a5008619d6 Mon Sep 17 00:00:00 2001 From: gaeun Date: Wed, 6 Sep 2023 15:28:08 +0900 Subject: [PATCH 5/9] =?UTF-8?q?[ADD/#40]=20Token=20dataSource=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/datasource/local/TokenDataSource.kt | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 app/src/main/java/com/puzzling/puzzlingaos/data/datasource/local/TokenDataSource.kt diff --git a/app/src/main/java/com/puzzling/puzzlingaos/data/datasource/local/TokenDataSource.kt b/app/src/main/java/com/puzzling/puzzlingaos/data/datasource/local/TokenDataSource.kt new file mode 100644 index 00000000..26846eb1 --- /dev/null +++ b/app/src/main/java/com/puzzling/puzzlingaos/data/datasource/local/TokenDataSource.kt @@ -0,0 +1,40 @@ +package com.puzzling.puzzlingaos.data.datasource.local + +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.datastore.core.Serializer +import com.puzzling.puzzlingaos.data.entity.Token +import com.puzzling.puzzlingaos.data.service.CryptoService +import kotlinx.serialization.json.Json +import org.apache.commons.lang3.SerializationException +import java.io.InputStream +import java.io.OutputStream + +@RequiresApi(Build.VERSION_CODES.M) +class TokenDataSource(private val cryptoService: CryptoService) : Serializer { + override val defaultValue: Token + get() = Token() + + override suspend fun readFrom(input: InputStream): Token { + val decryptedBytes = cryptoService.decrypt(input) + return try { + Json.decodeFromString( + deserializer = Token.serializer(), + string = decryptedBytes.decodeToString(), + ) + } catch (e: SerializationException) { + e.printStackTrace() + defaultValue + } + } + + override suspend fun writeTo(t: Token, output: OutputStream) { + cryptoService.encrypt( + bytes = Json.encodeToString( + serializer = Token.serializer(), + value = t, + ).encodeToByteArray(), + outputStream = output, + ) + } +} From 57e4c46afeead78a0922becbd4fe75a9dee99b44 Mon Sep 17 00:00:00 2001 From: gaeun Date: Sat, 23 Sep 2023 23:58:08 +0900 Subject: [PATCH 6/9] =?UTF-8?q?[FEAT/#40]=20encrypted=20datastore=20data?= =?UTF-8?q?=20layer=EA=B9=8C=EC=A7=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/datasource/local/TokenDataSource.kt | 3 +- .../data/repository/TokenRepositoryImpl.kt | 16 +++++++++ .../puzzlingaos/data/service/CryptoService.kt | 3 +- .../puzzlingaos/di/DataStoreModule.kt | 35 +++++++++++++++++++ .../puzzlingaos/di/RepositoryModule.kt | 16 ++++----- .../domain/repository/TokenRepository.kt | 9 +++++ 6 files changed, 70 insertions(+), 12 deletions(-) create mode 100644 app/src/main/java/com/puzzling/puzzlingaos/data/repository/TokenRepositoryImpl.kt create mode 100644 app/src/main/java/com/puzzling/puzzlingaos/di/DataStoreModule.kt create mode 100644 app/src/main/java/com/puzzling/puzzlingaos/domain/repository/TokenRepository.kt diff --git a/app/src/main/java/com/puzzling/puzzlingaos/data/datasource/local/TokenDataSource.kt b/app/src/main/java/com/puzzling/puzzlingaos/data/datasource/local/TokenDataSource.kt index 26846eb1..e3f3db63 100644 --- a/app/src/main/java/com/puzzling/puzzlingaos/data/datasource/local/TokenDataSource.kt +++ b/app/src/main/java/com/puzzling/puzzlingaos/data/datasource/local/TokenDataSource.kt @@ -9,9 +9,10 @@ import kotlinx.serialization.json.Json import org.apache.commons.lang3.SerializationException import java.io.InputStream import java.io.OutputStream +import javax.inject.Inject @RequiresApi(Build.VERSION_CODES.M) -class TokenDataSource(private val cryptoService: CryptoService) : Serializer { +class TokenDataSource @Inject constructor(private val cryptoService: CryptoService) : Serializer { override val defaultValue: Token get() = Token() diff --git a/app/src/main/java/com/puzzling/puzzlingaos/data/repository/TokenRepositoryImpl.kt b/app/src/main/java/com/puzzling/puzzlingaos/data/repository/TokenRepositoryImpl.kt new file mode 100644 index 00000000..e2f9412a --- /dev/null +++ b/app/src/main/java/com/puzzling/puzzlingaos/data/repository/TokenRepositoryImpl.kt @@ -0,0 +1,16 @@ +package com.puzzling.puzzlingaos.data.repository + +import androidx.datastore.core.DataStore +import com.puzzling.puzzlingaos.data.entity.Token +import com.puzzling.puzzlingaos.domain.repository.TokenRepository +import kotlinx.coroutines.flow.first +import javax.inject.Inject + +class TokenRepositoryImpl @Inject constructor(private val dataStore: DataStore) : + TokenRepository { + override suspend fun setToken(token: String) { + dataStore.updateData { Token(token) } + } + + override suspend fun getToken(): Token = dataStore.data.first() +} diff --git a/app/src/main/java/com/puzzling/puzzlingaos/data/service/CryptoService.kt b/app/src/main/java/com/puzzling/puzzlingaos/data/service/CryptoService.kt index 33343104..d052fb7a 100644 --- a/app/src/main/java/com/puzzling/puzzlingaos/data/service/CryptoService.kt +++ b/app/src/main/java/com/puzzling/puzzlingaos/data/service/CryptoService.kt @@ -11,9 +11,10 @@ import javax.crypto.Cipher import javax.crypto.KeyGenerator import javax.crypto.SecretKey import javax.crypto.spec.IvParameterSpec +import javax.inject.Inject @RequiresApi(Build.VERSION_CODES.M) -class CryptoService { +class CryptoService @Inject constructor() { private val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) diff --git a/app/src/main/java/com/puzzling/puzzlingaos/di/DataStoreModule.kt b/app/src/main/java/com/puzzling/puzzlingaos/di/DataStoreModule.kt new file mode 100644 index 00000000..22a0c10d --- /dev/null +++ b/app/src/main/java/com/puzzling/puzzlingaos/di/DataStoreModule.kt @@ -0,0 +1,35 @@ +package com.puzzling.puzzlingaos.di + +import android.content.Context +import androidx.datastore.core.DataStore +import androidx.datastore.core.DataStoreFactory +import androidx.datastore.dataStoreFile +import com.puzzling.puzzlingaos.data.datasource.local.TokenDataSource +import com.puzzling.puzzlingaos.data.entity.Token +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 + +@Module +@InstallIn(SingletonComponent::class) +object DataStoreModule { + private const val USER_PREFERENCES_NAME = "user_preferences" + private const val DATA_STORE_FILE_NAME = "user_prefs.pb" + + @Provides + @Singleton + fun providePreferencesDataStore( + @ApplicationContext appContext: Context, + tokenDataSource: TokenDataSource, + ): DataStore { + return DataStoreFactory.create( + serializer = tokenDataSource, + produceFile = { + appContext.dataStoreFile(DATA_STORE_FILE_NAME) + }, + ) + } +} diff --git a/app/src/main/java/com/puzzling/puzzlingaos/di/RepositoryModule.kt b/app/src/main/java/com/puzzling/puzzlingaos/di/RepositoryModule.kt index 84f96457..8f0f8594 100644 --- a/app/src/main/java/com/puzzling/puzzlingaos/di/RepositoryModule.kt +++ b/app/src/main/java/com/puzzling/puzzlingaos/di/RepositoryModule.kt @@ -1,15 +1,7 @@ package com.puzzling.puzzlingaos.di -import com.puzzling.puzzlingaos.data.repository.MyBoardRepositoryImpl -import com.puzzling.puzzlingaos.data.repository.MyPageRepositoryImpl -import com.puzzling.puzzlingaos.data.repository.ProjectRepositoryImpl -import com.puzzling.puzzlingaos.data.repository.TeamDashBoardRepositoryImpl -import com.puzzling.puzzlingaos.data.repository.WriteReviewRepositoryImpl -import com.puzzling.puzzlingaos.domain.repository.MyBoardRepository -import com.puzzling.puzzlingaos.domain.repository.MyPageRepository -import com.puzzling.puzzlingaos.domain.repository.ProjectRepository -import com.puzzling.puzzlingaos.domain.repository.TeamDashBoardRepository -import com.puzzling.puzzlingaos.domain.repository.WriteReviewRepository +import com.puzzling.puzzlingaos.data.repository.* +import com.puzzling.puzzlingaos.domain.repository.* import dagger.Binds import dagger.Module import dagger.hilt.InstallIn @@ -38,4 +30,8 @@ abstract class RepositoryModule { @Singleton @Binds abstract fun providesWriteReviewRepository(repoImpl: WriteReviewRepositoryImpl): WriteReviewRepository + + @Singleton + @Binds + abstract fun providesTokenRepository(repoImpl: TokenRepositoryImpl): TokenRepository } diff --git a/app/src/main/java/com/puzzling/puzzlingaos/domain/repository/TokenRepository.kt b/app/src/main/java/com/puzzling/puzzlingaos/domain/repository/TokenRepository.kt new file mode 100644 index 00000000..93f43adb --- /dev/null +++ b/app/src/main/java/com/puzzling/puzzlingaos/domain/repository/TokenRepository.kt @@ -0,0 +1,9 @@ +package com.puzzling.puzzlingaos.domain.repository + +import com.puzzling.puzzlingaos.data.entity.Token + +interface TokenRepository { + suspend fun setToken(token: String) + + suspend fun getToken(): Token +} From d0c98a4cb9645e19abf606682fe85715f419ac9d Mon Sep 17 00:00:00 2001 From: gaeun Date: Sun, 24 Sep 2023 23:51:28 +0900 Subject: [PATCH 7/9] =?UTF-8?q?[RENAME]=20Login=20->=20Auth=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/{KakaoLoginService.kt => KakaoAuthService.kt} | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) rename app/src/main/java/com/puzzling/puzzlingaos/data/service/{KakaoLoginService.kt => KakaoAuthService.kt} (88%) diff --git a/app/src/main/java/com/puzzling/puzzlingaos/data/service/KakaoLoginService.kt b/app/src/main/java/com/puzzling/puzzlingaos/data/service/KakaoAuthService.kt similarity index 88% rename from app/src/main/java/com/puzzling/puzzlingaos/data/service/KakaoLoginService.kt rename to app/src/main/java/com/puzzling/puzzlingaos/data/service/KakaoAuthService.kt index 335dee3c..4480d182 100644 --- a/app/src/main/java/com/puzzling/puzzlingaos/data/service/KakaoLoginService.kt +++ b/app/src/main/java/com/puzzling/puzzlingaos/data/service/KakaoAuthService.kt @@ -3,8 +3,10 @@ package com.puzzling.puzzlingaos.data.service import android.content.Context import com.kakao.sdk.auth.model.OAuthToken import com.kakao.sdk.user.UserApiClient +import dagger.hilt.android.qualifiers.ActivityContext +import javax.inject.Inject -class KakaoLoginService(private val context: Context) { +class KakaoAuthService @Inject constructor(@ActivityContext private val context: Context) { fun startKakaoLogin(kakaoLoginCallBack: (OAuthToken?, Throwable?) -> Unit) { val kakaoLoginState = if (UserApiClient.instance.isKakaoTalkLoginAvailable(context)) { @@ -20,6 +22,7 @@ class KakaoLoginService(private val context: Context) { callback = kakaoLoginCallBack, ) } + KAKAO_ACCOUNT_LOGIN -> { UserApiClient.instance.loginWithKakaoAccount( context, From d58bfa7f21f1eb60d90e035d30bc85cf57ea95e8 Mon Sep 17 00:00:00 2001 From: gaeun Date: Sun, 24 Sep 2023 23:53:06 +0900 Subject: [PATCH 8/9] =?UTF-8?q?[FEAT/#40]=20kakaoLogin=20DI=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/onboarding/LoginActivity.kt | 16 ++++++++++++---- .../presentation/onboarding/LoginViewModel.kt | 17 +++++++---------- .../puzzlingaos/util/ViewModelFactory.kt | 11 ++++------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/puzzling/puzzlingaos/presentation/onboarding/LoginActivity.kt b/app/src/main/java/com/puzzling/puzzlingaos/presentation/onboarding/LoginActivity.kt index 774d492d..bbfd50df 100644 --- a/app/src/main/java/com/puzzling/puzzlingaos/presentation/onboarding/LoginActivity.kt +++ b/app/src/main/java/com/puzzling/puzzlingaos/presentation/onboarding/LoginActivity.kt @@ -2,19 +2,27 @@ package com.puzzling.puzzlingaos.presentation.onboarding import android.content.Intent import android.os.Bundle +import android.util.Log import androidx.activity.viewModels import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import com.puzzling.puzzlingaos.R import com.puzzling.puzzlingaos.base.BaseActivity +import com.puzzling.puzzlingaos.data.service.KakaoAuthService import com.puzzling.puzzlingaos.databinding.ActivityLoginBinding -import com.puzzling.puzzlingaos.util.ViewModelFactory +import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch +import javax.inject.Inject +@AndroidEntryPoint class LoginActivity : BaseActivity(R.layout.activity_login) { - private val viewModel: LoginViewModel by viewModels { ViewModelFactory(this) } + @Inject + lateinit var kakakoAuthService: KakaoAuthService + + private val viewModel: LoginViewModel by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -24,13 +32,13 @@ class LoginActivity : BaseActivity(R.layout.activity_login private fun startKakaoLogin() { binding.ibLoginKakao.setOnClickListener { - viewModel.kakaoLogin() + kakakoAuthService.startKakaoLogin(viewModel.kakaoLoginCallback) } } private fun isKakaoLoginSuccess() { lifecycleScope.launch { - repeatOnLifecycle(Lifecycle.State.RESUMED) { + repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.isKakaoLogin.collect { isLoginSuccess -> if (isLoginSuccess) { val intent = diff --git a/app/src/main/java/com/puzzling/puzzlingaos/presentation/onboarding/LoginViewModel.kt b/app/src/main/java/com/puzzling/puzzlingaos/presentation/onboarding/LoginViewModel.kt index 67a747c0..0a8030f9 100644 --- a/app/src/main/java/com/puzzling/puzzlingaos/presentation/onboarding/LoginViewModel.kt +++ b/app/src/main/java/com/puzzling/puzzlingaos/presentation/onboarding/LoginViewModel.kt @@ -1,29 +1,26 @@ package com.puzzling.puzzlingaos.presentation.onboarding +import android.util.Log import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope import com.kakao.sdk.auth.model.OAuthToken import com.puzzling.puzzlingaos.data.datasource.local.LocalDataSource -import com.puzzling.puzzlingaos.data.service.KakaoLoginService import com.puzzling.puzzlingaos.util.KakaoLoginCallback +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch -import timber.log.Timber +import javax.inject.Inject -class LoginViewModel(private val kakaoLoginService: KakaoLoginService) : ViewModel() { +@HiltViewModel +class LoginViewModel @Inject constructor() : + ViewModel() { private val _isKakaoLogin = MutableStateFlow(false) val isKakaoLogin = _isKakaoLogin.asStateFlow() val kakaoLoginCallback: (OAuthToken?, Throwable?) -> Unit = { token, error -> KakaoLoginCallback { _isKakaoLogin.value = true - Timber.d("토큰!!!! $token") + Log.d("LoginViewModel", "토큰!! $token") LocalDataSource.setAccessToken("$token") }.handleResult(token, error) } - - fun kakaoLogin() = viewModelScope.launch { - kakaoLoginService.startKakaoLogin(kakaoLoginCallback) - } } diff --git a/app/src/main/java/com/puzzling/puzzlingaos/util/ViewModelFactory.kt b/app/src/main/java/com/puzzling/puzzlingaos/util/ViewModelFactory.kt index 4fbe7331..bf6a5503 100644 --- a/app/src/main/java/com/puzzling/puzzlingaos/util/ViewModelFactory.kt +++ b/app/src/main/java/com/puzzling/puzzlingaos/util/ViewModelFactory.kt @@ -3,9 +3,6 @@ package com.puzzling.puzzlingaos.util import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider -import com.puzzling.puzzlingaos.data.service.KakaoLoginService -import com.puzzling.puzzlingaos.presentation.invitationCode.InvitationCodeViewModel -import com.puzzling.puzzlingaos.presentation.onboarding.LoginViewModel class ViewModelFactory(private val context: Context) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { @@ -14,10 +11,10 @@ class ViewModelFactory(private val context: Context) : ViewModelProvider.Factory // InvitationCodeViewModel(context) as T // } - modelClass.isAssignableFrom(LoginViewModel::class.java) -> { - val repository = KakaoLoginService(context) - LoginViewModel(repository) as T - } +// modelClass.isAssignableFrom(LoginViewModel::class.java) -> { +// val repository = KakaoAuthService(context) +// LoginViewModel(repository) as T +// } else -> { throw java.lang.IllegalArgumentException("Unknown ViewModel") From 9a702554868a2b508bc27937d061bc28ee1a57f4 Mon Sep 17 00:00:00 2001 From: gaeun Date: Tue, 26 Sep 2023 22:20:49 +0900 Subject: [PATCH 9/9] =?UTF-8?q?[FEAT/#40]=20dataStore=20UseCase=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/usecase/onboarding/GetTokenUseCase.kt | 13 +++++++++++++ .../domain/usecase/onboarding/PostTokenUseCase.kt | 10 ++++++++++ .../presentation/onboarding/LoginViewModel.kt | 13 ++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/puzzling/puzzlingaos/domain/usecase/onboarding/GetTokenUseCase.kt create mode 100644 app/src/main/java/com/puzzling/puzzlingaos/domain/usecase/onboarding/PostTokenUseCase.kt diff --git a/app/src/main/java/com/puzzling/puzzlingaos/domain/usecase/onboarding/GetTokenUseCase.kt b/app/src/main/java/com/puzzling/puzzlingaos/domain/usecase/onboarding/GetTokenUseCase.kt new file mode 100644 index 00000000..36875199 --- /dev/null +++ b/app/src/main/java/com/puzzling/puzzlingaos/domain/usecase/onboarding/GetTokenUseCase.kt @@ -0,0 +1,13 @@ +package com.puzzling.puzzlingaos.domain.usecase.onboarding + +import com.puzzling.puzzlingaos.domain.repository.TokenRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetTokenUseCase @Inject constructor( + private val tokenRepository: TokenRepository, +) { + + suspend operator fun invoke() = tokenRepository.getToken() +} diff --git a/app/src/main/java/com/puzzling/puzzlingaos/domain/usecase/onboarding/PostTokenUseCase.kt b/app/src/main/java/com/puzzling/puzzlingaos/domain/usecase/onboarding/PostTokenUseCase.kt new file mode 100644 index 00000000..dcf39d58 --- /dev/null +++ b/app/src/main/java/com/puzzling/puzzlingaos/domain/usecase/onboarding/PostTokenUseCase.kt @@ -0,0 +1,10 @@ +package com.puzzling.puzzlingaos.domain.usecase.onboarding + +import com.puzzling.puzzlingaos.domain.repository.TokenRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class PostTokenUseCase @Inject constructor(private val tokenRepository: TokenRepository) { + suspend operator fun invoke(token: String) = tokenRepository.setToken(token) +} diff --git a/app/src/main/java/com/puzzling/puzzlingaos/presentation/onboarding/LoginViewModel.kt b/app/src/main/java/com/puzzling/puzzlingaos/presentation/onboarding/LoginViewModel.kt index 0a8030f9..6b60acba 100644 --- a/app/src/main/java/com/puzzling/puzzlingaos/presentation/onboarding/LoginViewModel.kt +++ b/app/src/main/java/com/puzzling/puzzlingaos/presentation/onboarding/LoginViewModel.kt @@ -2,16 +2,23 @@ package com.puzzling.puzzlingaos.presentation.onboarding import android.util.Log import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.kakao.sdk.auth.model.OAuthToken import com.puzzling.puzzlingaos.data.datasource.local.LocalDataSource +import com.puzzling.puzzlingaos.domain.usecase.onboarding.GetTokenUseCase +import com.puzzling.puzzlingaos.domain.usecase.onboarding.PostTokenUseCase import com.puzzling.puzzlingaos.util.KakaoLoginCallback import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel -class LoginViewModel @Inject constructor() : +class LoginViewModel @Inject constructor( + private val postTokenUseCase: PostTokenUseCase, + private val getTokenUseCase: GetTokenUseCase, +) : ViewModel() { private val _isKakaoLogin = MutableStateFlow(false) val isKakaoLogin = _isKakaoLogin.asStateFlow() @@ -21,6 +28,10 @@ class LoginViewModel @Inject constructor() : _isKakaoLogin.value = true Log.d("LoginViewModel", "토큰!! $token") LocalDataSource.setAccessToken("$token") + viewModelScope.launch { + postTokenUseCase.invoke(it) + Log.d("LoginViewModel", "토큰!! usecase ${getTokenUseCase.invoke()}") + } }.handleResult(token, error) } }