From f6524f085661469deaf3e2d3612e0f731540f171 Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Mon, 15 Apr 2024 13:07:38 +0200 Subject: [PATCH 1/2] Always call refreshToken --- .../fr/paug/androidmakers/MainActivity.kt | 3 ++- gradle/libs.versions.toml | 1 + .../graphql/ApolloClientBuilder.android.kt | 2 +- .../store/firebase/FirebaseUserRepository.kt | 20 ++++++++++++++++--- .../androidmakers/store/firebase/mappers.kt | 2 +- .../fr/androidmakers/domain/model/User.kt | 4 ---- .../domain/repo/UserRepository.kt | 3 ++- .../ui/common/navigation/UserViewModel.kt | 2 ++ .../wear/ui/signin/GoogleSignInViewModel.kt | 3 +-- 9 files changed, 27 insertions(+), 13 deletions(-) diff --git a/androidApp/src/main/java/fr/paug/androidmakers/MainActivity.kt b/androidApp/src/main/java/fr/paug/androidmakers/MainActivity.kt index dbd3256f..225da50e 100644 --- a/androidApp/src/main/java/fr/paug/androidmakers/MainActivity.kt +++ b/androidApp/src/main/java/fr/paug/androidmakers/MainActivity.kt @@ -112,7 +112,7 @@ class MainActivity : AppCompatActivity() { val result = auth.signInWithCredential(firebaseCredential) // Sign in success, update UI with the signed-in user's information lifecycleScope.launch { - UserData().userRepository.setUser(result.user?.toUser()) + UserData().userRepository.setUser(result.user) println("user id=${result.user?.uid}") println("idToken=${result.user?.getIdToken(true)}") } @@ -161,3 +161,4 @@ class MainActivity : AppCompatActivity() { } } + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0ef89669..32e4a422 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -38,6 +38,7 @@ apollo-adapters = { module = "com.apollographql.apollo3:apollo-adapters" } apollo-normalized-cache = { module = "com.apollographql.apollo3:apollo-normalized-cache" } apollo-normalized-cache-sqlite = { module = "com.apollographql.apollo3:apollo-normalized-cache-sqlite" } apollo-runtime = { module = "com.apollographql.apollo3:apollo-runtime" } +atomicfu = "org.jetbrains.kotlinx:atomicfu:0.20.1" shared-preferences = "androidx.preference:preference:1.2.1" coil-compose = "io.coil-kt:coil-compose:2.5.0" qdsfdhvh-imageloader = { module = "io.github.qdsfdhvh:image-loader", version.ref = "image-loader" } diff --git a/shared/data/src/androidMain/kotlin/fr/androidmakers/store/graphql/ApolloClientBuilder.android.kt b/shared/data/src/androidMain/kotlin/fr/androidmakers/store/graphql/ApolloClientBuilder.android.kt index 0b0a2fa4..8fca1101 100644 --- a/shared/data/src/androidMain/kotlin/fr/androidmakers/store/graphql/ApolloClientBuilder.android.kt +++ b/shared/data/src/androidMain/kotlin/fr/androidmakers/store/graphql/ApolloClientBuilder.android.kt @@ -35,7 +35,7 @@ actual class ApolloClientBuilder( /** * */ - val token = userRepository.getUser()?.idToken + val token = userRepository.getIdToken() if (token != null) { addHeader("Authorization", "Bearer $token") } diff --git a/shared/data/src/commonMain/kotlin/fr/androidmakers/store/firebase/FirebaseUserRepository.kt b/shared/data/src/commonMain/kotlin/fr/androidmakers/store/firebase/FirebaseUserRepository.kt index b230b5fd..893b4282 100644 --- a/shared/data/src/commonMain/kotlin/fr/androidmakers/store/firebase/FirebaseUserRepository.kt +++ b/shared/data/src/commonMain/kotlin/fr/androidmakers/store/firebase/FirebaseUserRepository.kt @@ -1,9 +1,14 @@ package fr.androidmakers.store.firebase import dev.gitlive.firebase.Firebase +import dev.gitlive.firebase.auth.FirebaseUser import dev.gitlive.firebase.auth.auth import fr.androidmakers.domain.model.User import fr.androidmakers.domain.repo.UserRepository +import kotlinx.atomicfu.AtomicRef +import kotlinx.atomicfu.atomic +import kotlinx.atomicfu.locks.reentrantLock +import kotlinx.atomicfu.locks.withLock import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.flow.MutableStateFlow @@ -11,12 +16,13 @@ import kotlinx.coroutines.launch @OptIn(DelicateCoroutinesApi::class) class FirebaseUserRepository : UserRepository { + private var currentUser = atomic(null) override val user = MutableStateFlow(null) init { GlobalScope.launch { try { - setUser(Firebase.auth.currentUser?.toUser()) + setUser(Firebase.auth.currentUser) } catch (e: Exception) { e.printStackTrace() } @@ -27,7 +33,15 @@ class FirebaseUserRepository : UserRepository { return user.value } - override suspend fun setUser(user: User?) { - this.user.emit(user) + override suspend fun getIdToken(): String? { + return currentUser.value?.getIdToken(false) + } + + override suspend fun setUser(user: Any?) { + check(user is FirebaseUser?) { + "Expected FirebaseUser, got '$user'" + } + currentUser.value = user + this.user.emit(user?.toUser()) } } diff --git a/shared/data/src/commonMain/kotlin/fr/androidmakers/store/firebase/mappers.kt b/shared/data/src/commonMain/kotlin/fr/androidmakers/store/firebase/mappers.kt index 249997f2..68fd2f43 100644 --- a/shared/data/src/commonMain/kotlin/fr/androidmakers/store/firebase/mappers.kt +++ b/shared/data/src/commonMain/kotlin/fr/androidmakers/store/firebase/mappers.kt @@ -4,5 +4,5 @@ import dev.gitlive.firebase.auth.FirebaseUser import fr.androidmakers.domain.model.User suspend fun FirebaseUser.toUser(): User { - return User(uid, photoURL, this.getIdToken(false)) + return User(uid, photoURL) } diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/model/User.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/model/User.kt index 8a140844..4de41bee 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/model/User.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/model/User.kt @@ -1,10 +1,6 @@ package fr.androidmakers.domain.model -import okio.Buffer -import okio.ByteString.Companion.decodeBase64 - data class User( val id: String, val photoUrl: String?, - val idToken: String? ) \ No newline at end of file diff --git a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/repo/UserRepository.kt b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/repo/UserRepository.kt index 26fe22e0..909fd37c 100644 --- a/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/repo/UserRepository.kt +++ b/shared/domain/src/commonMain/kotlin/fr/androidmakers/domain/repo/UserRepository.kt @@ -6,5 +6,6 @@ import kotlinx.coroutines.flow.StateFlow interface UserRepository { val user: StateFlow fun getUser(): User? - suspend fun setUser(user: User?) + suspend fun getIdToken(): String? + suspend fun setUser(user: Any?) } diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/common/navigation/UserViewModel.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/common/navigation/UserViewModel.kt index 024319ff..90d875f3 100644 --- a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/common/navigation/UserViewModel.kt +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/common/navigation/UserViewModel.kt @@ -7,3 +7,5 @@ import org.koin.core.component.inject class UserData: KoinComponent { val userRepository: UserRepository by inject() } + + diff --git a/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/signin/GoogleSignInViewModel.kt b/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/signin/GoogleSignInViewModel.kt index e110a3e9..2a10a103 100644 --- a/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/signin/GoogleSignInViewModel.kt +++ b/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/signin/GoogleSignInViewModel.kt @@ -38,7 +38,7 @@ class GoogleSignInViewModel( try { val credential = GoogleAuthProvider.getCredential(idToken!!, null) Firebase.auth.signInWithCredential(credential).await() - UserData().userRepository.setUser(Firebase.auth.currentUser?.toUser()) + UserData().userRepository.setUser(Firebase.auth.currentUser) onSignInSuccess() } catch (e: FirebaseAuthException) { Log.w(TAG, "Could not get Firebase auth credential from Google id token", e) @@ -53,7 +53,6 @@ private suspend fun FirebaseUser.toUser(): User { return User( id = this.uid, photoUrl = this.photoUrl.toString(), - idToken = this.getIdToken(true).await().token ) } From 067290df967fa732299cf86aaf60c7bc61506dca Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Mon, 15 Apr 2024 13:16:24 +0200 Subject: [PATCH 2/2] add atomicfu --- shared/data/build.gradle.kts | 1 + .../fr/androidmakers/store/firebase/FirebaseUserRepository.kt | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/shared/data/build.gradle.kts b/shared/data/build.gradle.kts index 7f862a22..f946abda 100644 --- a/shared/data/build.gradle.kts +++ b/shared/data/build.gradle.kts @@ -25,6 +25,7 @@ kotlin { implementation(libs.apollo.normalized.cache.sqlite) implementation(libs.apollo.normalized.cache) + implementation(libs.atomicfu) implementation(libs.androidx.datastore.preferences.core) api(libs.androidx.datastore.preferences) diff --git a/shared/data/src/commonMain/kotlin/fr/androidmakers/store/firebase/FirebaseUserRepository.kt b/shared/data/src/commonMain/kotlin/fr/androidmakers/store/firebase/FirebaseUserRepository.kt index 893b4282..2cdd2df1 100644 --- a/shared/data/src/commonMain/kotlin/fr/androidmakers/store/firebase/FirebaseUserRepository.kt +++ b/shared/data/src/commonMain/kotlin/fr/androidmakers/store/firebase/FirebaseUserRepository.kt @@ -5,10 +5,7 @@ import dev.gitlive.firebase.auth.FirebaseUser import dev.gitlive.firebase.auth.auth import fr.androidmakers.domain.model.User import fr.androidmakers.domain.repo.UserRepository -import kotlinx.atomicfu.AtomicRef import kotlinx.atomicfu.atomic -import kotlinx.atomicfu.locks.reentrantLock -import kotlinx.atomicfu.locks.withLock import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.flow.MutableStateFlow