diff --git a/firebase-auth/api/android/firebase-auth.api b/firebase-auth/api/android/firebase-auth.api index a5ac17791..d997bf223 100644 --- a/firebase-auth/api/android/firebase-auth.api +++ b/firebase-auth/api/android/firebase-auth.api @@ -51,6 +51,14 @@ public final class dev/gitlive/firebase/auth/ActionCodeSettings { public fun toString ()Ljava/lang/String; } +public final class dev/gitlive/firebase/auth/AdditionalUserInfo { + public fun (Lcom/google/firebase/auth/AdditionalUserInfo;)V + public final fun getProfile ()Ljava/util/Map; + public final fun getProviderId ()Ljava/lang/String; + public final fun getUsername ()Ljava/lang/String; + public final fun isNewUser ()Z +} + public final class dev/gitlive/firebase/auth/AndroidPackageName { public fun (Ljava/lang/String;ZLjava/lang/String;)V public synthetic fun (Ljava/lang/String;ZLjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -74,6 +82,9 @@ public class dev/gitlive/firebase/auth/AuthCredential { } public final class dev/gitlive/firebase/auth/AuthResult { + public fun (Lcom/google/firebase/auth/AuthResult;)V + public final fun getAdditionalUserInfo ()Ldev/gitlive/firebase/auth/AdditionalUserInfo; + public final fun getCredential ()Ldev/gitlive/firebase/auth/AuthCredential; public final fun getUser ()Ldev/gitlive/firebase/auth/FirebaseUser; } @@ -278,6 +289,7 @@ public final class dev/gitlive/firebase/auth/UserMetaData { public final class dev/gitlive/firebase/auth/android { public static final fun auth (Ldev/gitlive/firebase/Firebase;Ldev/gitlive/firebase/FirebaseApp;)Ldev/gitlive/firebase/auth/FirebaseAuth; + public static final fun getAndroid (Ldev/gitlive/firebase/auth/AdditionalUserInfo;)Lcom/google/firebase/auth/AdditionalUserInfo; public static final fun getAndroid (Ldev/gitlive/firebase/auth/AuthResult;)Lcom/google/firebase/auth/AuthResult; public static final fun getAndroid (Ldev/gitlive/firebase/auth/AuthTokenResult;)Lcom/google/firebase/auth/GetTokenResult; public static final fun getAndroid (Ldev/gitlive/firebase/auth/FirebaseAuth;)Lcom/google/firebase/auth/FirebaseAuth; diff --git a/firebase-auth/api/jvm/firebase-auth.api b/firebase-auth/api/jvm/firebase-auth.api index 170ac9afa..f629f1f01 100644 --- a/firebase-auth/api/jvm/firebase-auth.api +++ b/firebase-auth/api/jvm/firebase-auth.api @@ -51,6 +51,14 @@ public final class dev/gitlive/firebase/auth/ActionCodeSettings { public fun toString ()Ljava/lang/String; } +public final class dev/gitlive/firebase/auth/AdditionalUserInfo { + public fun ()V + public final fun getProfile ()Ljava/util/Map; + public final fun getProviderId ()Ljava/lang/String; + public final fun getUsername ()Ljava/lang/String; + public final fun isNewUser ()Z +} + public final class dev/gitlive/firebase/auth/AndroidPackageName { public fun (Ljava/lang/String;ZLjava/lang/String;)V public synthetic fun (Ljava/lang/String;ZLjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -74,6 +82,9 @@ public class dev/gitlive/firebase/auth/AuthCredential { } public final class dev/gitlive/firebase/auth/AuthResult { + public fun (Lcom/google/firebase/auth/AuthResult;)V + public final fun getAdditionalUserInfo ()Ldev/gitlive/firebase/auth/AdditionalUserInfo; + public final fun getCredential ()Ldev/gitlive/firebase/auth/AuthCredential; public final fun getUser ()Ldev/gitlive/firebase/auth/FirebaseUser; } diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt index fec2e73a0..cc4f2957d 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt @@ -118,9 +118,29 @@ public actual class FirebaseAuth internal constructor(internal val android: com. public val AuthResult.android: com.google.firebase.auth.AuthResult get() = android -public actual class AuthResult internal constructor(internal val android: com.google.firebase.auth.AuthResult) { +public actual class AuthResult(internal val android: com.google.firebase.auth.AuthResult) { public actual val user: FirebaseUser? get() = android.user?.let { FirebaseUser(it) } + public actual val credential: AuthCredential? + get() = android.credential?.let { AuthCredential(it) } + public actual val additionalUserInfo: AdditionalUserInfo? + get() = android.additionalUserInfo?.let { AdditionalUserInfo(it) } +} + +public val AdditionalUserInfo.android: com.google.firebase.auth.AdditionalUserInfo + get() = android + +public actual class AdditionalUserInfo( + internal val android: com.google.firebase.auth.AdditionalUserInfo, +) { + public actual val providerId: String? + get() = android.providerId + public actual val username: String? + get() = android.username + public actual val profile: Map? + get() = android.profile + public actual val isNewUser: Boolean + get() = android.isNewUser } public val AuthTokenResult.android: com.google.firebase.auth.GetTokenResult get() = android diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt index f66ce3c03..2665d2eb8 100644 --- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt @@ -41,6 +41,15 @@ public expect class FirebaseAuth { public expect class AuthResult { public val user: FirebaseUser? + public val credential: AuthCredential? + public val additionalUserInfo: AdditionalUserInfo? +} + +public expect class AdditionalUserInfo { + public val providerId: String? + public val username: String? + public val profile: Map? + public val isNewUser: Boolean } public expect class AuthTokenResult { diff --git a/firebase-auth/src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt index 47db21755..96f259176 100644 --- a/firebase-auth/src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt +++ b/firebase-auth/src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt @@ -112,6 +112,22 @@ class FirebaseAuthTest { assertEquals(uid, result.user!!.uid) } + @Test + fun testAuthResultStructure() = runTest { + val uid = getTestUid("test@test.com", "test123") + val result = auth.signInWithEmailAndPassword("test@test.com", "test123") + assertNotNull(result.user, "User does not exist.") + assertEquals(uid, result.user!!.uid, "uid does not match.") + assertNull(result.credential, "Credential throws.") + // Just test if it does not throw + result.additionalUserInfo?.let { additionalUserInfo -> + additionalUserInfo.providerId + additionalUserInfo.username + additionalUserInfo.profile + additionalUserInfo.isNewUser + } + } + @Test fun testIsSignInWithEmailLink() { val validLink = "http://localhost:9099/emulator/action?mode=signIn&lang=en&oobCode=_vr0QcFcxcVeLZbrcU-GpTaZiuxlHquqdC8MSy0YM_vzWCTAQgV9Jq&apiKey=fake-api-key&continueUrl=https%3A%2F%2Fexample.com%2Fsignin" diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt index 30cbc9cf0..30ff27bc1 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt @@ -17,6 +17,7 @@ import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.Flow import platform.Foundation.NSError +import platform.Foundation.NSString import platform.Foundation.NSURL public val FirebaseAuth.ios: FIRAuth get() = FIRAuth.auth() @@ -104,11 +105,39 @@ public actual class FirebaseAuth internal constructor(internal val ios: FIRAuth) public actual fun useEmulator(host: String, port: Int): Unit = ios.useEmulatorWithHost(host, port.toLong()) } + public val AuthResult.ios: FIRAuthDataResult get() = ios -public actual class AuthResult internal constructor(internal val ios: FIRAuthDataResult) { +public actual class AuthResult(internal val ios: FIRAuthDataResult) { public actual val user: FirebaseUser? get() = FirebaseUser(ios.user()) + public actual val credential: AuthCredential? + get() = ios.credential()?.let { AuthCredential(it) } + public actual val additionalUserInfo: AdditionalUserInfo? + get() = ios.additionalUserInfo()?.let { AdditionalUserInfo(it) } +} + +public val AdditionalUserInfo.ios: FIRAdditionalUserInfo get() = ios + +public actual class AdditionalUserInfo( + internal val ios: FIRAdditionalUserInfo, +) { + public actual val providerId: String? + get() = ios.providerID() + public actual val username: String? + get() = ios.username() + public actual val profile: Map? + get() = ios.profile() + ?.mapNotNull { (key, value) -> + if (key is NSString && value != null) { + key.toString() to value + } else { + null + } + } + ?.toMap() + public actual val isNewUser: Boolean + get() = ios.newUser() } public val AuthTokenResult.ios: FIRAuthTokenResult get() = ios diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/auth.kt index a222d4d6e..4d0223d28 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/auth.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/auth.kt @@ -33,8 +33,10 @@ import kotlinx.coroutines.await import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow +import kotlin.js.Json import kotlin.js.json import dev.gitlive.firebase.auth.externals.AuthResult as JsAuthResult +import dev.gitlive.firebase.auth.externals.AdditionalUserInfo as JsAdditionalUserInfo public actual val Firebase.auth: FirebaseAuth get() = rethrow { FirebaseAuth(getAuth()) } @@ -133,9 +135,34 @@ public actual class FirebaseAuth internal constructor(internal val js: Auth) { public val AuthResult.js: JsAuthResult get() = js -public actual class AuthResult internal constructor(internal val js: JsAuthResult) { +public actual class AuthResult(internal val js: JsAuthResult) { public actual val user: FirebaseUser? get() = rethrow { js.user?.let { FirebaseUser(it) } } + public actual val credential: AuthCredential? + get() = rethrow { js.credential?.let { AuthCredential(it) } } + public actual val additionalUserInfo: AdditionalUserInfo? + get() = rethrow { js.additionalUserInfo?.let { AdditionalUserInfo(it) } } +} + +public val AdditionalUserInfo.js: JsAdditionalUserInfo get() = js + +public actual class AdditionalUserInfo( + internal val js: JsAdditionalUserInfo, +) { + public actual val providerId: String? + get() = js.providerId + public actual val username: String? + get() = js.username + public actual val profile: Map? + get() = rethrow { + val profile = js.profile ?: return@rethrow null + val entries = js("Object.entries") as (Json) -> Array> + return@rethrow entries + .invoke(profile) + .associate { entry -> entry[0] as String to entry[1] } + } + public actual val isNewUser: Boolean + get() = js.newUser } public val AuthTokenResult.js: IdTokenResult get() = js diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/externals/auth.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/externals/auth.kt index e535e6c22..20c3f14c3 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/externals/auth.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/externals/auth.kt @@ -170,6 +170,14 @@ public external interface AuthResult { public val credential: AuthCredential? public val operationType: String? public val user: User? + public val additionalUserInfo: AdditionalUserInfo? +} + +public external interface AdditionalUserInfo { + public val providerId: String? + public val username: String? + public val profile: Json? + public val newUser: Boolean } public external interface AuthCredential { diff --git a/firebase-auth/src/jvmMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/jvmMain/kotlin/dev/gitlive/firebase/auth/auth.kt index 3eda71f6b..21043d4d4 100644 --- a/firebase-auth/src/jvmMain/kotlin/dev/gitlive/firebase/auth/auth.kt +++ b/firebase-auth/src/jvmMain/kotlin/dev/gitlive/firebase/auth/auth.kt @@ -18,7 +18,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.tasks.await -public actual val Firebase.auth +public actual val Firebase.auth: FirebaseAuth get() = FirebaseAuth(com.google.firebase.auth.FirebaseAuth.getInstance()) public actual fun Firebase.auth(app: FirebaseApp) = @@ -127,9 +127,24 @@ public actual class FirebaseAuth internal constructor(internal val android: com. public val AuthResult.android: com.google.firebase.auth.AuthResult get() = android -public actual class AuthResult internal constructor(internal val android: com.google.firebase.auth.AuthResult) { +public actual class AuthResult(internal val android: com.google.firebase.auth.AuthResult) { public actual val user: FirebaseUser? get() = android.user?.let { FirebaseUser(it) } + public actual val credential: AuthCredential? + get() = throw NotImplementedError() + public actual val additionalUserInfo: AdditionalUserInfo? + get() = throw NotImplementedError() +} + +public actual class AdditionalUserInfo { + public actual val providerId: String? + get() = throw NotImplementedError() + public actual val username: String? + get() = throw NotImplementedError() + public actual val profile: Map? + get() = throw NotImplementedError() + public actual val isNewUser: Boolean + get() = throw NotImplementedError() } public val AuthTokenResult.android: com.google.firebase.auth.GetTokenResult get() = android